bet-cli 0.1.3 → 0.1.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.
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
+ import { GroupedHelp } from "./lib/help.js";
3
4
  import { registerUpdate } from "./commands/update.js";
4
5
  import { registerList } from "./commands/list.js";
5
6
  import { registerSearch } from "./commands/search.js";
@@ -10,10 +11,13 @@ import { registerShell } from "./commands/shell.js";
10
11
  import { registerCompletion } from "./commands/completion.js";
11
12
  import { registerIgnore } from "./commands/ignore.js";
12
13
  const program = new Command();
14
+ program.createHelp = function createHelp() {
15
+ return Object.assign(new GroupedHelp(), this.configureHelp());
16
+ };
13
17
  program
14
18
  .name("bet")
15
19
  .description("Explore and jump between local projects.")
16
- .version("0.1.2");
20
+ .version("0.1.3");
17
21
  registerUpdate(program);
18
22
  registerList(program);
19
23
  registerSearch(program);
@@ -0,0 +1,81 @@
1
+ import { Help } from "commander";
2
+ const GROUP_1 = ["list", "search", "info", "go", "path"];
3
+ const GROUP_2 = ["shell", "completion"];
4
+ const GROUP_3 = ["update", "ignore", "help"];
5
+ const GROUPS = [
6
+ { heading: "Projects", names: GROUP_1 },
7
+ { heading: "Shell integration", names: GROUP_2 },
8
+ { heading: "Index & config", names: GROUP_3 },
9
+ ];
10
+ function getGroupIndex(cmdName) {
11
+ for (let i = 0; i < GROUPS.length; i++) {
12
+ if (GROUPS[i].names.includes(cmdName))
13
+ return i;
14
+ }
15
+ return GROUPS.length; // unlisted commands go last
16
+ }
17
+ /**
18
+ * Custom Help that renders top-level commands in three groups with headings.
19
+ */
20
+ export class GroupedHelp extends Help {
21
+ formatHelp(cmd, helper) {
22
+ const termWidth = helper.padWidth(cmd, helper);
23
+ const helpWidth = helper.helpWidth ?? 80;
24
+ const itemIndentWidth = 2;
25
+ const itemSeparatorWidth = 2;
26
+ const formatItem = (term, description) => {
27
+ if (description) {
28
+ const fullText = `${term.padEnd(termWidth + itemSeparatorWidth)}${description}`;
29
+ return helper.wrap(fullText, helpWidth - itemIndentWidth, termWidth + itemSeparatorWidth);
30
+ }
31
+ return term;
32
+ };
33
+ const formatList = (textArray) => textArray.join("\n").replace(/^/gm, " ".repeat(itemIndentWidth));
34
+ const output = [];
35
+ // Usage
36
+ output.push(`Usage: ${helper.commandUsage(cmd)}`, "");
37
+ // Description
38
+ const commandDescription = helper.commandDescription(cmd);
39
+ if (commandDescription.length > 0) {
40
+ output.push(helper.wrap(commandDescription, helpWidth, 0), "");
41
+ }
42
+ // Arguments
43
+ const argumentList = helper.visibleArguments(cmd).map((argument) => formatItem(helper.argumentTerm(argument), helper.argumentDescription(argument)));
44
+ if (argumentList.length > 0) {
45
+ output.push("Arguments:", formatList(argumentList), "");
46
+ }
47
+ // Options
48
+ const optionList = helper.visibleOptions(cmd).map((option) => formatItem(helper.optionTerm(option), helper.optionDescription(option)));
49
+ if (optionList.length > 0) {
50
+ output.push("Options:", formatList(optionList), "");
51
+ }
52
+ if (this.showGlobalOptions) {
53
+ const globalOptionList = helper
54
+ .visibleGlobalOptions(cmd)
55
+ .map((option) => formatItem(helper.optionTerm(option), helper.optionDescription(option)));
56
+ if (globalOptionList.length > 0) {
57
+ output.push("Global Options:", formatList(globalOptionList), "");
58
+ }
59
+ }
60
+ // Commands (grouped)
61
+ const visibleCommands = helper.visibleCommands(cmd);
62
+ if (visibleCommands.length > 0) {
63
+ const byGroup = new Map();
64
+ for (const sub of visibleCommands) {
65
+ const name = sub.name();
66
+ const idx = getGroupIndex(name);
67
+ const list = byGroup.get(idx) ?? [];
68
+ list.push(sub);
69
+ byGroup.set(idx, list);
70
+ }
71
+ const groupIndices = [...byGroup.keys()].sort((a, b) => a - b);
72
+ for (const idx of groupIndices) {
73
+ const commands = byGroup.get(idx);
74
+ const heading = idx < GROUPS.length ? GROUPS[idx].heading : "Commands";
75
+ const commandList = commands.map((sub) => formatItem(helper.subcommandTerm(sub), helper.subcommandDescription(sub)));
76
+ output.push(`${heading}:`, formatList(commandList), "");
77
+ }
78
+ }
79
+ return output.join("\n");
80
+ }
81
+ }
@@ -1,14 +1,50 @@
1
1
  import { isSubpath } from "../utils/paths.js";
