157 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			157 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| '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;
 |