bet-cli 0.1.1 → 0.1.2

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.
package/README.md CHANGED
@@ -77,6 +77,15 @@ After that:
77
77
  - `bet go <slug>` will `cd` your current shell into the project
78
78
  - `bet list` / `bet search` can also “select and jump” in interactive mode
79
79
 
80
+ **Project name autocompletion:** To complete project names (slugs) when using `bet go`, `bet path`, or `bet info`, add to your rc file:
81
+
82
+ ```sh
83
+ eval "$(bet completion zsh)" # zsh
84
+ eval "$(bet completion bash)" # bash
85
+ ```
86
+
87
+ Then Tab-complete the slug argument after `bet go `, `bet path `, or `bet info `.
88
+
80
89
  ## Core commands
81
90
 
82
91
  - **`bet update`**: Scan configured roots and rebuild the project index.
@@ -94,6 +103,7 @@ After that:
94
103
  - **`--print`**: print selected path only (no shell `cd`)
95
104
  - **`--no-enter`**: do not run the project’s `onEnter` hook (if configured)
96
105
  - **`bet shell`**: Print the shell integration snippet (see above).
106
+ - **`bet completion [bash|zsh]`**: Print shell completion script for project name autocompletion (see above).
97
107
 
98
108
  ## Config & data files
99
109
 
@@ -0,0 +1,108 @@
1
+ import { getProjectSlugs } from "../lib/completion.js";
2
+ const SLUG_COMMANDS = ["go", "path", "info"];
3
+ const SUBCOMMANDS = [
4
+ "update",
5
+ "list",
6
+ "search",
7
+ "info",
8
+ "go",
9
+ "path",
10
+ "shell",
11
+ "completion",
12
+ ];
13
+ function zshScript() {
14
+ const slugCommandsPattern = SLUG_COMMANDS.join("|");
15
+ return `#compdef bet
16
+ _bet() {
17
+ local -a subcommands
18
+ subcommands=(
19
+ 'update:Scan roots and rebuild project index'
20
+ 'list:List projects'
21
+ 'search:Fuzzy-search projects'
22
+ 'info:Show project details'
23
+ 'go:Jump to a project'
24
+ 'path:Print project path'
25
+ 'shell:Print shell integration'
26
+ 'completion:Print shell completion script'
27
+ )
28
+
29
+ if (( CURRENT == 2 )); then
30
+ _describe 'bet commands' subcommands
31
+ return
32
+ fi
33
+
34
+ if [[ "${slugCommandsPattern}" == *"\$words[2]"* ]]; then
35
+ if (( CURRENT == 3 )); then
36
+ local -a slugs
37
+ slugs=(\$(command bet completion --list 2>/dev/null))
38
+ _describe 'project' slugs
39
+ fi
40
+ return
41
+ fi
42
+
43
+ _default
44
+ }
45
+ compdef _bet bet
46
+ `;
47
+ }
48
+ function bashScript() {
49
+ const subcommandsList = SUBCOMMANDS.join(" ");
50
+ const cw = "COMP_WORDS";
51
+ const cc = "COMP_CWORD";
52
+ const dollar = "$";
53
+ return `_bet_completions() {
54
+ local cur="${dollar}{${cw}[${cc}]}"
55
+
56
+ if (( ${cc} == 1 )); then
57
+ COMPREPLY=(\$(compgen -W "${subcommandsList}" -- "${dollar}cur"))
58
+ return
59
+ fi
60
+
61
+ local cmd="${dollar}{${cw}[1]}"
62
+ if [[ "${dollar}cmd" == "go" || "${dollar}cmd" == "path" || "${dollar}cmd" == "info" ]]; then
63
+ if (( ${cc} == 2 )); then
64
+ local slugs
65
+ slugs=\$(command bet completion --list 2>/dev/null)
66
+ COMPREPLY=(\$(compgen -W "${dollar}slugs" -- "${dollar}cur"))
67
+ fi
68
+ fi
69
+ }
70
+ complete -F _bet_completions bet
71
+ `;
72
+ }
73
+ export function registerCompletion(program) {
74
+ program
75
+ .command("completion [shell]")
76
+ .description("Print shell completion script for project name autocompletion")
77
+ .option("--list", "Print project slugs only (for use by completion script)")
78
+ .option("--prefix <prefix>", "Filter slugs by prefix")
79
+ .action(async (shell, options) => {
80
+ if (options.list) {
81
+ let slugs = await getProjectSlugs();
82
+ if (options.prefix?.length) {
83
+ const p = options.prefix.toLowerCase();
84
+ slugs = slugs.filter((s) => s.toLowerCase().startsWith(p));
85
+ }
86
+ for (const slug of slugs) {
87
+ process.stdout.write(`${slug}\n`);
88
+ }
89
+ return;
90
+ }
91
+ const sh = shell?.toLowerCase() ?? "";
92
+ if (sh === "zsh") {
93
+ process.stdout.write(zshScript());
94
+ return;
95
+ }
96
+ if (sh === "bash") {
97
+ process.stdout.write(bashScript());
98
+ return;
99
+ }
100
+ if (shell !== undefined) {
101
+ process.stderr.write(`Unknown shell "${shell}". Use bash or zsh.\n`);
102
+ process.exitCode = 1;
103
+ return;
104
+ }
105
+ process.stderr.write("Usage: bet completion [bash|zsh]\n eval \"$(bet completion zsh)\"\n");
106
+ process.exitCode = 1;
107
+ });
108
+ }
package/dist/index.js CHANGED
@@ -7,6 +7,7 @@ import { registerInfo } from "./commands/info.js";
7
7
  import { registerGo } from "./commands/go.js";
