UNPKG

allume

Version:

A cross-platform package bootloader for javascript.

466 lines (412 loc) 16.1 kB
///////////////////////////////////////////////////////////////////////////////////// // // module 'cc.cli.0.2.0/' // ///////////////////////////////////////////////////////////////////////////////////// (function(using, require) { define.parameters = {}; define.parameters.wrapped = true; define.parameters.system = "pkx"; define.parameters.id = "cc.cli.0.2.0/"; define.parameters.pkx = { "name": "cc.cli", "version": "0.2.0", "title": "CLI Package", "description": "Library for processing command line interface parameters..", "license": "Apache-2.0", "pkx": { "main": "cli.js", "dependencies": [ "cc.string.0.2", "cc.type.0.2" ] } }; define.parameters.dependencies = [ "pkx", "module", "configuration", "requirer" ]; define.parameters.dependencies[0] = define.parameters.pkx; define.parameters.dependencies.push(define.cache.get("cc.string.0.2/")); define.parameters.dependencies.push(define.cache.get("cc.type.0.2/")); using = define.getUsing(define.parameters.id); require = define.getRequire(define.parameters.id, require); ///////////////////////////////////////////////////////////////////////////////////////////// // // cc.cli // // Library for processing command line interface parameters. // // License // Apache License Version 2.0 // // Copyright Nick Verlinden (info@createconform.com) // ///////////////////////////////////////////////////////////////////////////////////////////// var type; var string; var REGEX_MATCH_CLI_HELP = /([-a-zA-Z0-9]+)|\[(.*?)\]|<(.*?)>/g; var REGEX_MATCH_SQBRSPACE = /^( )*\[( )*|( )*\]( )*$/g; var REGEX_MATCH_TRBRSPACE = /^( )*<( )*|( )*>( )*$/g; var OPTION_PREFIX = "--"; var HELP_CMD = "CMD"; var HELP_OPT = "OPT"; var HELP_HINT = "Type '$" + HELP_CMD + " " + OPTION_PREFIX + "help' for detailed information on how to use this command."; var HELP_OPTION = OPTION_PREFIX + "help"; var HELP_MARGIN = Array(4).join(" "); function splitGroups(c) { if (!c) { c = ""; } var params = c.match(REGEX_MATCH_CLI_HELP); var groups = {"raw": [], "words": [], "mandatory": [], "optional": [], "options": []}; for (var p in params) { groups.raw[p] = params[p]; switch (params[p].substr(0, 1)) { case "<": groups.mandatory[p] = params[p].replace(REGEX_MATCH_TRBRSPACE, ""); break; case "-": groups.options[p] = params[p]; break; case "[": groups.optional[p] = params[p].replace(REGEX_MATCH_SQBRSPACE, ""); break; default: groups.words[p] = params[p].replace(REGEX_MATCH_TRBRSPACE, ""); break; } } return groups; } function getUsageParameters(command) { var usage = (command.options && command.options.length > 0 ? " [options]" : "") + (command.commands && command.commands.length > 0 ? " [command]" : ""); for (var m in command.mandatory) { usage += " <" + command.mandatory[m] + ">"; } for (var m in command.optional) { usage += " [" + command.optional[m] + "]"; } return usage; } var TextTable = function (matchTable) { var self = this; var rows = []; var layout = []; var offset = 0; var hSpacing = 3; var vSpacing = 0; this.margin = ""; this.keepRight = 0; this.setHorizontalSpacing = function (s) { hSpacing = s; }; this.setVerticalSpacing = function (s) { vSpacing = s; }; this.getOffset = function (o) { return offset; }; this.setOffset = function (o) { offset = o; self.updateLayout(); }; /* this.matchLayout = function(t) { matchTable = t; };*/ this.setLayout = function (l) { layout = l; /*if (matchTable) { matchTable.setLayout(layout); }*/ }; this.getLayout = function (l) { return layout; }; this.updateLayout = function (columnIdx) { var uRows = self.getRows(true); if (!columnIdx) { columnIdx = 0; } // get length for column var colLength = layout[columnIdx] ? layout[columnIdx] - hSpacing : 0; var hasRows = false; for (var i in uRows) { hasRows = hasRows || uRows[i][columnIdx] || uRows[i][columnIdx] === ""; colLength = uRows[i][columnIdx] && uRows[i][columnIdx].length > colLength ? uRows[i][columnIdx].length : colLength; } if (hasRows) { layout[columnIdx] = colLength + hSpacing; self.updateLayout(columnIdx + 1); } /*if (columnIdx === 0 && matchTable) { matchTable.setLayout(layout); }*/ }; this.getRows = function (withMatchTable) { var uRows = rows.slice(); if (offset > 0 && matchTable) { for (var r in uRows) { var oArr = Array(offset); for (var o in oArr) { oArr[o] = ""; } uRows[r] = oArr.concat(uRows[r]); } /*if (withMatchTable) { uRows = uRows.concat(matchTable.getRows(true)); }*/ } var colLength = 0; for (var u in uRows) { colLength = uRows[u].length > colLength ? uRows[u].length : colLength; } uRows = uRows.map(function (row) { if (row.length < colLength && self.keepRight > 0) { row.splice(row.length - self.keepRight, 0, Array(colLength - row.length)); } return row; }); return uRows; }; this.addRow = function (arr) { rows.push(arr); self.updateLayout(); }; this.print = function (noprint) { var text = ""; var uRows = self.getRows(); for (var r in uRows) { var rowStr = ""; var row = uRows[r]; if (row.length < layout.length && self.keepRight > 0) { var oArr = []; for (var o = 0; o < layout.length - row.length; o++) { oArr = ""; } row.splice(row.length - self.keepRight, 0, oArr); } for (var c = 0; c < row.length; c++) { rowStr += string.padRight(row[c] || "", layout[c] || 0); } text += self.margin + rowStr + (vSpacing > 0 ? Array(vSpacing + 1).join("\n") : "") + "\n"; } if (!noprint) { console.log(text); } return text; }; }; var Option = function (c, description) { var self = this; this.name = c && c.options ? c.options[0] : HELP_OPT; this.description = description; this.mandatory = []; this.optional = []; if (c) { var params = splitGroups(c); self.name = params.options[0] || self.name; self.mandatory = params.mandatory; self.optional = params.optional; } }; var Interpreter = function (c, description, parent) { var self = this; this.name = c && c.words ? c.words[0] : HELP_CMD; this.description = description; this.commands = []; this.options = []; this.mandatory = []; this.optional = []; this.actions = []; if (c) { var params = splitGroups(c); self.name = params.words[0] || self.name; self.mandatory = params.mandatory; self.optional = params.optional; } this.displayHelp = function() { var text = "\nUsage: " + self.getFullName() + getUsageParameters(self) + "\n"; if (self.description) { text += "\n" + self.description + "\n"; } var tableCommands, tableOptions; // initialize table (for matching) if (self.commands.length > 0) { tableCommands = new TextTable(); } if (self.options.length > 0) { tableOptions = new TextTable(); } if (tableCommands) { tableCommands.margin = HELP_MARGIN; for (var c in self.commands) { tableCommands.addRow([self.commands[c].name, getUsageParameters(self.commands[c]), self.commands[c].description]); } } if (tableOptions) { tableOptions = new TextTable(); tableOptions.margin = HELP_MARGIN; for (var c in self.options) { tableOptions.addRow([self.options[c].name, getUsageParameters(self.options[c]), self.options[c].description]); } } if (tableCommands) { text += "\nCommands:\n"; text += tableCommands.print(true); } if (tableOptions) { text += "\nOptions:\n"; text += tableOptions.print(true); } text += "\n"; console.log(text); return text; }; this.getFullName = function () { if (parent) { return parent.getFullName() + " " + self.name; } return self.name; }; this.command = function (c, description) { var params = splitGroups(c); for (var i in self.commands) { if (self.commands[i].name === params.words[0]) { return self.commands[i]; } } var sub = new Interpreter(c, description, self); self.commands.push(sub); return sub; }; this.option = function (c, description) { self.options.push(new Option(c, description)); return self; }; this.parameter = function (c) { if (c) { var params = splitGroups(c); self.name = params.words[0] || self.name; self.mandatory = params.mandatory; self.optional = params.optional; } return self; }; this.action = function (fn) { self.actions.push(fn); return self; }; this.parse = function (args) { if (!args) { args = []; } else if (self.name == HELP_CMD) { // first arg is name of command self.name = args[0]; } var command = {}; // check if help is needed if (args[1] === HELP_OPTION) { return { "--help" : self.displayHelp() }; } // check next argument, if command, invoke parser for (var i in self.commands) { if (self.commands[i].name === args[1]) { command[self.commands[i].name] = self.commands[i].parse(args.slice(1)); return command; } } // start parsing commands command.displayHelp = self.displayHelp; var pIdx = 0; var oIdx = 0; var hint = HELP_HINT.replace("$" + HELP_CMD, self.getFullName()); for (var a = 1; a < args.length; a++) { var argument = a; var match = false; if (args[a].substr(0, 2) === OPTION_PREFIX) { var option; for (var o in self.options) { if (self.options[o].name === args[a]) { match = true; option = args[a]; command[option] = {}; for (var m in self.options[o].mandatory) { a++; if (args[a] && args[a].substr(0, 2) !== OPTION_PREFIX) { command[option][self.options[o].mandatory[m]] = args[a]; } else { console.log("Option '" + option + "' is missing mandatory parameter '" + self.options[o].mandatory[m] + "'. " + hint); return; } } for (var m in self.options[o].optional) { a++; if (args[a] && args[a].substr(0, 2) !== "--") { command[option][self.options[o].optional[m]] = args[a]; } } } } if (option !== args[argument]) { console.log("Invalid option '" + args[argument] + "'. " + hint); return; } } else { var mCount = 0; var mDone = true; for (var m in self.mandatory) { mCount++; if (mCount - 1 < pIdx) { continue; } if (args[a] && args[a].substr(0, 2) !== OPTION_PREFIX) { match = true; command[self.mandatory[m]] = args[a]; pIdx++; } else { console.log("Mandatory parameter '" + self.mandatory[m] + "' is missing. " + hint); return; } mDone = false; break; } var oCount = 0; if (mDone) { for (var m in self.optional) { oCount++; if (oCount - 1 < oIdx) { continue; } if (args[a] && args[a].substr(0, 2) !== OPTION_PREFIX) { match = true; command[self.optional[m]] = args[a]; oIdx++; } break; } } } if (!match) { console.log("Unknown parameter '" + args[a] + "'. " + hint); return; } } for (var a in self.actions) { self.actions[a](command); } return command; }; }; // module factory define(function() { if (!type) { type = require("cc.type"); } if (!string) { string = require("cc.string"); } return new Interpreter(); }); })(typeof using != "undefined"? using : null, typeof require != "undefined"? require : null);