New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add .commandDir(dir) to API to apply all command modules from a relative directory #494
Conversation
@nexdrew I love this work, don't suppose we could get a test in the mix :) |
Yes, this is exactly what I had hoped for - I think the chosen approach makes perfect sense and complements the functionality provided by command modules really well. Love it. Great work @nexdrew |
@AGresvig Thanks! I'll get some tests and docs written up within the next couple days so we can merge this safely. |
self.addHandler(cmd.command, extractDesc(cmd), cmd.builder, cmd.handler) | ||
} else { | ||
self.addHandler(cmd.command, extractDesc(cmd)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little confused here, is allowing commands without builder and handler functions an essential feature for .commandDir()
or is this unrelated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@maxrimue Good question. This could certainly be done in a separate PR (maybe as a precursor) but is just something I ran into when testing with require-directory
.
A couple reasons:
- yargs currently blows up when you give it a command module/object that does not have all the expected properties of a command module - this is something that should probably be fixed in general
require-directory
looks for and loadsjson
files as well asjs
andcoffee
modules by default, which I have overridden to be justjs
(since a JSON "command module" cannot support ahandler
function by itself), but if folks want to define "commands" via JSON files, then they will need this change to support an option ofextensions: ['js', 'json']
(or similar)
I don't really think no. 2 is a big concern, unless folks are dynamically generating their commands as JSON (not sure why you would), but is more of a "why not?".
I view no. 1 as a bigger problem that we should address, either before or with #492. So figured I'd kill two birds with one stone here. I can easily be persuaded otherwise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's address this in #429 👍
Looks awesome, well done! Could we perhaps make some variables constants since there are some good reasons for doing so in yargs in general as shown in #502? |
@nexdrew Awesome! LGTM |
@@ -19,6 +19,7 @@ | |||
"os-locale": "^1.4.0", | |||
"pkg-conf": "^1.1.2", | |||
"read-pkg-up": "^1.0.1", | |||
"require-directory": "^2.1.1", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I appreciate that this only pull in once dependency in total \o/
@nexdrew please give |
@bcoe OK will do! |
This replaces #463, opting to require modules from a single directory at a time via
require-directory
(instead of supporting globs).The implementation is slightly trickier than I originally thought, but it allows a consumer to do things like the following.
Example setup
directory structure:
cli.js:
commands/people.js:
commands/places.js:
commands/things.js:
commands/common_cmds/details.js:
Example CLI
API
This adds one method to the API:
.commandDir(dir, [opts])
dir
is a directory name which can/should be relative to the module calling the method.opts
is an options object that is passed torequire-directory
, allowing consumers to customize the behavior. In the initial implementation, the following opts are valid:opts.recurse
: boolean, defaultfalse
Should yargs require command modules from all nested directories? The default is
false
so subcommands can be nested instead of flattened.opts.extensions
: array of strings, default['js']
The types of files to include when requiring.
opts.visit
: functionA synchronous function that is called for each command module encountered. Accepts
commandObject
,pathToFile
, andfilename
as arguments. ReturnscommandObject
to include the command; any falsey value to exclude/skip it.opts.include
: RegExp or functionWhitelist certain modules. See require-directory whitelisting for details.
opts.exclude
: RegExp or functionBlacklist certain modules. See require-directory blacklisting for details.
Notes
This also includes a change that allows a command module to only define
command
anddescription
, which better supports requiring JSON modules (though I'm not sure why someone would want to do that) and fulfills (at least) a part of #492.I considered adding support for using the filename of a command module as its
command
string if the module itself doesn't definecommand
, but I think it'd be nice to support this for all command modules (i.e. not just when using.commandDir()
), so I'd like to tackle that separately/subsequently.I don't have strong feelings about the method name
commandDir
. Would be happy to change it if folks like something else better. As always, feedback is welcomed!Still lacking