@bomb.sh/tab 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +153 -167
  2. package/dist/bin/cli.d.ts +1 -1
  3. package/dist/bin/cli.js +1190 -324
  4. package/dist/{cac-DEQnX2V4.js → cac-D7fQPv8f.js} +7 -4
  5. package/dist/{src/cac.d.ts → cac.d.ts} +2 -3
  6. package/dist/cac.js +5 -0
  7. package/dist/{src/citty.d.ts → citty.d.ts} +2 -3
  8. package/dist/citty.js +192 -0
  9. package/dist/{src/commander.d.ts → commander.d.ts} +1 -2
  10. package/dist/{commander-gLSiUyHX.js → commander.js} +6 -7
  11. package/dist/{consola.36c0034f-CftISWio.js → consola.36c0034f-DcBvmSjS.js} +20 -26
  12. package/dist/{prompt-BeRRtcd8.js → prompt-Cjrbe4Tk.js} +15 -17
  13. package/dist/{shared-BGWjvggn.js → shared-H1O-vFhE.js} +1 -2
  14. package/dist/shared-NttFmF7I.d.ts +10 -0
  15. package/dist/{t-Zhhzaib1.js → t-BDEAdEmc.js} +17 -17
  16. package/dist/t-_VA0Gr6E.d.ts +67 -0
  17. package/dist/t.d.ts +2 -0
  18. package/dist/{src/t.js → t.js} +1 -1
  19. package/package.json +6 -6
  20. package/README.2.md +0 -108
  21. package/dist/citty-BJEnxM_0.js +0 -525
  22. package/dist/dist-QXQoOtHE.js +0 -487
  23. package/dist/examples/demo.cac.d.ts +0 -1
  24. package/dist/examples/demo.cac.js +0 -63
  25. package/dist/examples/demo.citty.d.ts +0 -1
  26. package/dist/examples/demo.citty.js +0 -173
  27. package/dist/examples/demo.commander.d.ts +0 -1
  28. package/dist/examples/demo.commander.js +0 -3035
  29. package/dist/examples/demo.t.d.ts +0 -1
  30. package/dist/examples/demo.t.js +0 -78
  31. package/dist/shared.d-B8B93rZW.d.ts +0 -11
  32. package/dist/src/cac.js +0 -5
  33. package/dist/src/citty.js +0 -6
  34. package/dist/src/commander.js +0 -5
  35. package/dist/src/t.d.ts +0 -3
  36. package/dist/t.d-keC1Qwmr.d.ts +0 -68
package/README.md CHANGED
@@ -1,169 +1,174 @@
1
+ ![tab CLI autocompletions demo](assets/preview.gif)
2
+
1
3
  # tab
2
4
 
3
- Shell autocompletions are largely missing in the javascript cli ecosystem. This tool is an attempt to make autocompletions come out of the box for any cli tool.
5
+ Shell autocompletions are largely missing in the JavaScript CLI ecosystem. tab provides a simple API for adding autocompletions to any JavaScript CLI tool.
4
6
 
5
- Tools like git and their autocompletion experience inspired us to build this tool and make the same ability available for any javascript cli project. Developers love hitting the tab key, hence why they prefer tabs over spaces.
7
+ Additionally, tab supports autocompletions for `pnpm`, `npm`, `yarn`, and `bun`.
6
8
 
7
- ## Examples
9
+ As CLI tooling authors, if we can spare our users a second or two by not checking documentation or writing the `-h` flag, we're doing them a huge favor. The unconscious mind loves hitting the [TAB] key and always expects feedback. When nothing happens, it breaks the user's flow - a frustration apparent across the whole JavaScript CLI tooling ecosystem.
8
10
 
9
- Check out the [examples directory](./examples) for complete examples of using Tab with different command-line frameworks:
11
+ tab solves this complexity by providing autocompletions that work consistently across `zsh`, `bash`, `fish`, and `powershell`.
10
12
 
11
- - [CAC](./examples/demo.cac.ts)
12
- - [Citty](./examples/demo.citty.ts)
13
- - [Commander.js](./examples/demo.commander.ts)
13
+ ## Installation
14
14
 
15
- ## Usage
15
+ ```bash
16
+ npm install @bomb.sh/tab
17
+ # or
18
+ pnpm add @bomb.sh/tab
19
+ # or
20
+ yarn add @bomb.sh/tab
21
+ # or
22
+ bun add @bomb.sh/tab
23
+ ```
16
24
 
