Bez popisu

subparsers.js 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /** internal
  2. * class ActionSubparsers
  3. *
  4. * Support the creation of such sub-commands with the addSubparsers()
  5. *
  6. * This class inherited from [[Action]]
  7. **/
  8. 'use strict';
  9. var util = require('util');
  10. var format = require('util').format;
  11. var _ = require('underscore');
  12. var Action = require('../action');
  13. // Constants
  14. var $$ = require('../const');
  15. // Errors
  16. var argumentErrorHelper = require('../argument/error');
  17. /*:nodoc:*
  18. * new ChoicesPseudoAction(name, help)
  19. *
  20. * Create pseudo action for correct help text
  21. *
  22. **/
  23. var ChoicesPseudoAction = function (name, help) {
  24. var options = {
  25. optionStrings: [],
  26. dest: name,
  27. help: help
  28. };
  29. Action.call(this, options);
  30. };
  31. util.inherits(ChoicesPseudoAction, Action);
  32. /**
  33. * new ActionSubparsers(options)
  34. * - options (object): options hash see [[Action.new]]
  35. *
  36. **/
  37. var ActionSubparsers = module.exports = function ActionSubparsers(options) {
  38. options = options || {};
  39. options.dest = options.dest || $$.SUPPRESS;
  40. options.nargs = $$.PARSER;
  41. this.debug = (options.debug === true);
  42. this._progPrefix = options.prog;
  43. this._parserClass = options.parserClass;
  44. this._nameParserMap = {};
  45. this._choicesActions = [];
  46. options.choices = this._nameParserMap;
  47. Action.call(this, options);
  48. };
  49. util.inherits(ActionSubparsers, Action);
  50. /*:nodoc:*
  51. * ActionSubparsers#addParser(name, options) -> ArgumentParser
  52. * - name (string): sub-command name
  53. * - options (object): see [[ArgumentParser.new]]
  54. *
  55. * Note:
  56. * addParser supports an additional aliases option,
  57. * which allows multiple strings to refer to the same subparser.
  58. * This example, like svn, aliases co as a shorthand for checkout
  59. *
  60. **/
  61. ActionSubparsers.prototype.addParser = function (name, options) {
  62. var parser;
  63. var self = this;
  64. options = options || {};
  65. options.debug = (this.debug === true);
  66. // set program from the existing prefix
  67. if (!options.prog) {
  68. options.prog = this._progPrefix + ' ' + name;
  69. }
  70. var aliases = options.aliases || [];
  71. // create a pseudo-action to hold the choice help
  72. if (!!options.help || _.isString(options.help)) {
  73. var help = options.help;
  74. delete options.help;
  75. var choiceAction = new ChoicesPseudoAction(name, help);
  76. this._choicesActions.push(choiceAction);
  77. }
  78. // create the parser and add it to the map
  79. parser = new this._parserClass(options);
  80. this._nameParserMap[name] = parser;
  81. // make parser available under aliases also
  82. aliases.forEach(function (alias) {
  83. self._nameParserMap[alias] = parser;
  84. });
  85. return parser;
  86. };
  87. ActionSubparsers.prototype._getSubactions = function () {
  88. return this._choicesActions;
  89. };
  90. /*:nodoc:*
  91. * ActionSubparsers#call(parser, namespace, values, optionString) -> Void
  92. * - parser (ArgumentParser): current parser
  93. * - namespace (Namespace): namespace for output data
  94. * - values (Array): parsed values
  95. * - optionString (Array): input option string(not parsed)
  96. *
  97. * Call the action. Parse input aguments
  98. **/
  99. ActionSubparsers.prototype.call = function (parser, namespace, values) {
  100. var parserName = values[0];
  101. var argStrings = values.slice(1);
  102. // set the parser name if requested
  103. if (this.dest !== $$.SUPPRESS) {
  104. namespace[this.dest] = parserName;
  105. }
  106. // select the parser
  107. if (!!this._nameParserMap[parserName]) {
  108. parser = this._nameParserMap[parserName];
  109. } else {
  110. throw argumentErrorHelper(format(
  111. 'Unknown parser "%s" (choices: [%s]).',
  112. parserName,
  113. _.keys(this._nameParserMap).join(', ')
  114. ));
  115. }
  116. // parse all the remaining options into the namespace
  117. parser.parseArgs(argStrings, namespace);
  118. };