8
8
  import { registerPath } from "./commands/path.js";
9
9
  import { registerShell } from "./commands/shell.js";
10
+ import { registerCompletion } from "./commands/completion.js";
10
11
  const program = new Command();
11
12
  program
12
13
  .name("bet")
@@ -19,4 +20,5 @@ registerInfo(program);
19
20
  registerGo(program);
20
21
  registerPath(program);
21
22
  registerShell(program);
23
+ registerCompletion(program);
22
24
  program.parseAsync(process.argv);
@@ -0,0 +1,16 @@
1
+ import { readConfig } from "./config.js";
2
+ import { listProjects } from "./projects.js";
3
+ /**
4
+ * Returns project slugs for shell completion. On missing config or error,
5
+ * returns an empty array so the completion path can exit 0 with no output.
6
+ */
7
+ export async function getProjectSlugs() {
8
+ try {
9
+ const config = await readConfig();
10
+ const projects = listProjects(config);
11
+ return projects.map((p) => p.slug);
12
+ }
13
+ catch {
14
+ return [];
15
+ }
16
+ }
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "bet-cli",
3
3
  "description": "Explore and jump between local projects.",
4
+ "version": "0.1.2",
4
5
  "author": "Chris Mckenzie",
5
6
  "license": "Apache-2.0",
6
7
  "repository": {
@@ -14,7 +15,6 @@
14
15
  "management",
15
16
  "navigation"
16
17
  ],
17
- "version": "0.1.1",
18
18
  "type": "module",