17
- ```ts
18
- import { Completion, script } from '@bomb.sh/tab';
25
+ ## Quick Start
19
26
 
20
- const name = 'my-cli';
21
- const completion = new Completion();
27
+ Add autocompletions to your CLI tool:
22
28
 
23
- completion.addCommand(
24
- 'start',
25
- 'Start the application',
26
- async (previousArgs, toComplete, endsWithSpace) => {
27
- // suggestions
28
- return [
29
- { value: 'dev', description: 'Start in development mode' },
30
- { value: 'prod', description: 'Start in production mode' },
31
- ];
32
- }
33
- );
34
-
35
- completion.addOption(
36
- 'start',
37
- '--port',
38
- 'Specify the port number',
39
- async (previousArgs, toComplete, endsWithSpace) => {
40
- return [
41
- { value: '3000', description: 'Development port' },
42
- { value: '8080', description: 'Production port' },
43
- ];
44
- }
45
- );
29
+ ```typescript
30
+ import t from '@bomb.sh/tab';
46
31
 
47
- // a way of getting the executable path to pass to the shell autocompletion script
48
- function quoteIfNeeded(path: string) {
49
- return path.includes(' ') ? `'${path}'` : path;
50
- }
51
- const execPath = process.execPath;
52
- const processArgs = process.argv.slice(1);
53
- const quotedExecPath = quoteIfNeeded(execPath);
54
- const quotedProcessArgs = processArgs.map(quoteIfNeeded);
55
- const quotedProcessExecArgs = process.execArgv.map(quoteIfNeeded);
56
- const x = `${quotedExecPath} ${quotedProcessExecArgs.join(' ')} ${quotedProcessArgs[0]}`;
57
-
58
- if (process.argv[2] === '--') {
59
- // autocompletion logic
60
- await completion.parse(process.argv.slice(2), 'start'); // TODO: remove "start"
61
- } else {
62
- // process.argv[2] can be "zsh", "bash", "fish", "powershell"
63
- script(process.argv[2], name, x);
32
+ // Define your CLI structure
33
+ const devCmd = t.command('dev', 'Start development server');
34
+ devCmd.option('port', 'Specify port', (complete) => {
35
+ complete('3000', 'Development port');
36
+ complete('8080', 'Production port');
37
+ });
38
+
39
+ // Handle completion requests
40
+ if (process.argv[2] === 'complete') {
41
+ const shell = process.argv[3];
42
+ if (shell === '--') {
43
+ const args = process.argv.slice(4);
44
+ t.parse(args);
45
+ } else {
46
+ t.setup('my-cli', 'node my-cli.js', shell);
47
+ }
64
48
  }
65
49
  ```
66
50
 
67
- Now your user can run `source <(my-cli complete zsh)` and they will get completions for the `my-cli` command using the [autocompletion server](#autocompletion-server).
51
+ Test your completions:
68
52
 
69
- ## Adapters
53
+ ```bash
54
+ node my-cli.js complete -- dev --port=<TAB>
55
+ # Output: --port=3000 Development port
56
+ # --port=8080 Production port
57
+ ```
70
58
 
71
- Since we are heavy users of tools like `cac` and `citty`, we have created adapters for both of them. Ideally, tab would be integrated internally into these tools, but for now, this is a good compromise.
59
+ Install for users:
72
60
 
73
- ### `@bomb.sh/tab/cac`
61
+ ```bash
62
+ # One-time setup
63
+ source <(my-cli complete zsh)
74
64
 
75
- ```ts
76
- import cac from 'cac';
77
- import tab from '@bomb.sh/tab/cac';
65
+ # Permanent setup
66
+ my-cli complete zsh > ~/.my-cli-completion.zsh
67
+ echo 'source ~/.my-cli-completion.zsh' >> ~/.zshrc
68
+ ```
78
69
 
79
- const cli = cac('my-cli');
70
+ ## Package Manager Completions
80
71
 
81
- cli.command('dev', 'Start dev server').option('--port <port>', 'Specify port');
72
+ As mentioned earlier, tab provides completions for package managers as well:
82
73
 
83
- const completion = tab(cli);
74
+ ```bash
75
+ # Generate and install completion scripts
76
+ npx @bomb.sh/tab pnpm zsh > ~/.pnpm-completion.zsh && echo 'source ~/.pnpm-completion.zsh' >> ~/.zshrc
77
+ npx @bomb.sh/tab npm bash > ~/.npm-completion.bash && echo 'source ~/.npm-completion.bash' >> ~/.bashrc
78
+ npx @bomb.sh/tab yarn fish > ~/.config/fish/completions/yarn.fish
79
+ npx @bomb.sh/tab bun powershell > ~/.bun-completion.ps1 && echo '. ~/.bun-completion.ps1' >> $PROFILE
80
+ ```
84
81
 
85
- // Get the dev command completion handler
86
- const devCommandCompletion = completion.commands.get('dev');
82
+ Example in action:
87
83
 
88
- // Get and configure the port option completion handler
89
- const portOptionCompletion = devCommandCompletion.options.get('--port');
90
- portOptionCompletion.handler = async (
91
- previousArgs,
92
- toComplete,
93
- endsWithSpace
94
- ) => {
95
- return [
96
- { value: '3000', description: 'Development port' },
97
- { value: '8080', description: 'Production port' },
98
- ];
99
- };
84
+ ```bash
85
+ pnpm install --reporter=<TAB>
86
+ # Shows: append-only, default, ndjson, silent
100
87
 
101
- cli.parse();
88
+ yarn add --emoji=<TAB>
89
+ # Shows: true, false
102
90
  ```
103
91
 
104
- Now autocompletion will be available for any specified command and option in your cac instance. If your user writes `my-cli dev --po`, they will get suggestions for the `--port` option. Or if they write `my-cli d` they will get suggestions for the `dev` command.
92
+ ## Framework Adapters
93
+
94
+ tab provides adapters for popular JavaScript CLI frameworks.
95
+
96
+ ### CAC Integration
97
+
98
+ ```typescript
99
+ import cac from 'cac';
100
+ import tab from '@bomb.sh/tab/cac';
101
+
102
+ const cli = cac('my-cli');
105
103
 
106
- Suggestions are missing in the adapters since yet cac or citty do not have a way to provide suggestions (tab just came out!), we'd have to provide them manually. Mutations do not hurt in this situation.
104
+ // Define your CLI
105
+ cli
106
+ .command('dev', 'Start dev server')
107
+ .option('--port <port>', 'Specify port')
108
+ .option('--host <host>', 'Specify host');
109
+
110
+ // Initialize tab completions
111
+ const completion = await tab(cli);
112
+
113
+ // Add custom completions for option values
114
+ const devCommand = completion.commands.get('dev');
115
+ const portOption = devCommand?.options.get('port');
116
+ if (portOption) {
117
+ portOption.handler = (complete) => {
118
+ complete('3000', 'Development port');
119
+ complete('8080', 'Production port');
120
+ };
121
+ }
107
122
 
108
- ### `@bomb.sh/tab/citty`
123
+ cli.parse();
124
+ ```
125
+
126
+ ### Citty Integration
109
127
 
110
- ```ts
111
- import citty, { defineCommand, createMain } from 'citty';
128
+ ```typescript
129
+ import { defineCommand, createMain } from 'citty';
112
130
  import tab from '@bomb.sh/tab/citty';
113
131
 
114
132
  const main = defineCommand({
115
- meta: {
116
- name: 'my-cli',
117
- description: 'My CLI tool',
133
+ meta: { name: 'my-cli', description: 'My CLI tool' },
134
+ subCommands: {
135
+ dev: defineCommand({
136
+ meta: { name: 'dev', description: 'Start dev server' },
137
+ args: {
138
+ port: { type: 'string', description: 'Specify port' },
139
+ host: { type: 'string', description: 'Specify host' },
140
+ },
141
+ }),
118
142
  },
119
143
  });
120
144
 
121
- const devCommand = defineCommand({
122
- meta: {
123
- name: 'dev',
124
- description: 'Start dev server',
125
- },
126
- args: {
127
- port: { type: 'string', description: 'Specify port' },
128
- },
129
- });
130
-
131
- main.subCommands = {
132
- dev: devCommand,
133
- };
134
-
145
+ // Initialize tab completions
135
146
  const completion = await tab(main);
136
147
 
137
- // TODO: addHandler function to export
138
- const devCommandCompletion = completion.commands.get('dev');
139
-
140
- const portOptionCompletion = devCommandCompletion.options.get('--port');
141
-
142
- portOptionCompletion.handler = async (
143
- previousArgs,
144
- toComplete,
145
- endsWithSpace
146
- ) => {
147
- return [
148
- { value: '3000', description: 'Development port' },
149
- { value: '8080', description: 'Production port' },
150
- ];
151
- };
148
+ // Add custom completions
149
+ const devCommand = completion.commands.get('dev');
150
+ const portOption = devCommand?.options.get('port');
151
+ if (portOption) {
152
+ portOption.handler = (complete) => {
153
+ complete('3000', 'Development port');
154
+ complete('8080', 'Production port');
155
+ };
156
+ }
152
157
 
153
158
  const cli = createMain(main);
154
159
  cli();
155
160
  ```
156
161
 
157
- ### `@bomb.sh/tab/commander`
162
+ ### Commander.js Integration
158
163
 
159
- ```ts
164
+ ```typescript
160
165
  import { Command } from 'commander';
161
166
  import tab from '@bomb.sh/tab/commander';
162
167
 
163
168
  const program = new Command('my-cli');
164
169
  program.version('1.0.0');
165
170
 
166
- // Add commands
171
+ // Define commands
167
172
  program
168
173
  .command('serve')
169
174
  .description('Start the server')
@@ -173,74 +178,55 @@ program
173
178
  console.log('Starting server...');
174
179
  });
175
180
 
176
- // Initialize tab completion
181
+ // Initialize tab completions
177
182
  const completion = tab(program);
178
183
 
179
- // Configure custom completions
180
- for (const command of completion.commands.values()) {
181
- if (command.name === 'serve') {
182
- for (const [option, config] of command.options.entries()) {
183
- if (option === '--port') {
184
- config.handler = () => {
185
- return [
186
- { value: '3000', description: 'Default port' },
187
- { value: '8080', description: 'Alternative port' },
188
- ];
189
- };
190
- }
191
- }
192
- }
184
+ // Add custom completions
185
+ const serveCommand = completion.commands.get('serve');
186
+ const portOption = serveCommand?.options.get('port');
187
+ if (portOption) {
188
+ portOption.handler = (complete) => {
189
+ complete('3000', 'Default port');
190
+ complete('8080', 'Alternative port');
191
+ };
193
192
  }
194
193
 
195
194
  program.parse();
196
195
  ```
197
196
 
198
- ## Recipe
199
-
200
- `source <(my-cli complete zsh)` won't be enough since the user would have to run this command each time they spin up a new shell instance.
201
-
202
- We suggest this approach for the end user that you as a maintainer might want to push.
203
-
204
- ```
205
- my-cli completion zsh > ~/completion-for-my-cli.zsh
206
- echo 'source ~/completion-for-my-cli.zsh' >> ~/.zshrc
207
- ```
208
-
209
- For other shells:
197
+ tab uses a standardized completion protocol that any CLI can implement:
210
198
 
211
199
  ```bash
212
- # Bash
213
- my-cli complete bash > ~/.bash_completion.d/my-cli
214
- echo 'source ~/.bash_completion.d/my-cli' >> ~/.bashrc
215
-
216
- # Fish
217
- my-cli complete fish > ~/.config/fish/completions/my-cli.fish
200
+ # Generate shell completion script
201
+ my-cli complete zsh
218
202
 
219
- # PowerShell
220
- my-cli complete powershell > $PROFILE.CurrentUserAllHosts
203
+ # Parse completion request (called by shell)
204
+ my-cli complete -- install --port=""
221
205
  ```
222
206
 
223
- ## Autocompletion Server
207
+ **Output Format:**
224
208
 
225
- By integrating tab into your cli, your cli would have a new command called `complete`. This is where all the magic happens. And the shell would contact this command to get completions. That's why we call it the autocompletion server.
226
-
227
- ```zsh
228
- my-cli complete -- --po
229
- --port Specify the port number
230
- :0
231
209
  ```
210
+ --port=3000 Development port
211
+ --port=8080 Production port
212
+ :4
213
+ ```
214
+
215
+ ## Documentation
232
216
 
233
- The autocompletion server can be a standard to identify whether a package provides autocompletions. Whether running `tool complete --` would result in an output that ends with `:{Number}` (matching the pattern `/:\d+$/`).
217
+ See [bombshell docs](https://bomb.sh/docs/tab/).
234
218
 
235
- In situations like `my-cli dev --po` you'd have autocompletions! But in the case of `pnpm my-cli dev --po` which is what most of us use, tab does not inject autocompletions for a tool like pnpm.
219
+ ## Contributing
236
220
 
237
- Since pnpm already has its own autocompletion [script](https://pnpm.io/completion), this provides the opportunity to check whether a package provides autocompletions and use those autocompletions if available.
221
+ We welcome contributions! tab's architecture makes it easy to add support for new package managers or CLI frameworks.
238
222
 
239
- This would also have users avoid injecting autocompletions in their shell config for any tool that provides its own autocompletion script, since pnpm would already support proxying the autocompletions out of the box.
223
+ ## Acknowledgments
240
224
 
241
- Other package managers like `npm` and `yarn` can decide whether to support this or not too for more universal support.
225
+ tab was inspired by the great [Cobra](https://github.com/spf13/cobra/) project, which set the standard for CLI tooling in the Go ecosystem.
242
226
 
243
- ## Inspiration
227
+ ## Adoption Support
244
228
 
245
- - git
246
- - [cobra](https://github.com/spf13/cobra/blob/main/shell_completions.go), without cobra, tab would have took 10x longer to build
229
+ We want to make it as easy as possible for the JS ecosystem to enjoy great autocompletions.
230
+ We at [thundraa](https://thundraa.com) would be happy to help any open source CLI utility adopt tab.
231
+ If you maintain a CLI and would like autocompletions set up for your users, just [drop the details in our _Adopting tab_ discussion](https://github.com/bombshell-dev/tab/discussions/61).
232
+ We’ll gladly help and even open a PR to get you started.
package/dist/bin/cli.d.ts CHANGED
@@ -1 +1 @@
1
- #!/usr/bin/env node
1
+ export { };