UNPKG

11 kBMarkdownView Raw
1<img width="945" alt="2017-07-26 9 27 05" src="https://user-images.githubusercontent.com/8784712/28623641-373450f4-7249-11e7-854d-1b076dab274d.png">
2
3[![NPM version](https://img.shields.io/npm/v/cac.svg?style=flat)](https://npmjs.com/package/cac) [![NPM downloads](https://img.shields.io/npm/dm/cac.svg?style=flat)](https://npmjs.com/package/cac) [![CircleCI](https://circleci.com/gh/cacjs/cac/tree/master.svg?style=shield)](https://circleci.com/gh/cacjs/cac/tree/master) [![donate](https://img.shields.io/badge/$-donate-ff69b4.svg?maxAge=2592000&style=flat)](https://github.com/egoist/donate) [![chat](https://img.shields.io/badge/chat-on%20discord-7289DA.svg?style=flat)](https://chat.egoist.moe) [![install size](https://badgen.net/packagephobia/install/cac)](https://packagephobia.now.sh/result?p=cac)
4
5## Introduction
6
7**C**ommand **A**nd **C**onquer is a JavaScript library for building CLI apps.
8
9## Table of Contents
10
11<!-- toc -->
12
13- [Install](#install)
14- [Usage](#usage)
15 - [Simple Parsing](#simple-parsing)
16 - [Display Help Message and Version](#display-help-message-and-version)
17 - [Command-specific Options](#command-specific-options)
18 - [Brackets](#brackets)
19 - [Variadic Arguments](#variadic-arguments)
20 - [Dot-nested Options](#dot-nested-options)
21 - [Default Command](#default-command)
22 - [With TypeScript](#with-typescript)
23- [Projects Using CAC](#projects-using-cac)
24- [References](#references)
25 - [CLI Instance](#cli-instance)
26 - [cli.command(name, description)](#clicommandname-description)
27 - [cli.option(name, description, config?)](#clioptionname-description-config)
28 - [cli.parse(argv?)](#cliparseargv)
29 - [cli.version(version, customFlags?)](#cliversionversion-customflags)
30 - [cli.help(callback?)](#clihelpcallback)
31 - [cli.outputHelp(subCommand?)](#clioutputhelpsubcommand)
32 - [Command Instance](#command-instance)
33 - [command.option()](#commandoption)
34 - [command.action(callback)](#commandactioncallback)
35 - [command.alias(name)](#commandaliasname)
36 - [command.allowUnknownOptions()](#commandallowunknownoptions)
37 - [command.example(example)](#commandexampleexample)
38 - [Events](#events)
39- [FAQ](#faq)
40 - [How is the name written and pronounced?](#how-is-the-name-written-and-pronounced)
41- [Contributing](#contributing)
42- [Author](#author)
43
44<!-- tocstop -->
45
46## Install
47
48```bash
49yarn add cac
50```
51
52## Usage
53
54### Simple Parsing
55
56Use CAC as simple argument parser:
57
58```js
59// examples/basic-usage.js
60const cli = require('cac')()
61
62cli.option('--type [type]', 'Choose a project type', {
63 default: 'node'
64})
65
66const parsed = cli.parse()
67
68console.log(JSON.stringify(parsed, null, 2))
69```
70
71<img width="500" alt="2018-11-26 12 28 03" src="https://user-images.githubusercontent.com/8784712/48981576-2a871000-f112-11e8-8151-80f61e9b9908.png">
72
73### Display Help Message and Version
74
75```js
76// examples/help.js
77const cli = require('cac')()
78
79cli.option('--type [type]', 'Choose a project type', {
80 default: 'node'
81})
82cli.option('--name <name>', 'Provide your name')
83
84cli.command('lint [...files]', 'Lint files').action((files, options) => {
85 console.log(files, options)
86})
87
88// Display help message when `-h` or `--help` appears
89cli.help()
90// Display version number when `-h` or `--help` appears
91cli.version('0.0.0')
92
93cli.parse()
94```
95
96<img width="500" alt="2018-11-25 8 21 14" src="https://user-images.githubusercontent.com/8784712/48979012-acb20d00-f0ef-11e8-9cc6-8ffca00ab78a.png">
97
98### Command-specific Options
99
100You can attach options to a command.
101
102```js
103const cli = require('cac')()
104
105cli
106 .command('rm <dir>')
107 .option('-r, --recursive', 'Remove recursively')
108 .action((dir, options) => {
109 console.log('remove ' + dir + (options.recursive ? ' recursively' : ''))
110 })
111
112cli.parse()
113```
114
115A command's options are validated when the command is used. Any unknown options will be reported as an error. However, if an action-based command does not define an action, then the options are not validated. If you really want to use unknown options, use [`command.allowUnknownOptions`](#commandallowunknownoptions).
116
117### Brackets
118
119When using brackets in command name, angled brackets indicate required command arguments, while sqaure bracket indicate optional arguments.
120
121When using brackets in option name, angled brackets indicate that the option value is required, while sqaure bracket indicate that the value is optional.
122
123```js
124const cli = require('cac')()
125
126cli
127 .command('deploy <folder>', 'Deploy a folder to AWS')
128 .option('--scale [level]', 'Scaling level')
129 .action((folder, options) => {
130 console.log(folder)
131 console.log(options)
132 })
133
134cli.parse()
135```
136
137### Variadic Arguments
138
139The last argument of a command can be variadic, and only the last argument. To make an argument variadic you have to add `...` to the start of argument name, just like the rest operator in JavaScript. Here is an example:
140
141```js
142const cli = require('cac')()
143
144cli
145 .command('build <entry> [...otherFiles]', 'Build your app')
146 .option('--foo', 'Foo option')
147 .action((entry, otherFiles, options) => {
148 console.log(entry)
149 console.log(otherFiles)
150 console.log(options)
151 })
152
153cli.help()
154
155cli.parse()
156```
157
158<img width="500" alt="2018-11-25 8 25 30" src="https://user-images.githubusercontent.com/8784712/48979056-47125080-f0f0-11e8-9d8f-3219e0beb0ed.png">
159
160### Dot-nested Options
161
162Dot-nested options will be merged into a single option.
163
164```js
165const cli = require('cac')()
166
167cli
168 .command('build', 'desc')
169 .option('--env <env>', 'Set envs')
170 .example('--env.API_SECRET xxx')
171 .action(options => {
172 console.log(options)
173 })
174
175cli.help()
176
177cli.parse()
178```
179
180<img width="500" alt="2018-11-25 9 37 53" src="https://user-images.githubusercontent.com/8784712/48979771-6ada9400-f0fa-11e8-8192-e541b2cfd9da.png">
181
182### Default Command
183
184Register a command that will be used when no other command is matched.
185
186```js
187const cli = require('cac')()
188
189cli
190 // Simply omit the command name, just brackets
191 .command('[...files]', 'Build files')
192 .option('--minimize', 'Minimize output')
193 .action((files, options) => {
194 console.log(files)
195 console.log(options.minimize)
196 })
197
198cli.parse()
199```
200
201### With TypeScript
202
203First you need `@types/node` to be installed as a dev dependency in your project:
204
205```bash
206yarn add @types/node --dev
207```
208
209Then everything just works out of the box:
210
211```js
212const cac = require('cac')
213// OR ES modules
214import cac from 'cac'
215```
216
217## Projects Using CAC
218
219Projects that use **CAC**:
220
221- [SAO](https://github.com/egoist/sao): ⚔️ Futuristic scaffolding tool.
222- [DocPad](https://github.com/docpad/docpad): 🏹 Powerful Static Site Generator.
223- [Poi](https://github.com/egoist/poi): ⚡️ Delightful web development.
224- [bili](https://github.com/egoist/bili): 🥂 Schweizer Armeemesser for bundling JavaScript libraries.
225- [lass](https://github.com/lassjs/lass): 💁🏻 Scaffold a modern package boilerplate for Node.js.
226- Feel free to add yours here...
227
228## References
229
230### CLI Instance
231
232CLI instance is created by invoking the `cac` function:
233
234```js
235const cac = require('cac')
236const cli = cac()
237```
238
239#### cli.command(name, description)
240
241- Type: `(name: string, description: string) => Command`
242
243Create a command instance.
244
245#### cli.option(name, description, config?)
246
247- Type: `(name: string, description: string, config?: OptionConfig) => CLI`
248
249Add a global option.
250
251The option also accepts a third argument `config` for addtional config:
252
253- `config.default`: Default value for the option.
254- `config.coerce`: `(value: any) => newValue` A function to process the option value.
255
256#### cli.parse(argv?)
257
258- Type: `(argv = process.argv) => ParsedArgv`
259
260```ts
261interface ParsedArgv {
262 args: string[]
263 options: {
264 [k: string]: any
265 }
266}
267```
268
269When this method is called, `cli.rawArgs` `cli.args` `cli.options` `cli.matchedCommand` will also be available.
270
271#### cli.version(version, customFlags?)
272
273- Type: `(version: string, customFlags = '-v, --version') => CLI`
274
275Output version number when `-v, --version` flag appears.
276
277#### cli.help(callback?)
278
279- Type: `(callback?: HelpCallback) => CLI`
280
281Output help message when `-h, --help` flag appears.
282
283Optional `callback` allows post-processing of help text before it is displayed:
284
285```ts
286type HelpCallback = (sections: HelpSection[]) => void
287
288interface HelpSection {
289 title?: string
290 body: string
291}
292```
293
294#### cli.outputHelp(subCommand?)
295
296- Type: `(subCommand?: boolean) => CLI`
297
298Output help message. Optional `subCommand` argument if you want to output the help message for the matched sub-command instead of the global help message.
299
300### Command Instance
301
302Command instance is created by invoking the `cli.command` method:
303
304```js
305const command = cli.command('build [...files]', 'Build given files')
306```
307
308#### command.option()
309
310Basically the same as `cli.option` but this adds the option to specific command.
311
312#### command.action(callback)
313
314- Type: `(callback: ActionCallback) => Command`
315
316Use a callback function as the command action when the command matches user inputs.
317
318```ts
319type ActionCallback = (
320 // Parsed CLI args
321 // The last arg will be an array if it's an varadic argument
322 ...args: string | string[] | number | number[]
323 // Parsed CLI options
324 options: Options
325) => any
326
327interface Options {
328 [k: string]: any
329}
330```
331
332#### command.alias(name)
333
334- Type: `(name: string) => Command`
335
336Add an alias name to this command, the `name` here can't contain brackets.
337
338#### command.allowUnknownOptions()
339
340- Type: `() => Command`
341
342Allow unknown options in this command, by default CAC will log an error when unknown options are used.
343
344#### command.example(example)
345
346- Type: `(example: CommandExample) => Command`
347
348Add an example which will be displayed at the end of help message.
349
350```ts
351type CommandExample = ((bin: string) => string) | string
352```
353
354### Events
355
356Listen to commands:
357
358```js
359// Listen to the `foo` command
360cli.on('command:foo', () => {
361 // Do something
362})
363
364// Listen to the default command
365cli.on('command:!', () => {
366 // Do something
367})
368
369// Listen to unknown commands
370cli.on('command:*', () => {
371 console.error('Invalid command: %', cli.args.join(' '))
372 process.exit(1)
373})
374```
375
376## FAQ
377
378### How is the name written and pronounced?
379
380CAC, or cac, pronounced `C-A-C`.
381
382This project is dedicated to our lovely C.C. sama. Maybe CAC stands for C&C as well :P
383
384<img src="http://i.giphy.com/v3FeH4swox9mg.gif" width="400"/>
385
386## Contributing
387
3881. Fork it!
3892. Create your feature branch: `git checkout -b my-new-feature`
3903. Commit your changes: `git commit -am 'Add some feature'`
3914. Push to the branch: `git push origin my-new-feature`
3925. Submit a pull request :D
393
394## Author
395
396**CAC** © [EGOIST](https://github.com/egoist), Released under the [MIT](./LICENSE) License.<br>
397Authored and maintained by egoist with help from contributors ([list](https://github.com/cacjs/cac/contributors)).
398
399> [Website](https://egoist.sh) · GitHub [@egoist](https://github.com/egoist) · Twitter [@\_egoistlily](https://twitter.com/_egoistlily)