1 | var Parameter, Signature, _, appearedMoreThanOnce, async, isLastOne, parse, settings, utils;
|
2 |
|
3 | _ = require('lodash');
|
4 |
|
5 | _.str = require('underscore.string');
|
6 |
|
7 | async = require('async');
|
8 |
|
9 | Parameter = require('./parameter');
|
10 |
|
11 | settings = require('./settings');
|
12 |
|
13 | parse = require('./parse');
|
14 |
|
15 | utils = require('./utils');
|
16 |
|
17 | isLastOne = function(parameters, predicate) {
|
18 | var lastParameter;
|
19 | lastParameter = _.last(parameters);
|
20 | return predicate(lastParameter);
|
21 | };
|
22 |
|
23 | appearedMoreThanOnce = function(parameters, predicate) {
|
24 | var filteredParameters;
|
25 | filteredParameters = _.filter(parameters, predicate);
|
26 | return filteredParameters.length > 1;
|
27 | };
|
28 |
|
29 | module.exports = Signature = (function() {
|
30 | function Signature(signature) {
|
31 | var isStdin, isVariadic;
|
32 | if ((signature == null) || !_.isString(signature)) {
|
33 | throw new Error('Missing or invalid signature');
|
34 | }
|
35 | this.parameters = [];
|
36 | _.each(parse.split(signature), this._addParameter, this);
|
37 | if (this.allowsStdin()) {
|
38 | isStdin = function(parameter) {
|
39 | return parameter.allowsStdin();
|
40 | };
|
41 | if (appearedMoreThanOnce(this.parameters, isStdin)) {
|
42 | throw new Error('Signature can only contain one stdin parameter');
|
43 | }
|
44 | if (!isLastOne(this.parameters, isStdin)) {
|
45 | throw new Error('The stdin parameter should be the last one');
|
46 | }
|
47 | }
|
48 | if (this.hasVariadicParameters()) {
|
49 | isVariadic = function(parameter) {
|
50 | return parameter.isVariadic();
|
51 | };
|
52 | if (appearedMoreThanOnce(this.parameters, isVariadic)) {
|
53 | throw new Error('Signature can only contain one variadic parameter');
|
54 | }
|
55 | if (!isLastOne(this.parameters, isVariadic)) {
|
56 | throw new Error('The variadic parameter should be the last one');
|
57 | }
|
58 | }
|
59 | }
|
60 |
|
61 | Signature.prototype._addParameter = function(word) {
|
62 | var parameter;
|
63 | parameter = new Parameter(word);
|
64 | return this.parameters.push(parameter);
|
65 | };
|
66 |
|
67 | Signature.prototype.hasParameters = function() {
|
68 | return _.any(this.parameters, function(parameter) {
|
69 | return !parameter.isWord();
|
70 | });
|
71 | };
|
72 |
|
73 | Signature.prototype.hasVariadicParameters = function() {
|
74 | return _.any(this.parameters, function(parameter) {
|
75 | return parameter.isVariadic();
|
76 | });
|
77 | };
|
78 |
|
79 | Signature.prototype.allowsStdin = function() {
|
80 | return _.any(this.parameters, function(parameter) {
|
81 | return parameter.allowsStdin();
|
82 | });
|
83 | };
|
84 |
|
85 | Signature.prototype.toString = function() {
|
86 | var i, len, parameter, ref, result;
|
87 | result = [];
|
88 | ref = this.parameters;
|
89 | for (i = 0, len = ref.length; i < len; i++) {
|
90 | parameter = ref[i];
|
91 | result.push(parameter.toString());
|
92 | }
|
93 | return result.join(' ');
|
94 | };
|
95 |
|
96 | Signature.prototype.isWildcard = function() {
|
97 | return _.all([this.parameters.length === 1, this.parameters[0].toString() === settings.signatures.wildcard]);
|
98 | };
|
99 |
|
100 | Signature.prototype.matches = function(command, callback) {
|
101 | return this.compileParameters(command, function(error) {
|
102 | if (error == null) {
|
103 | return callback(true);
|
104 | }
|
105 | if (_.str.startsWith(error.message, 'Missing')) {
|
106 | return callback(true);
|
107 | }
|
108 | return callback(false);
|
109 | }, false);
|
110 | };
|
111 |
|
112 | Signature.prototype.compileParameters = function(command, callback, performStdin) {
|
113 | var commandWords, comparison, result;
|
114 | if (performStdin == null) {
|
115 | performStdin = true;
|
116 | }
|
117 | commandWords = parse.split(command);
|
118 | comparison = _.zip(this.parameters, commandWords);
|
119 | result = {};
|
120 | if (this.isWildcard()) {
|
121 | return callback(null, result);
|
122 | }
|
123 | return async.eachSeries(comparison, (function(_this) {
|
124 | return function(item, done) {
|
125 | var parameter, parameterIndex, parameterValue, value, word;
|
126 | parameter = item[0];
|
127 | word = item[1];
|
128 | if (parameter == null) {
|
129 | return callback(new Error('Signature dismatch'));
|
130 | }
|
131 | parameterValue = parameter.getValue();
|
132 | if (parameter.allowsStdin() && (word == null)) {
|
133 | if (!performStdin) {
|
134 | return callback(null, result);
|
135 | }
|
136 | return utils.getStdin(function(stdin) {
|
137 | if (parameter.isRequired() && (stdin == null)) {
|
138 | return callback(new Error("Missing " + parameterValue));
|
139 | }
|
140 | if (stdin != null) {
|
141 | result[parameterValue] = stdin;
|
142 | }
|
143 | return callback(null, result);
|
144 | });
|
145 | }
|
146 | if (!parameter.matches(word)) {
|
147 | if (parameter.isRequired()) {
|
148 | return callback(new Error("Missing " + parameterValue));
|
149 | }
|
150 | return callback(new Error(parameterValue + " does not match " + word));
|
151 | }
|
152 | if (parameter.isVariadic()) {
|
153 | parameterIndex = _.indexOf(_this.parameters, parameter);
|
154 | value = _.rest(commandWords, parameterIndex).join(' ');
|
155 | if (parameter.isOptional() && _.isEmpty(value)) {
|
156 | return callback(null, result);
|
157 | }
|
158 | result[parameterValue] = value;
|
159 | return callback(null, result);
|
160 | }
|
161 | if (!parameter.isWord() && (word != null)) {
|
162 | if (/^\d+$/.test(word)) {
|
163 | result[parameterValue] = _.parseInt(word);
|
164 | } else {
|
165 | result[parameterValue] = word;
|
166 | }
|
167 | }
|
168 | return done();
|
169 | };
|
170 | })(this), function(error) {
|
171 | if (error != null) {
|
172 | return callback(error);
|
173 | }
|
174 | return callback(null, result);
|
175 | });
|
176 | };
|
177 |
|
178 | return Signature;
|
179 |
|
180 | })();
|