Skip to content

Commit f2f1cf7

Browse files
Refactor CLI setup and command handling
1 parent 242c591 commit f2f1cf7

File tree

1 file changed

+89
-68
lines changed

1 file changed

+89
-68
lines changed

bin/tldr

Lines changed: 89 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,107 @@
11
#!/usr/bin/env node
22

3-
const program = require('commander');
3+
const { Command } = require('commander'); // Commander 14
44
const pkg = require('../package');
55
const Tldr = require('../lib/tldr');
66
const config = require('../lib/config');
77
const platforms = require('../lib/platforms');
88
const Completion = require('../lib/completion');
99
const { TldrError } = require('../lib/errors');
1010

11-
pkg.version = `v${pkg.version}\nClient Specification: 2.0`;
11+
const program = new Command();
1212

13+
pkg.version = `v${pkg.version} (Client Spec: 2.0)`;
14+
15+
// Basic CLI setup
1316
program
14-
.version(pkg.version)
17+
.name('tldr')
18+
.version(pkg.version) // Commander 14 only takes version string
1519
.description(pkg.description)
1620
.usage('command [options]')
17-
//
18-
// BASIC OPTIONS
19-
//
21+
22+
// --------------------
23+
// BASIC OPTIONS
24+
// --------------------
25+
program
2026
.option('-l, --list', 'List all commands for the chosen platform in the cache')
2127
.option('-a, --list-all', 'List all commands in the cache')
22-
.option('-1, --single-column', 'List single command per line (use with options -l or -a)')
28+
.option('-1, --single-column', 'List single command per line (use with -l or -a)')
2329
.option('-r, --random', 'Show a random command')
2430
.option('-e, --random-example', 'Show a random example')
2531
.option('-f, --render [file]', 'Render a specific markdown [file]')
2632
.option('-m, --markdown', 'Output in markdown format')
2733
.option('-p, --platform [type]', `Override the current platform [${platforms.supportedPlatforms.join(', ')}]`)
28-
.option('completion [shell]', 'Generate and add shell completion script to your shell configuration');
34+
.option('-t, --theme [theme]', 'Color theme (simple, base16, ocean)')
35+
.option('-s, --search [keywords]', 'Search pages using keywords')
36+
.option('-u, --update', 'Update the local cache')
37+
.option('-c, --clear-cache', 'Clear the local cache');
2938

39+
// Add flags for each supported platform
3040
for (const platform of platforms.supportedPlatforms) {
31-
program.option(`--${platform}`, `Override the platform with ${platform}`);
41+
program.option(`--${platform}`, `Override platform with ${platform}`);
3242
}
3343

44+
// --------------------
45+
// COMPLETION SUBCOMMAND
46+
// --------------------
3447
program
35-
.option('-t, --theme [theme]', 'Color theme (simple, base16, ocean)')
36-
.option('-s, --search [keywords]', 'Search pages using keywords')
37-
//
38-
// CACHE MANAGEMENT
39-
//
40-
.option('-u, --update', 'Update the local cache')
41-
.option('-c, --clear-cache', 'Clear the local cache');
48+
.command('completion [shell]')
49+
.description('Generate and add shell completion script to your shell configuration')
50+
.action(async (shell) => {
51+
try {
52+
const completion = new Completion(shell);
53+
const script = await completion.getScript();
54+
await completion.appendScript(script);
55+
56+
if (shell === 'zsh') {
57+
console.log('If completions don\'t work, rebuild ~/.zcompdump:');
58+
console.log(' rm -f ~/.zcompdump; compinit');
59+
}
60+
} catch (err) {
61+
console.error(err.stack || err);
62+
process.exit(1);
63+
}
64+
});
4265

