Skip to content

Commit 38de566

Browse files
committed
prettier
1 parent 18814e6 commit 38de566

File tree

13 files changed

+644
-524
lines changed

13 files changed

+644
-524
lines changed

README.2.md

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,48 @@
22
33
# tab
44

5-
> Instant feedback for your CLI tool when hitting [TAB] in your terminal
5+
> Instant feedback for your CLI tool when hitting [TAB] in your terminal
66
77
As CLI tooling authors, if we can spare our users a second or two by not checking the documentation or writing the `-h` option, we're doing them a huge favor. The unconscious loves hitting the [TAB] key. It always expects feedback. So it feels disappointing when hitting that key in the terminal but then nothing happens. That frustration is apparent across the whole JavaScript CLI tooling ecosystem.
88

9-
Autocompletions are the solution to not break the user's flow. The issue is they're not simple to add. `zsh` expects them in one way, and `bash` in another way. Then where do we provide them so the shell environment parses them? Too many headaches to ease the user's experience. Whether it's worth it or not is out of the question. Because tab is the solution to this complexity.
9+
Autocompletions are the solution to not break the user's flow. The issue is they're not simple to add. `zsh` expects them in one way, and `bash` in another way. Then where do we provide them so the shell environment parses them? Too many headaches to ease the user's experience. Whether it's worth it or not is out of the question. Because tab is the solution to this complexity.
1010

1111
`my-cli.ts`:
12+
1213
```typescript
13-
import t from '@bombsh/tab'
14+
import t from '@bombsh/tab';
1415

15-
t.name('my-cli')
16+
t.name('my-cli');
1617

17-
t.command('start', 'start the development server')
18+
t.command('start', 'start the development server');
1819

1920
if (process.argv[2] === 'complete') {
20-
const [shell, ...args] = process.argv.slice(3)
21+
const [shell, ...args] = process.argv.slice(3);
2122
if (shell === '--') {
22-
t.parse(args)
23+
t.parse(args);
2324
} else {
24-
t.setup(shell, x)
25+
t.setup(shell, x);
2526
}
2627
}
2728
```
2829

29-
This `my-cli.ts` would be equipped with all the tools required to provide autocompletions.
30+
This `my-cli.ts` would be equipped with all the tools required to provide autocompletions.
3031

3132
```bash
3233
node my-cli.ts complete -- "st"
3334
```
35+
3436
```
3537
start start the development server
3638
:0
3739
```
3840

39-
This output was generated by the `t.parse` method to autocomplete "st" to "start".
41+
This output was generated by the `t.parse` method to autocomplete "st" to "start".
4042

41-
Obviously, the user won't be running that command directly in their terminal. They'd be running something like this.
43+
Obviously, the user won't be running that command directly in their terminal. They'd be running something like this.
4244

4345
```bash
44-
source <(node my-cli.ts complete zsh)
46+
source <(node my-cli.ts complete zsh)
4547
```
4648

