|
|
'use strict';
var brackets = require('expand-brackets'); var define = require('define-property'); var utils = require('./utils');
/** * Characters to use in text regex (we want to "not" match * characters that are matched by other parsers) */
var TEXT_REGEX = '([!@*?+]?\\(|\\)|[*?.+\\\\]|\\[:?(?=.*\\])|:?\\])+'; var not = utils.createRegex(TEXT_REGEX);
/** * Extglob parsers */
function parsers(extglob) { extglob.state = extglob.state || {};
/** * Use `expand-brackets` parsers */
extglob.use(brackets.parsers); extglob.parser.sets.paren = extglob.parser.sets.paren || []; extglob.parser
/** * Extglob open: "*(" */
.capture('paren.open', function() { var parsed = this.parsed; var pos = this.position(); var m = this.match(/^([!@*?+])?\(/); if (!m) return;
var prev = this.prev(); var prefix = m[1]; var val = m[0];
var open = pos({ type: 'paren.open', parsed: parsed, val: val });
var node = pos({ type: 'paren', prefix: prefix, nodes: [open] });
// if nested negation extglobs, just cancel them out to simplify
if (prefix === '!' && prev.type === 'paren' && prev.prefix === '!') { prev.prefix = '@'; node.prefix = '@'; }
define(node, 'rest', this.input); define(node, 'parsed', parsed); define(node, 'parent', prev); define(open, 'parent', node);
this.push('paren', node); prev.nodes.push(node); })
/** * Extglob close: ")" */
.capture('paren.close', function() { var parsed = this.parsed; var pos = this.position(); var m = this.match(/^\)/); if (!m) return;
var parent = this.pop('paren'); var node = pos({ type: 'paren.close', rest: this.input, parsed: parsed, val: m[0] });
if (!this.isType(parent, 'paren')) { if (this.options.strict) { throw new Error('missing opening paren: "("'); } node.escaped = true; return node; }
node.prefix = parent.prefix; parent.nodes.push(node); define(node, 'parent', parent); })
/** * Escape: "\\." */
.capture('escape', function() { var pos = this.position(); var m = this.match(/^\\(.)/); if (!m) return;
return pos({ type: 'escape', val: m[0], ch: m[1] }); })
/** * Question marks: "?" */
.capture('qmark', function() { var parsed = this.parsed; var pos = this.position(); var m = this.match(/^\?+(?!\()/); if (!m) return; extglob.state.metachar = true; return pos({ type: 'qmark', rest: this.input, parsed: parsed, val: m[0] }); })
/** * Character parsers */
.capture('star', /^\*(?!\()/) .capture('plus', /^\+(?!\()/) .capture('dot', /^\./) .capture('text', not); };
/** * Expose text regex string */
module.exports.TEXT_REGEX = TEXT_REGEX;
/** * Extglob parsers */
module.exports = parsers;
|