commandable.js 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. var nopt = require('nopt');
  2. // Commandable Mixin
  3. //
  4. // Provides API to route arbitrary routes or register command / sub commands /
  5. // sub programs.
  6. var commandable = module.exports;
  7. // XXX: tomdocify, generate in readme
  8. commandable.cmd =
  9. commandable.command = function command(name, fn) {
  10. this._commands[name] = fn;
  11. var commandable = fn && fn.command && fn.route && fn.parse;
  12. this.on(name, commandable ? function(args, opts, position) {
  13. fn.parse(args, position);
  14. } : fn);
  15. return this;
  16. };
  17. commandable.route = function route(pattern, fn) {
  18. pattern = pattern instanceof RegExp ? pattern : new RegExp('^' + pattern + '$');
  19. this._routes.push({
  20. pattern: pattern,
  21. fn: fn
  22. });
  23. return this;
  24. };
  25. commandable.routeCommand = function routeCommand(opts) {
  26. opts = opts || this.nopt;
  27. var args = opts.argv.remain;
  28. var commands = Object.keys(this._commands);
  29. // firt try to find a route, then fallback to command
  30. var route = this._routes.filter(function(route) {
  31. return route.pattern.test(args.join(' '));
  32. });
  33. if(route.length) return route[0].fn();
  34. var first = 0
  35. var registered = args.filter(function(arg, i) {
  36. var match = ~commands.indexOf(arg);
  37. if(match) first = first || i;
  38. return match;
  39. });
  40. if(!registered[0]) return this.run();
  41. opts.argv.remain = args.slice(0, first);
  42. registered.forEach(function(command) {
  43. var position = opts.argv.original.indexOf(command) + 1;
  44. var options = nopt({}, {}, opts.argv.original, position);
  45. this.emit(command, options.argv.original, options, position);
  46. }, this);
  47. };
  48. commandable.registered = function(args) {
  49. var commands = Object.keys(this._commands);
  50. var registered = args.filter(function(arg, i) {
  51. return ~commands.indexOf(arg);
  52. });
  53. return registered.length ? this._commands[registered] : false;
  54. };