4749
Now whenever the shell sees `my-cli`, it would bring the autocompletions we wrote for this CLI tool. The `node my-cli.ts complete zsh` part would output the zsh script that loads the autocompletions provided by `t.parse` which then would be executed using `source`.
@@ -52,54 +54,55 @@ The autocompletions only live through the current shell session. To set them up
5254
my-cli complete zsh > ~/completion-for-my-cli.zsh && echo 'source ~/completion-for-my-cli.zsh' >> ~/.zshrc
5355
```
5456

55-
Or
57+
Or
5658

5759
```bash
5860
echo 'source <(npx --offline my-cli complete zsh)' >> ~/.zshrc
5961
```
6062

61-
This is an example of autocompletions on a global CLI command that is usually installed using the `-g` flag (e.g. `npm add -g my-cli`) which is available across the computer.
63+
This is an example of autocompletions on a global CLI command that is usually installed using the `-g` flag (e.g. `npm add -g my-cli`) which is available across the computer.
6264

6365
---
6466

65-
While working on tab, we came to the realization that most JavaScript CLIs are not global CLI commands but rather, per-project dependencies.
67+
While working on tab, we came to the realization that most JavaScript CLIs are not global CLI commands but rather, per-project dependencies.
6668

6769
For instance, Vite won't be installed globally and instead it'd be always installed on a project. Here's an example usage:
6870

6971
```bash
7072
pnpm vite dev
7173
```
7274

73-
Rather than installing it globally. This example is pretty rare:
75+
Rather than installing it globally. This example is pretty rare:
7476

7577
```bash
7678
vite dev
7779
```
7880

79-
So in this case, a computer might have hundreds of Vite instances each installed separately and potentially from different versions on different projects.
81+
So in this case, a computer might have hundreds of Vite instances each installed separately and potentially from different versions on different projects.
8082

81-
We were looking for a fluid strategy that would be able to load the autocompletions from each of these dependencies on a per-project basis.
83+
We were looking for a fluid strategy that would be able to load the autocompletions from each of these dependencies on a per-project basis.
8284

83-
And that made us develop our own autocompletion abstraction over npm, pnpm and yarn. This would help tab identify which binaries are available in a project and which of these binaries provide autocompletions. So the user would not have to `source` anything or inject any script in their `.zshrc`.
85+
And that made us develop our own autocompletion abstraction over npm, pnpm and yarn. This would help tab identify which binaries are available in a project and which of these binaries provide autocompletions. So the user would not have to `source` anything or inject any script in their `.zshrc`.
8486

85-
They'd only have to run this command once and inject it in their shell config.
87+
They'd only have to run this command once and inject it in their shell config.
8688

8789
```bash
8890
npx @bombsh/tab pnpm zsh
8991
```
9092

9193
These autocompletions on top of the normal autocompletions that these package managers provide are going to be way more powerful.
9294

93-
These new autocompletions on top of package managers would help us with autocompletions on commands like `pnpm vite` and other global or per-project binaries. The only requirement would be that the npm binary itself would be a tab-compatible binary.
95+
These new autocompletions on top of package managers would help us with autocompletions on commands like `pnpm vite` and other global or per-project binaries. The only requirement would be that the npm binary itself would be a tab-compatible binary.
9496

9597
What is a tab-compatible binary? It's a tool that provides the `complete` subcommand that was showcased above. Basically any CLI tool that uses tab for its autocompletions is a tab-compatible binary.
9698

9799
```bash
98100
pnpm my-cli complete --
99101
```
102+
100103
```
101104
start start the development server
102105
:0
103106
```
104107

105-
We are planning to maintain these package manager autocompletions on our own and turn them into full-fledged autocompletions that touch on every part of our package managers.
108+
We are planning to maintain these package manager autocompletions on our own and turn them into full-fledged autocompletions that touch on every part of our package managers.

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# tab
32

43
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.

bin/completion-handlers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// TODO: i do not see any completion functionality in this file. nothing is being provided for the defined commands of these package managers. this is a blocker for release. every each of them should be handled.
1+
// TODO: i do not see any completion functionality in this file. nothing is being provided for the defined commands of these package managers. this is a blocker for release. every each of them should be handled.
22
import { Completion } from '../src/index.js';
33
import { execSync } from 'child_process';
44

@@ -72,7 +72,7 @@ export function setupCompletionForPackageManager(
7272
setupBunCompletions(completion);
7373
}
7474

75-
// TODO: the core functionality of tab should have nothing related to package managers. even though completion is not there anymore, but this is something to consider.
75+
// TODO: the core functionality of tab should have nothing related to package managers. even though completion is not there anymore, but this is something to consider.
7676
completion.setPackageManager(packageManager);
7777
}
7878

examples/demo.cac.ts

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ cli
99
.option('-m, --mode <mode>', `Set env mode`)
1010
.option('-l, --logLevel <level>', `info | warn | error | silent`);
1111

12-
13-
1412
cli
1513
.command('dev', 'Start dev server')
1614
.option('-H, --host [host]', `Specify hostname`)
@@ -25,7 +23,9 @@ cli
2523

2624
cli.command('dev build', 'Build project').action((options) => {});
2725

28-
cli.command('copy <source> <destination>', 'Copy files').action((source, destination, options) => {});
26+
cli
27+
.command('copy <source> <destination>', 'Copy files')
28+
.action((source, destination, options) => {});
2929

3030
cli.command('lint [...files]', 'Lint project').action((files, options) => {});
3131

@@ -35,12 +35,12 @@ await tab(cli, {
3535
subCommands: {
3636
copy: {
3737
args: {
38-
source: function(complete) {
38+
source: function (complete) {
3939
complete('src/', 'Source directory');
4040
complete('dist/', 'Distribution directory');
4141
complete('public/', 'Public assets');
4242
},
43-
destination: function(complete) {
43+
destination: function (complete) {
4444
complete('build/', 'Build output');
4545
complete('release/', 'Release directory');
4646
complete('backup/', 'Backup location');
@@ -49,35 +49,55 @@ await tab(cli, {
4949
},
5050
lint: {
5151
args: {
52-
files: function(complete) {
52+
files: function (complete) {
5353
complete('main.ts', 'Main file');
5454
complete('index.ts', 'Index file');
5555
},
5656
},
5757
},
5858
dev: {
5959
options: {
60-
port: function(this: Option, complete: (value: string, description: string) => void, options: OptionsMap) {
60+
port: function (
61+
this: Option,
62+
complete: (value: string, description: string) => void,
63+
options: OptionsMap
64+
) {
6165
complete('3000', 'Development server port');
6266
complete('8080', 'Alternative port');
6367
},
64-
host: function(this: Option, complete: (value: string, description: string) => void, options: OptionsMap) {
68+
host: function (
69+
this: Option,
70+
complete: (value: string, description: string) => void,
71+
options: OptionsMap
72+
) {
6573
complete('localhost', 'Localhost');
6674
complete('0.0.0.0', 'All interfaces');
6775
},
6876
},
6977
},
7078
},
7179
options: {
72-
config: function(this: Option, complete: (value: string, description: string) => void, options: OptionsMap) {
80+
config: function (
81+
this: Option,
82+
complete: (value: string, description: string) => void,
83+
options: OptionsMap
84+
) {
7385
complete('vite.config.ts', 'Vite config file');
7486
complete('vite.config.js', 'Vite config file');
7587
},
76-
mode: function(this: Option, complete: (value: string, description: string) => void, options: OptionsMap) {
88+
mode: function (
89+
this: Option,
90+
complete: (value: string, description: string) => void,
91+
options: OptionsMap
92+
) {
7793
complete('development', 'Development mode');
7894
complete('production', 'Production mode');
7995
},
80-
logLevel: function(this: Option, complete: (value: string, description: string) => void, options: OptionsMap) {
96+
logLevel: function (
97+
this: Option,
98+
complete: (value: string, description: string) => void,
99+
options: OptionsMap
100+
) {
81101
complete('info', 'Info level');
82102
complete('warn', 'Warn level');
83103
complete('error', 'Error level');

examples/demo.citty.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { defineCommand, createMain, type CommandDef, type ArgsDef } from 'citty';
1+
import {
2+
defineCommand,
3+
createMain,
4+
type CommandDef,
5+
type ArgsDef,
6+
} from 'citty';
27
import tab from '../src/citty';
38

49
const main = defineCommand({
@@ -104,22 +109,22 @@ main.subCommands = {
104109

105110
const completion = await tab(main, {
106111
args: {
107-
project: function(complete) {
112+
project: function (complete) {
108113
complete('my-app', 'My application');
109114
complete('my-lib', 'My library');
110115
complete('my-tool', 'My tool');
111116
},
112117
},
113118
options: {
114-
config: function(this: any, complete) {
119+
config: function (this: any, complete) {
115120
complete('vite.config.ts', 'Vite config file');
116121
complete('vite.config.js', 'Vite config file');
117122
},
118-
mode: function(this: any, complete) {
123+
mode: function (this: any, complete) {
119124
complete('development', 'Development mode');
120125
complete('production', 'Production mode');
121126
},
122-
logLevel: function(this: any, complete) {
127+
logLevel: function (this: any, complete) {
123128
complete('info', 'Info level');
124129
complete('warn', 'Warn level');
125130
complete('error', 'Error level');
@@ -130,12 +135,12 @@ const completion = await tab(main, {
130135
subCommands: {
131136
copy: {
132137
args: {
133-
source: function(complete) {
138+
source: function (complete) {
134139
complete('src/', 'Source directory');
135140
complete('dist/', 'Distribution directory');
136141
complete('public/', 'Public assets');
137142
},
138-
destination: function(complete) {
143+
destination: function (complete) {
139144
complete('build/', 'Build output');
140145
complete('release/', 'Release directory');
141146
complete('backup/', 'Backup location');
@@ -144,19 +149,19 @@ const completion = await tab(main, {
144149
},
145150
lint: {
146151
args: {
147-
files: function(complete) {
152+
files: function (complete) {
148153
complete('main.ts', 'Main file');
149154
complete('index.ts', 'Index file');
150155
},
151156
},
152157
},
153158
dev: {
154159
options: {
155-
port: function(this: any, complete) {
160+
port: function (this: any, complete) {
156161
complete('3000', 'Development server port');
157162
complete('8080', 'Alternative port');
158163
},
159-
host: function(this: any, complete) {
164+
host: function (this: any, complete) {
160165
complete('localhost', 'Localhost');
161166
complete('0.0.0.0', 'All interfaces');
162167
},

0 commit comments

Comments
 (0)