2
2
  export const DEFAULT_IGNORES = [
3
+ // JS/TS/Node
3
4
  "**/node_modules/**",
4
5
  "**/.git/**",
5
6
  "**/dist/**",
6
7
  "**/build/**",
7
8
  "**/.next/**",
9
+ // Rust, Scala, Java (Maven)
8
10
  "**/target/**",
11
+ // PHP, Ruby, Go
9
12
  "**/vendor/**",
13
+ // Python
10
14
  "**/.venv/**",
11
15
  "**/venv/**",
16
+ "**/__pycache__/**",
17
+ "**/.mypy_cache/**",
18
+ "**/.pytest_cache/**",
19
+ "**/.eggs/**",
20
+ "**/*.egg-info/**",
21
+ "**/*.egg",
22
+ // Ruby
23
+ "**/.bundle/**",
24
+ "**/vendor/bundle/**",
25
+ // PHP (Symfony, Laravel cache/log)
26
+ "**/var/cache/**",
27
+ "**/var/log/**",
28
+ // Java/Kotlin (Gradle, IntelliJ output)
29
+ "**/.gradle/**",
30
+ "**/out/**",
31
+ // Elixir
32
+ "**/deps/**",
33
+ "**/_build/**",
34
+ // Swift
35
+ "**/.build/**",
36
+ "**/DerivedData/**",
37
+ // Dart/Flutter
38
+ "**/.dart_tool/**",
39
+ "**/.packages",
40
+ // C# / .NET
41
+ "**/obj/**",
42
+ // Haskell
43
+ "**/.stack-work/**",
44
+ "**/.cabal-sandbox/**",
45
+ // Scala (Metals)
46
+ "**/.metals/**",
47
+ "**/.bloop/**",
12
48
  ];
