You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
3.5 KiB

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