Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/utils/lib/args.js
diff options
context:
space:
mode:
Diffstat (limited to 'utils/lib/args.js')
-rwxr-xr-xutils/lib/args.js702
1 files changed, 0 insertions, 702 deletions
diff --git a/utils/lib/args.js b/utils/lib/args.js
deleted file mode 100755
index 4c7f450..0000000
--- a/utils/lib/args.js
+++ /dev/null
@@ -1,702 +0,0 @@
-
-var os = require('os');
-var util = require('util');
-var stream = require('term').stream;
-
-exports.Parser = function () {
- this._options = [];
- this._def = {};
- this._long = {};
- this._short = {};
- this._commands = {};
- this._args = [];
- this._vargs = undefined;
-};
-
-exports.Parser.prototype.option = function () {
- var self = this;
- var option = new this.Option(this, arguments);
- this._options.push(option);
- return option;
-};
-
-exports.Parser.prototype.def = function (name, value) {
- this._def[name] = value;
- return this;
-};
-
-exports.Parser.prototype.command = function (name, handler) {
- var parent = this;
- if (!handler) {
- var parser = new exports.Parser();
- this._commands[name] = function () {
- return parser;
- };
- return parser;
- } else if (typeof handler == "string") {
- this._commands[name] = function () {
- return require(handler).parser;
- };
- return;
- } else {
- var parser = new this.Parser();
- parser.action(handler);
- this._commands[name] = function () {
- return parser;
- };
- return parser;
- }
-};
-
-exports.Parser.prototype.arg = function (name) {
- var argument = new exports.Argument(this).name(name);
- this._args.push(argument);
- return argument;
-};
-
-exports.Parser.prototype.args = function (name) {
- var argument = new exports.Argument(this).name(name);
- this._vargs = argument;
- return argument;
-};
-
-exports.Parser.prototype.act = function (args, options) {
- if (!this._action) {
- this.error(options, "Not yet implemented.");
- this.exit(-1);
- }
- options.acted = true;
- this._action.call(this, this.parse(args), options);
-};
-
-exports.Parser.prototype.action = function (action) {
- this._action = action;
- return this;
-};
-
-// should be called last
-exports.Parser.prototype.helpful = function () {
- var self = this;
- this.option('-h', '--help')
- .help('displays usage information')
- .action(function (options) {
- return self.printHelp(options);
- })
- .halt();
- if (util.len(this._commands))
- this.command('help', function (options) {
- self.printHelp(options);
- }).help('displays usage information');
- return this;
-};
-
-exports.Parser.prototype.usage = function (usage) {
- this._usage = usage;
- return this;
-};
-
-exports.Parser.prototype.help = function (help) {
- this._help = help;
- return this;
-};
-
-exports.Parser.prototype.printHelp = function (options) {
- if (options.args.length) {
- util.put(options.args, 1, '--help');
- this._commands[options.args[0]]().act(options.args, options);
- } else {
- this.printUsage(options);
- // todo, parse args for deep help
- if (this._help)
- this.print('\0cyan(\0bold(' + this._help + '\0)\0)');
- this.printCommands(options);
- this.printOptions(options);
- this.exit();
- }
-};
-
-exports.Parser.prototype.printUsage = function (options) {
- this.print(
- 'Usage: \0bold(\0blue(' + system.fs.basename(options.command || '<unknown>') + ' [OPTIONS]' +
- (util.len(this._commands) ?
- ' COMMAND' :
- ''
- ) +
- (util.len(this._args) ?
- ' ' + this._args.map(function (arg) {
- if (arg._optional) {
- return '[' + arg._name.toUpperCase() + ']';
- } else {
- return arg._name.toUpperCase();
- }
- }).join(' ') :
- ''
- ) +
- (this._vargs ?
- ' [' + this._vargs._name.toUpperCase() + ' ...]':
- ''
- ) +
- (this._usage ?
- ' ' + this._usage :
- ''
- ) + "\0)\0)"
- );
-};
-
-exports.Parser.prototype.printCommands = function (options) {
- var self = this;
- util.forEachApply(
- util.items(this._commands),
- function (name, command) {
- var parser = command();
- self.print(' \0bold(\0green(' + name + '\0)\0)' + (
- parser._help ?
- (
- ': ' +
- (
- parser._action?
- '': '\0red(NYI\0): '
- ) +
- parser._help
- ) : ''
- ));
- }
- );
-};
-
-exports.Parser.prototype.printOptions = function (options) {
- var self = this;
- this._options.forEach(function (option) {
- if (option._hidden)
- return;
- var message = [];
- if (option._short.length)
- message.push(option._short.map(function (_short) {
- return ' \0bold(\0green(-' + _short + '\0)\0)';
- }).join(''));
- if (option._long.length)
- message.push(option._long.map(function (_long) {
- return ' \0bold(\0green(--' + _long + '\0)\0)';
- }).join(''));
- if (option._action.length > 2)
- message.push(
- ' ' +
- util.range(option._action.length - 2)
- .map(function () {
- return '\0bold(\0green(' + util.upper(
- option.getName()
- ) + '\0)\0)';
- }).join(' ')
- );
- if (option._help)
- message.push(': ' + option._help + '');
- if (option._choices) {
- var choices = option._choices;
- if (!util.isArrayLike(choices))
- choices = util.keys(choices);
- message.push(' \0bold(\0blue((' + choices.join(', ') + ')\0)\0)');
- }
- if (option._halt)
- message.push(' \0bold(\0blue((final option)\0)\0)');
- self.print(message.join(''));
- });
-};
-
-exports.Parser.prototype.error = function (options, message) {
- if (this._parser) {
- this._parser.error.apply(
- this._parser,
- arguments
- );
- } else {
- this.print('\0red(' + message + '\0)');
- this.exit();
- }
-};
-
-exports.Parser.prototype.exit = function (status) {
- if (this._parser)
- this._parser.exit.apply(
- this._parser,
- arguments
- );
- else {
- os.exit(status);
- throw new Error("exit failed");
- }
-};
-
-exports.Parser.prototype.print = function () {
- if (this._parser)
- this._parser.print.apply(
- this._parser,
- arguments
- );
- else
- stream.print.apply(null, arguments);
-};
-
-exports.Parser.prototype.parse = function (args, options, noCommand) {
- var self = this;
-
- if (!args)
- args = system.args;
- if (!options)
- options = {};
-
- options.args = args;
- if (!noCommand && args.length && !/^-/.test(args[0]))
- options.command = args.shift();
-
- function mandatoryShift(n, name) {
- if (n > args.length) {
- this.error(
- options,
- 'ERROR: The ' + util.enquote(name) +
- ' option requires ' + n + ' arguments.'
- );
- }
- return args.shift(n);
- };
-
- function validate (option, value) {
- try {
- return option._validate.call(self, value);
- } catch (exception) {
- self.error(options, exception);
- }
- };
-
- // initial values
- for (var name in this._def) {
- if (util.has(this._def, name) && !util.has(options, name))
- options[name] = util.copy(this._def[name]);
- }
- this._options.forEach(function (option) {
- if (!util.has(options, option._name))
- options[option._name] = option._def;
- });
-
- // walk args
- ARGS: while (args.length) {
- var arg = args.shift();
- if (arg == "--") {
- break;
-
- } else if (/^--/.test(arg)) {
-
- var pattern = arg.match(/^--([^=]+)(?:=(.*))?/).slice(1);
- var word = pattern[0];
- var value = pattern[1];
-
- if (!!value) {
- args.unshift(value);
- }
-
- if (util.has(this._long, word)) {
-
- var option = this._long[word];
- if (!option._action) {
- self.error(
- options,
- "Programmer error: The " + word +
- " option does not have an associated action."
- );
- }
- if (option._action.length <= 2) {
- option._action.call(
- self,
- options,
- option._name
- );
- } else if (option._action.length <= 3) {
- option._action.apply(
- self,
- [
- options,
- option.getName(),
- validate(option, mandatoryShift.call(
- this,
- Math.max(0, option._action.length - 2),
- word
- ))
- ]
- );
- } else {
- option._action.apply(
- self,
- [
- options,
- option.getName()
- ].concat(
- validate(option, mandatoryShift.call(
- this,
- Math.max(0, option._action.length - 2),
- word
- ))
- )
- );
- }
-
- if (option._halt)
- break ARGS;
-
- } else {
- this.error(options, 'ERROR: Unrecognized option: ' + util.enquote(word));
- }
-
- } else if (/^-/.test(arg)) {
-
- var letters = arg.match(/^-(.*)/)[1].split('');
- while (letters.length) {
- var letter = letters.shift();
- if (util.has(this._short, letter)) {
- var option = this._short[letter];
- if (option._action.length > 2) {
- if (letters.length) {
- option._action.call(
- self,
- options,
- option._name,
- validate(option, letters.join(''))
- );
- letters = '';
- } else {
- option._action.apply(
- self,
- [
- options,
- option._name,
- ].concat(
- validate(option, args.shift(option._action.length - 2))
- )
- );
- }
- } else {
- option._action.call(self, options, option._name);
- }
-
- if (option._halt)
- break ARGS;
-
- } else {
- this.error(options, 'ERROR: unrecognized option: ' + util.enquote(letter));
- }
- }
-
- } else {
- args.unshift(arg);
- break;
- }
-
- }
-
- if (util.len(this._commands)) {
- if (args.length) {
- if (util.has(this._commands, args[0])) {
- var command = this._commands[args[0]];
- command().act(args, options);
- } else {
- this.error(options, 'ERROR: unrecognized command');
- }
- } else {
- this.printHelp(options);
- this.exit(0);
- }
- }
-
- return options;
-};
-
-exports.Argument = function (parser) {
- this._parser = parser;
- return this;
-};
-
-exports.Argument.prototype.name = function (name) {
- this._name = name;
- return this;
-};
-
-exports.Argument.prototype.optional = function () {
- this._optional = true;
- return this;
-};
-
-exports.Option = function (parser, args) {
- var self = this;
- this._parser = parser;
- this._validate = function (value) {
- return value;
- };
- this._long = [];
- this._short = [];
- util.forEach(args, function (arg) {
- if (typeof arg == "function") {
- self.action(arg);
- } else if (typeof arg !== "string") {
- for (var name in arg) {
- var value = arg[name];
- self[name](value);
- }
- } else if (/ /.test(arg)) {
- self.help(arg);
- } else if (/^--/.test(arg)) {
- arg = arg.match(/^--(.*)/)[1];
- self.__(arg);
- } else if (/^-.$/.test(arg)) {
- arg = arg.match(/^-(.)/)[1];
- self._(arg);
- } else if (/^-/.test(arg)) {
- throw new Error("option names with one dash can only have one letter.");
- } else {
- self.name(arg);
- }
- });
- return this;
-};
-
-exports.Option.prototype._ = function (letter) {
- this._short.push(letter);
- this._parser._short[letter] = this;
- return this;
-};
-
-exports.Option.prototype.__ = function (word) {
- this._long.push(word);
- this._parser._long[word] = this;
- return this;
-};
-
-exports.Option.prototype.name = function (name) {
- this._name = name;
- return this;
-};
-
-exports.Option.prototype.getName = function () {
- if (this._name)
- return this._name;
- if (this._long.length);
- return this._long[0]
- if (this._short.length)
- return this._short[0]
- throw new Error("Programmer error: unnamed option");
-};
-
-exports.Option.prototype.action = function (action) {
- var self = this;
- if (typeof action == "string") {
- this._action = self._parser[action];
- } else {
- this._action = action;
- }
- return this;
-};
-
-exports.Option.prototype.set = function (value) {
- var option = this;
- if (arguments.length == 0)
- return this.action(function (options, name, value) {
- options[name] = value;
- });
- else if (arguments.length == 1)
- return this.action(function (options, name) {
- options[name] = value;
- });
- else
- throw new Error("Option().set takes 0 or 1 arguments");
-};
-
-exports.Option.prototype.push = function () {
- var option = this;
- return this.def([]).action(function (options, name, value) {
- options[option._name].push(option._validate.call(
- this,
- value
- ));
- });
-};
-
-exports.Option.prototype.inc = function () {
- return this.def(0).action(function (options, name) {
- options[name]++;
- });
-};
-
-exports.Option.prototype.dec = function () {
- return this.def(0).action(function (options, name) {
- options[name]--;
- });
-};
-
-exports.Option.prototype.choices = function (choices) {
- this.set();
- this._choices = choices;
- var self = this;
- if (util.isArrayLike(choices)) {
- return this.validate(function (value) {
- if (choices.indexOf(value) < 0)
- throw new Error(
- "choice for " + util.upper(self.getName()) +
- " is invalid: " + util.enquote(value) + "\n" +
- "Use one of: " + choices.map(function (choice) {
- return util.enquote(choice);
- }).join(', ')
- );
- return value;
- })
- } else {
- return this.validate(function (value) {
- if (!util.has(choices, value))
- throw new Error(
- "choice for " + util.upper(self.getName()) +
- " is invalid: " + util.enquote(value) + "\n" +
- "Use one of: " + util.keys(choices).map(function (choice) {
- return util.enquote(choice);
- }).join(', ')
- );
- return choices[value];
- });
- }
-};
-
-exports.Option.prototype.def = function (value) {
- if (this._def === undefined)
- this._def = value;
- return this;
-};
-
-exports.Option.prototype.validate = function (validate) {
- this._validate = validate;
- return this;
-};
-
-exports.Option.prototype.input = function () {
- this.set().validate(function (value) {
- if (value == "-")
- return system.stdin;
- else
- return system.fs.open(value, 'r');
- });
-};
-
-exports.Option.prototype.output = function () {
- this.set().validate(function (value) {
- if (value == "-")
- return system.stdout;
- else
- return system.fs.open(value, 'w');
- });
-};
-
-exports.Option.prototype.number = function () {
- return this.set().validate(function (value) {
- var result = +value;
- if (result == NaN)
- throw new Error("not a number");
- return result;
- });
-};
-
-exports.Option.prototype.oct = function () {
- return this.set().validate(function (value) {
- var result = parseInt(value, 8);
- if (result == 0 && +value !== 0)
- throw new Error("not an octal value");
- return result;
- });
-};
-
-exports.Option.prototype.hex = function () {
- return this.set().validate(function (value) {
- var result = parseInt(value, 16);
- if (result == 0 && +value !== 0)
- throw new Error("not an hex value");
- return result;
- });
-};
-
-exports.Option.prototype.integer = function () {
- return this.set().validate(function (value) {
- var result = value >>> 0;
- if (result !== value)
- throw new Error("not an integer");
- return result;
- });
-};
-
-exports.Option.prototype.natural = function () {
- return this.set().validate(function (value) {
- var result = value >>> 0;
- if (result !== +value || result < 0)
- throw new Error("not a natural number");
- return result;
- });
-};
-
-exports.Option.prototype.whole = function () {
- return this.set().validate(function (value) {
- var result = value >>> 0;
- if (result !== +value || result < 1)
- throw new Error("not a whole number");
- return result;
- });
-};
-
-exports.Option.prototype.bool = function (def) {
- if (def === undefined)
- def = true;
- return this.def(!def).set(!!def);
-};
-
-exports.Option.prototype.inverse = function () {
- var args = arguments;
- if (!args.length) {
- args = [];
- this._short.forEach(function (_) {
- args.push('-' + _.toUpperCase());
- });
- this._long.forEach(function (__) {
- args.push('--no-' + __);
- });
- if (this._name)
- args.push(this._name);
- }
- var parser = this._parser;
- var inverse = this._inverse = parser.option.apply(
- parser,
- args
- ).set(!this._def).help('^ inverse');
- return this;
-};
-
-exports.Option.prototype.help = function (text) {
- this._help = text;
- return this;
-};
-
-exports.Option.prototype.halt = function () {
- this._halt = true;
- return this;
-};
-
-exports.Option.prototype.hidden = function () {
- this._hidden = true;
- return this;
-};
-
-exports.Option.prototype.end = function () {
- return this._parser;
-};
-
-exports.Option.prototype.option = function () {
- return this.end().option.apply(this, arguments);
-};
-
-exports.Parser.prototype.end = function () {
- return this._parser;
-};
-
-exports.Parser.prototype.Option = exports.Option;
-exports.Parser.prototype.Parser = exports.Parser;
-