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 +5 -1
- package/dist/lib/help.js +81 -0
- package/dist/lib/ignore.js +36 -0
- package/package.json +1 -1
- package/src/index.ts +6 -1
- package/src/lib/help.ts +122 -0
- package/src/lib/ignore.ts +40 -1
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.
|
|
20
|
+
.version("0.1.3");
|
|
17
21
|
registerUpdate(program);
|
|
18
22
|
registerList(program);
|
|
19
23
|
registerSearch(program);
|
package/dist/lib/help.js
ADDED
|
@@ -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
|
+
}
|
package/dist/lib/ignore.js
CHANGED
|
@@ -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
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.
|
|
23
|
+
.version("0.1.4");
|
|
19
24
|
|
|
20
25
|
registerUpdate(program);
|
|
21
26
|
registerList(program);
|
package/src/lib/help.ts
ADDED
|
@@ -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(
|
|
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),
|