43-
const help = `
44-
Examples:
66+
// --------------------
67+
// CUSTOM HELP EXAMPLES
68+
// --------------------
69+
const helpText = `
70+
Examples:
4571
46-
$ tldr tar
47-
$ tldr du --platform=linux
48-
$ tldr --search "create symbolic link to file"
49-
$ tldr --list
50-
$ tldr --list-all
51-
$ tldr --random
52-
$ tldr --random-example
72+
$ tldr tar
73+
$ tldr du --platform=linux
74+
$ tldr --search "create symbolic link to file"
75+
$ tldr --list
76+
$ tldr --list-all
77+
$ tldr --random
78+
$ tldr --random-example
5379
54-
To control the cache:
80+
Cache control:
5581
56-
$ tldr --update
57-
$ tldr --clear-cache
82+
$ tldr --update
83+
$ tldr --clear-cache
5884
59-
To render a local file (for testing):
85+
Render local file:
6086
61-
$ tldr --render /path/to/file.md
62-
63-
To add shell completion:
87+
$ tldr --render /path/to/file.md
6488
65-
$ tldr completion bash
66-
$ tldr completion zsh
89+
Add shell completion:
90+
91+
$ tldr completion bash
92+
$ tldr completion zsh
6793
`;
6894

69-
program.on('--help', () => {
70-
console.log(help);
71-
});
95+
program.addHelpText('after', helpText);
7296

97+
// --------------------
98+
// PARSE ARGS
99+
// --------------------
73100
program.parse(process.argv);
74101

102+
// --------------------
103+
// PLATFORM OVERRIDE
104+
// --------------------
75105
for (const platform of platforms.supportedPlatforms) {
76106
if (program[platform]) {
77107
program.platform = platform;
@@ -82,59 +112,50 @@ let cfg = config.get();
82112
if (program.platform && platforms.isSupported(program.platform)) {
83113
cfg.platform = program.platform;
84114
}
85-
86115
if (program.theme) {
87116
cfg.theme = program.theme;
88117
}
89118

90119
const tldr = new Tldr(cfg);
91120

92-
let p = null;
121+
// --------------------
122+
// COMMAND HANDLING
123+
// --------------------
124+
let promise = null;
125+
93126
if (program.list) {
94-
p = tldr.list(program.singleColumn);
127+
promise = tldr.list(program.singleColumn);
95128
} else if (program.listAll) {
96-
p = tldr.listAll(program.singleColumn);
129+
promise = tldr.listAll(program.singleColumn);
97130
} else if (program.random) {
98-
p = tldr.random(program);
131+
promise = tldr.random(program);
99132
} else if (program.randomExample) {
100-
p = tldr.randomExample();
133+
promise = tldr.randomExample();
101134
} else if (program.clearCache) {
102-
p = tldr.clearCache();
135+
promise = tldr.clearCache();
103136
} else if (program.update) {
104-
p = tldr.updateCache()
105-
.then(() => {
106-
return tldr.updateIndex();
107-
});
137+
promise = tldr.updateCache()
138+
.then(() => tldr.updateIndex());
108139
} else if (program.render) {
109-
p = tldr.render(program.render);
140+
promise = tldr.render(program.render);
110141
} else if (program.search) {
111142
program.args.unshift(program.search);
112-
p = tldr.search(program.args);
143+
promise = tldr.search(program.args);
113144
} else if (program.args.length >= 1) {
114-
if (program.args[0] === 'completion') {
115-
const shell = program.args[1];
116-
const completion = new Completion(shell);
117-
p = completion.getScript()
118-
.then((script) => {return completion.appendScript(script);})
119-
.then(() => {
120-
if (shell === 'zsh') {
121-
console.log('If completions don\'t work, you may need to rebuild your zcompdump:');
122-
console.log(' rm -f ~/.zcompdump; compinit');
123-
}
124-
});
125-
} else {
126-
p = tldr.get(program.args, program);
127-
}
145+
promise = tldr.get(program.args, program);
128146
}
129147

130-
if (p === null) {
148+
// --------------------
149+
// EXIT HANDLING
150+
// --------------------
151+
if (!promise) {
131152
program.outputHelp();
132153
process.exitCode = 1;
133154
} else {
134-
p.catch((err) => {
135-
let output = TldrError.isTldrError(err)
155+
promise.catch((err) => {
156+
const output = TldrError.isTldrError(err)
136157
? err.message
137-
: err.stack;
158+
: err.stack || err;
138159
console.error(output);
139160
process.exitCode = err.code || 1;
140161
});

0 commit comments

Comments
 (0)