13
49
  export function getEffectiveIgnores(config) {
14
50
  return config.ignores !== undefined ? config.ignores : DEFAULT_IGNORES;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "bet-cli",
3
3
  "description": "Explore and jump between local projects.",
4
- "version": "0.1.3",
4
+ "version": "0.1.4",
5
5
  "author": "Chris Mckenzie",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
+ import { GroupedHelp } from "./lib/help.js";
3
4
  import { registerUpdate } from "./commands/update.js";
4
5
  import { registerList } from "./commands/list.js";
5
6
  import { registerSearch } from "./commands/search.js";
@@ -12,10 +13,14 @@ import { registerIgnore } from "./commands/ignore.js";
12
13
 
13
14
  const program = new Command();
14
15
 
16
+ program.createHelp = function createHelp(this: Command) {
17
+ return Object.assign(new GroupedHelp(), this.configureHelp());
18
+ };
19
+
15
20
  program
16
21
  .name("bet")
17
22
  .description("Explore and jump between local projects.")
18
- .version("0.1.3");
23
+ .version("0.1.4");
19
24
 
20
25
  registerUpdate(program);
21
26
  registerList(program);
@@ -0,0 +1,122 @@
1
+ import { Help } from "commander";
2
+ import type { Command } from "commander";
3
+
4
+ const GROUP_1: string[] = ["list", "search", "info", "go", "path"];
5
+ const GROUP_2: string[] = ["shell", "completion"];
6
+ const GROUP_3: string[] = ["update", "ignore", "help"];
7
+
8
+ const GROUPS: { heading: string; names: string[] }[] = [
9
+ { heading: "Projects", names: GROUP_1 },
10
+ { heading: "Shell integration", names: GROUP_2 },
11
+ { heading: "Index & config", names: GROUP_3 },
12
+ ];
13
+
14
+ function getGroupIndex(cmdName: string): number {
15
+ for (let i = 0; i < GROUPS.length; i++) {
16
+ if (GROUPS[i].names.includes(cmdName)) return i;
17
+ }
18
+ return GROUPS.length; // unlisted commands go last
19
+ }
20
+
21
+ /**
22
+ * Custom Help that renders top-level commands in three groups with headings.
23
+ */
24
+ export class GroupedHelp extends Help {
25
+ override formatHelp(cmd: Command, helper: Help): string {
26
+ const termWidth = helper.padWidth(cmd, helper);
27
+ const helpWidth = helper.helpWidth ?? 80;
28
+ const itemIndentWidth = 2;
29
+ const itemSeparatorWidth = 2;
30
+
31
+ const formatItem = (term: string, description: string): string => {
32
+ if (description) {
33
+ const fullText = `${term.padEnd(termWidth + itemSeparatorWidth)}${description}`;
34
+ return helper.wrap(
35
+ fullText,
36
+ helpWidth - itemIndentWidth,
37
+ termWidth + itemSeparatorWidth,
38
+ );
39
+ }
40
+ return term;
41
+ };
42
+
43
+ const formatList = (textArray: string[]): string =>
44
+ textArray.join("\n").replace(/^/gm, " ".repeat(itemIndentWidth));
45
+
46
+ const output: string[] = [];
47
+
48
+ // Usage
49
+ output.push(`Usage: ${helper.commandUsage(cmd)}`, "");
50
+
51
+ // Description
52
+ const commandDescription = helper.commandDescription(cmd);
53
+ if (commandDescription.length > 0) {
54
+ output.push(helper.wrap(commandDescription, helpWidth, 0), "");
55
+ }
56
+
57
+ // Arguments
58
+ const argumentList = helper.visibleArguments(cmd).map((argument) =>
59
+ formatItem(
60
+ helper.argumentTerm(argument),
61
+ helper.argumentDescription(argument),
62
+ ),
63
+ );
64
+ if (argumentList.length > 0) {
65
+ output.push("Arguments:", formatList(argumentList), "");
66
+ }
67
+
68
+ // Options
69
+ const optionList = helper.visibleOptions(cmd).map((option) =>
70
+ formatItem(
71
+ helper.optionTerm(option),
72
+ helper.optionDescription(option),
73
+ ),
74
+ );
75
+ if (optionList.length > 0) {
76
+ output.push("Options:", formatList(optionList), "");
77
+ }
78
+
79
+ if (this.showGlobalOptions) {
80
+ const globalOptionList = helper
81
+ .visibleGlobalOptions(cmd)
82
+ .map((option) =>
83
+ formatItem(
84
+ helper.optionTerm(option),
85
+ helper.optionDescription(option),
86
+ ),
87
+ );
88
+ if (globalOptionList.length > 0) {
89
+ output.push("Global Options:", formatList(globalOptionList), "");
90
+ }
91
+ }
92
+
93
+ // Commands (grouped)
94
+ const visibleCommands = helper.visibleCommands(cmd);
95
+ if (visibleCommands.length > 0) {
96
+ const byGroup = new Map<number, Command[]>();
97
+ for (const sub of visibleCommands) {
98
+ const name = sub.name();
99
+ const idx = getGroupIndex(name);
100
+ const list = byGroup.get(idx) ?? [];
101
+ list.push(sub);
102
+ byGroup.set(idx, list);
103
+ }
104
+
105
+ const groupIndices = [...byGroup.keys()].sort((a, b) => a - b);
106
+ for (const idx of groupIndices) {
107
+ const commands = byGroup.get(idx)!;
108
+ const heading =
109
+ idx < GROUPS.length ? GROUPS[idx].heading : "Commands";
110
+ const commandList = commands.map((sub) =>
111
+ formatItem(
112
+ helper.subcommandTerm(sub),
113
+ helper.subcommandDescription(sub),
114
+ ),
115
+ );
116
+ output.push(`${heading}:`, formatList(commandList), "");
117
+ }
118
+ }
119
+
120
+ return output.join("\n");
121
+ }
122
+ }
package/src/lib/ignore.ts CHANGED
@@ -1,22 +1,61 @@
1
1
  import { isSubpath } from "../utils/paths.js";
2
2
 
3
3
  export const DEFAULT_IGNORES = [
4
+ // JS/TS/Node
4
5
  "**/node_modules/**",
5
6
  "**/.git/**",
6
7
  "**/dist/**",
7
8
  "**/build/**",
8
9
  "**/.next/**",
10
+ // Rust, Scala, Java (Maven)
9
11
  "**/target/**",
12
+ // PHP, Ruby, Go
10
13
  "**/vendor/**",
14
+ // Python
11
15
  "**/.venv/**",
12
16
  "**/venv/**",
17
+ "**/__pycache__/**",
18
+ "**/.mypy_cache/**",
19
+ "**/.pytest_cache/**",
20
+ "**/.eggs/**",
21
+ "**/*.egg-info/**",
22
+ "**/*.egg",
23
+ // Ruby
24
+ "**/.bundle/**",
25
+ "**/vendor/bundle/**",
26
+ // PHP (Symfony, Laravel cache/log)
27
+ "**/var/cache/**",
28
+ "**/var/log/**",
29
+ // Java/Kotlin (Gradle, IntelliJ output)
30
+ "**/.gradle/**",
31
+ "**/out/**",
32
+ // Elixir
33
+ "**/deps/**",
34
+ "**/_build/**",
35
+ // Swift
36
+ "**/.build/**",
37
+ "**/DerivedData/**",
38
+ // Dart/Flutter
39
+ "**/.dart_tool/**",
40
+ "**/.packages",
41
+ // C# / .NET
42
+ "**/obj/**",
43
+ // Haskell
44
+ "**/.stack-work/**",
45
+ "**/.cabal-sandbox/**",
46
+ // Scala (Metals)
47
+ "**/.metals/**",
48
+ "**/.bloop/**",
13
49
  ];
14
50
 
15
51
  export function getEffectiveIgnores(config: { ignores?: string[] }): string[] {
16
52
  return config.ignores !== undefined ? config.ignores : DEFAULT_IGNORES;
17
53
  }
18
54
 
19
- export function isPathIgnored(projectPath: string, ignoredPaths: string[]): boolean {
55
+ export function isPathIgnored(
56
+ projectPath: string,
57
+ ignoredPaths: string[],
58
+ ): boolean {
20
59
  if (ignoredPaths.length === 0) return false;
21
60
  return ignoredPaths.some(
22
61
  (ip) => projectPath === ip || isSubpath(projectPath, ip),