UNPKG

11.5 kBMarkdownView Raw
1Capitano
2========
3
4[![npm version](https://badge.fury.io/js/capitano.svg)](http://badge.fury.io/js/capitano)
5[![dependencies](https://david-dm.org/resin-io/capitano.png)](https://david-dm.org/username/repo.png)
6
7Capitano allows you to craft powerful command line applications, your way.
8
9```coffee
10capitano = require('capitano')
11
12capitano.command
13 signature: 'utils print <title> [words...]'
14 options: [
15 signature: 'date'
16 boolean: true
17 alias: [ 'd' ]
18 ]
19 action: (params, options) ->
20 log = ''
21
22 if options.date
23 log += "#{new Date()} "
24
25 log += "#{params.title}: #{params.words}"
26
27 console.log(log)
28
29capitano.run process.argv, (error) ->
30 throw error if error?
31```
32
33***
34
35```sh
36$ myCoolApp utils print Error Something very bad happened
37Error: Something very bad happened
38
39$ myCoolApp utils print Error Something very bad happened -d
40Thu Dec 18 2014 14:49:27 GMT-0400 (BOT) Error: Something very bad happened
41```
42
43Features
44--------
45
46- Infinitely nested git-like subcommands.
47- Global and per-command options.
48- Variadic arguments.
49- Option aliases.
50- Separate between parsing and executing command line arguments.
51- No built-in generated help page, you roll your own.
52- No built-in commands, you have a high degree of control over your app.
53
54Installation
55------------
56
57Install `capitano` by running:
58
59```sh
60$ npm install --save capitano
61```
62
63API
64-------
65
66## capitano.command(options)
67
68Register a command. Capitano understands the following options, but you can pass custom options to do nifty things (see the [examples section](https://github.com/resin-io/capitano#examples)):
69
70### signature (string)
71
72The command signature. If it's `*`, it will match anything that is not matched by other commands.
73
74### action (function)
75
76Function to call when the signature is matched. This function gets passed a parameter object, an options object and a `callback` to be called when the action is finished.
77
78If the `callback` argument is not declared in the action function, it'll be called implicitly, however in order to ensure Capitano works as expected, call the `callback` function if your action is async.
79
80### options ([object])
81
82Array of objects describing the options specific to this command. See the [options section](https://github.com/resin-io/capitano#option) for more information.
83
84## capitano.globalOption(options)
85
86Register a global option, which will be accessible from every command (and from outside too!) so be careful about naming collisions!
87
88It accepts an object containing the following options:
89
90### signature (string)
91
92The option signature **excluding** any parameter (`foo` instead of `foo <bar>`).
93
94### boolean (boolean)
95
96Whether the option is boolean (doesn't accepts any parameters). It defaults to `false`. If `parameter` is defined, then `boolean` should be `false`.
97
98### parameter (string)
99
100The name of the parameter, excluding required/optional tags (`bar` instead of `<bar>`). Notice that if you set `boolean: true`, then you have to omit this option.
101
102
103### alias (string|[string])
104
105Define an alias, or a set of alias for an option. Aliases can contain single letter abbreviations (`f`, `l`) or full option names (`baz`, `foo`).
106
107## capitano.run(argv, callback)
108
109Run and execute the application given a set of arguments (usually `process.argv`):
110
111```coffee
112capitano.run(process.argv)
113```
114
115**Note:** `capitano.run` is a shorcut function for `capitano.execute(capitano.parse(argv), callback)`. You will usually use this function, however you can use `parse()` and `execute()` in particular situations when you need to differenciate between parsing and executing the commands.
116
117## capitano.parse(argv)
118
119Parse, but not execute the command line arguments (usually `process.argv`).
120
121It returns a `cli` object containing three fields:
122
123### command (string)
124
125A string representing the issued command, omitting any option.
126
127### options (object)
128
129An object containing the raw representation of the given options.
130
131### globals (object)
132
133An object containing the matches and parsed global options.
134
135## capitano.execute(cli, callback)
136
137It accepts a `cli` object (returned by [capitano.parse()](https://github.com/resin-io/capitano#capitanoparseargv)) and
138executes the corresponding command, with it's corresponding options.
139
140You're expected to provide your own error handling mechanism here, or in the `capitano.run` if executing from there.
141
142## capitano.state
143
144An object containing the current registered commands an options. As with Capitano you're expected to implement every command (including `help`, etc) this object comes handy to accomplish a wide range of tasks.
145
146It includes the following fields:
147
148### commands (array)
149
150An array containing every registered command so far (with `capitano.command()`)
151
152See the [Command class](https://github.com/resin-io/capitano#command) for more information.
153
154### globalOptions (array)
155
156An array containing every registered global option so far (with `capitano.globalOption()`).
157
158See the [Option class](https://github.com/resin-io/capitano#option) for more information.
159
160### findCommandBySignature(signature)
161
162A self explanatory function that returns a command that matches a specific signature.
163
164### getMatchCommand(signature)
165
166Get command that matches a signature, without taking parameters into account.
167
168This means that a command `app create <id>` will be matched by a signature `app create`.
169
170## capitano.defaults
171
172An object containing some settings used by Capitano.
173
174It includes the following fields:
175
176- `signatures.wildcard (string)` The wildcard symbol. Defaults to `*`.
177- `actions.commandNotFound(signature)` The function called when a command was not found. By default, it prints a boring `Command not found: <signature>` and exits with an error code 1.
178
179**Pro tip:** If you want to modify these settings, do it as early as possible (before registering any commands/global options) as some settings are used when performing the mentioned tasks.
180
181Classes
182-------
183
184### Command
185
186The Capitano Command class contains the following public fields:
187
188#### Command#signature (Signature)
189
190See the [Signature class](https://github.com/resin-io/capitano#signature).
191
192#### Command#options ([Option])
193
194An array of [Option classes](https://github.com/resin-io/capitano#option).
195
196#### Command#isWildcard()
197
198A predicate method that returns `true` if a command represents a wildcard.
199
200***
201
202### Signature
203
204The Capitano Signature class contains the following public fields:
205
206#### Signature#hasParameters()
207
208A predicate method that returns `true` if the signature has at least one parameter.
209
210#### Signature#hasVariadicParameters()
211
212A predicate method that returns `true` if the signature has at least one variadic parameter.
213
214#### Signature#isWildcard()
215
216A predicate method that returns `true` if the signature represents a wildcard.
217
218***
219
220### Option
221
222The Capitano Option class contains the following public fields:
223
224#### Option#signature
225
226See [Signature class](https://github.com/resin-io/capitano#signature).
227
228#### Option#alias (string|[string])
229
230A string or array of string alias.
231
232#### Option#boolean (boolean)
233
234Whether the option is boolean or not.
235
236#### Option#parameter (string)
237
238An option parameter (optional).
239
240#### Option#required (boolean|string)
241
242Defines whether an option is required. If the field is `true`, a generic error is thrown, otherwise you can set a custom error message by setting to a `string`.
243
244Examples
245--------
246
247Capitano is very flexible, allowing you to implement all sort of crazy stuff. Here I present some common patterns that I've been doing on Capitano. If you have an interesting idea that you think it's worth to share, please submit a PR!
248
249### Generated help
250
251Notice this is a very rudimentary help page and lacks features such as printing global options, command specific options, handling correct aligment, etc, but you can at least get an idea on how to implement this for yourself.
252
253```coffee
254capitano = require('capitano')
255
256capitano.command
257 signature: 'version'
258 description: 'output version information'
259 action: ...
260
261capitano.command
262 signature: 'help'
263 description: 'output general help page'
264 action: ->
265 console.log("Usage: #{myAppName} [COMMANDS] [OPTIONS]")
266 console.log('\nCommands:\n')
267
268 for command in capitano.state.commands
269 continue if command.isWildcard()
270 console.log("\t#{command.signature}\t\t\t"#{command.description})
271
272capitano.run process.argv, (error) ->
273 throw error if error?
274```
275
276***
277
278```sh
279$ app help
280Usage: MyCoolApp [COMMANDS] [OPTIONS]
281
282Commands:
283
284 version output version information
285 help output general help page
286```
287
288### Command specific help pages
289
290```coffee
291capitano = require('capitano')
292
293capitano.command
294 signature: 'version'
295 description: 'output version information'
296 help: '''
297 Software versioning is the process of assigning either unique version names or unique version numbers to unique states of computer software. Within a given version number category (major, minor), these numbers are generally assigned in increasing order and correspond to new developments in the software. At a fine-grained level, revision control is often used for keeping track of incrementally different versions of electronic information, whether or not this information is computer software.
298 '''
299 action: ...
300
301capitano.command
302 signature: 'help [command...]'
303 description: 'output general help page'
304 action: (params) ->
305 return outputGeneralHelp() if not params?
306
307 command = capitano.state.getMatchCommand(params.command)
308 if not command? or command.isWildcard()
309 return capitano.defaults.actions.commandNotFound(params.command)
310
311 console.log(command.help)
312
313capitano.run process.argv, (error) ->
314 throw error if error?
315```
316
317***
318
319```sh
320$ app help version
321Software versioning is the process of assigning either unique version names or unique version numbers to unique states of computer software. Within a given version number category (major, minor), these numbers are generally assigned in increasing order and correspond to new developments in the software. At a fine-grained level, revision control is often used for keeping track of incrementally different versions of electronic information, whether or not this information is computer software.
322```
323
324Tests
325-----
326
327Run the test suite by doing:
328
329```sh
330$ gulp test
331```
332
333ChangeLog
334---------
335
336### 1.2.0
337
338- Implement action callback support. Discussed in [#11](https://github.com/resin-io/capitano/issues/11).
339
340### 1.1.1
341
342- Fix issue with parsing words that start with a number.
343
344### 1.1.0
345
346- Implement support for required options.
347
348### 1.0.4
349
350- Fix issue when instantiating Parameter instances with a number directly.
351
352### 1.0.3
353
354- Fix issue with quotation of multi word parameters. Thanks [@Page-](https://github.com/Page-)!
355
356### 1.0.2
357
358- Fix https://github.com/resin-io/capitano/issues/4.
359
360### 1.0.1
361
362- Fix issues with path and quoted multi string parameters.
363
364Contribute
365----------
366
367- Issue Tracker: [github.com/resin-io/capitano/issues](https://github.com/resin-io/capitano/issues)
368- Source Code: [github.com/resin-io/capitano](https://github.com/resin-io/capitano)
369
370Before submitting a PR, please make sure that you include tests, and that [coffeelint](http://www.coffeelint.org/) runs without any warning:
371
372```sh
373$ gulp lint
374```
375
376Support
377-------
378
379If you're having any problem, please [raise an issue](https://github.com/resin-io/capitano/issues) on GitHub.
380
381TODO
382-------
383
384- Options default values.
385- Allow comma-separated parameter values (numbers, floats, etc).
386
387License
388-------
389
390The project is licensed under the MIT license.