19
19
  "bin": {
20
20
  "bet": "dist/index.js"
@@ -0,0 +1,125 @@
1
+ import { Command } from "commander";
2
+ import { getProjectSlugs } from "../lib/completion.js";
3
+
4
+ const SLUG_COMMANDS = ["go", "path", "info"];
5
+ const SUBCOMMANDS = [
6
+ "update",
7
+ "list",
8
+ "search",
9
+ "info",
10
+ "go",
11
+ "path",
12
+ "shell",
13
+ "completion",
14
+ ];
15
+
16
+ function zshScript(): string {
17
+ const slugCommandsPattern = SLUG_COMMANDS.join("|");
18
+ return `#compdef bet
19
+ _bet() {
20
+ local -a subcommands
21
+ subcommands=(
22
+ 'update:Scan roots and rebuild project index'
23
+ 'list:List projects'
24
+ 'search:Fuzzy-search projects'
25
+ 'info:Show project details'
26
+ 'go:Jump to a project'
27
+ 'path:Print project path'
28
+ 'shell:Print shell integration'
29
+ 'completion:Print shell completion script'
30
+ )
31
+
32
+ if (( CURRENT == 2 )); then
33
+ _describe 'bet commands' subcommands
34
+ return
35
+ fi
36
+
37
+ if [[ "${slugCommandsPattern}" == *"\$words[2]"* ]]; then
38
+ if (( CURRENT == 3 )); then
39
+ local -a slugs
40
+ slugs=(\$(command bet completion --list 2>/dev/null))
41
+ _describe 'project' slugs
42
+ fi
43
+ return
44
+ fi
45
+
46
+ _default
47
+ }
48
+ compdef _bet bet
49
+ `;
50
+ }
51
+
52
+ function bashScript(): string {
53
+ const subcommandsList = SUBCOMMANDS.join(" ");
54
+ const cw = "COMP_WORDS";
55
+ const cc = "COMP_CWORD";
56
+ const dollar = "$";
57
+ return `_bet_completions() {
58
+ local cur="${dollar}{${cw}[${cc}]}"
59
+
60
+ if (( ${cc} == 1 )); then
61
+ COMPREPLY=(\$(compgen -W "${subcommandsList}" -- "${dollar}cur"))
62
+ return
63
+ fi
64
+
65
+ local cmd="${dollar}{${cw}[1]}"
66
+ if [[ "${dollar}cmd" == "go" || "${dollar}cmd" == "path" || "${dollar}cmd" == "info" ]]; then
67
+ if (( ${cc} == 2 )); then
68
+ local slugs
69
+ slugs=\$(command bet completion --list 2>/dev/null)
70
+ COMPREPLY=(\$(compgen -W "${dollar}slugs" -- "${dollar}cur"))
71
+ fi
72
+ fi
73
+ }
74
+ complete -F _bet_completions bet
75
+ `;
76
+ }
77
+
78
+ export function registerCompletion(program: Command): void {
79
+ program
80
+ .command("completion [shell]")
81
+ .description("Print shell completion script for project name autocompletion")
82
+ .option("--list", "Print project slugs only (for use by completion script)")
83
+ .option("--prefix <prefix>", "Filter slugs by prefix")
84
+ .action(
85
+ async (
86
+ shell: string | undefined,
87
+ options: { list?: boolean; prefix?: string },
88
+ ) => {
89
+ if (options.list) {
90
+ let slugs = await getProjectSlugs();
91
+ if (options.prefix?.length) {
92
+ const p = options.prefix.toLowerCase();
93
+ slugs = slugs.filter((s) => s.toLowerCase().startsWith(p));
94
+ }
95
+ for (const slug of slugs) {
96
+ process.stdout.write(`${slug}\n`);
97
+ }
98
+ return;
99
+ }
100
+
101
+ const sh = shell?.toLowerCase() ?? "";
102
+ if (sh === "zsh") {
103
+ process.stdout.write(zshScript());
104
+ return;
105
+ }
106
+ if (sh === "bash") {
107
+ process.stdout.write(bashScript());
108
+ return;
109
+ }
110
+
111
+ if (shell !== undefined) {
112
+ process.stderr.write(
113
+ `Unknown shell "${shell}". Use bash or zsh.\n`,
114
+ );
115
+ process.exitCode = 1;
116
+ return;
117
+ }
118
+
119
+ process.stderr.write(
120
+ "Usage: bet completion [bash|zsh]\n eval \"$(bet completion zsh)\"\n",
121
+ );
122
+ process.exitCode = 1;
123
+ },
124
+ );
125
+ }
package/src/index.ts CHANGED
@@ -7,13 +7,14 @@ import { registerInfo } from "./commands/info.js";
7
7
  import { registerGo } from "./commands/go.js";
8
8
  import { registerPath } from "./commands/path.js";
9
9
  import { registerShell } from "./commands/shell.js";
10
+ import { registerCompletion } from "./commands/completion.js";
10
11
 
11
12
  const program = new Command();
12
13
 
13
14
  program
14
15
  .name("bet")
15
16
  .description("Explore and jump between local projects.")
16
- .version("0.1.0");
17
+ .version("0.1.2");
17
18
 
18
19
  registerUpdate(program);
19
20
  registerList(program);
@@ -22,5 +23,6 @@ registerInfo(program);
22
23
  registerGo(program);
23
24
  registerPath(program);
24
25
  registerShell(program);
26
+ registerCompletion(program);
25
27
 
26
28
  program.parseAsync(process.argv);
@@ -0,0 +1,16 @@
1
+ import { readConfig } from "./config.js";
2
+ import { listProjects } from "./projects.js";
3
+
4
+ /**
5
+ * Returns project slugs for shell completion. On missing config or error,
6
+ * returns an empty array so the completion path can exit 0 with no output.
7
+ */
8
+ export async function getProjectSlugs(): Promise<string[]> {
9
+ try {
10
+ const config = await readConfig();
11
+ const projects = listProjects(config);
12
+ return projects.map((p) => p.slug);
13
+ } catch {
14
+ return [];
15
+ }
16
+ }