@n-seiji/nuthatch 0.1.7 → 0.2.1
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.ja.md +31 -21
- package/README.md +31 -21
- package/dist/{clean-n2f9z8n3.js → clean-rn2476my.js} +36 -27
- package/dist/cli-26d2drt6.js +30 -0
- package/dist/{cli-2bhb9p0x.js → cli-77yanq37.js} +3 -1
- package/dist/{cli-23z98dw1.js → cli-9n04gsq1.js} +22 -30
- package/dist/cli-a56b2ar0.js +20 -0
- package/dist/{cli-g72ra4e5.js → cli-b0tk5wcx.js} +1 -19
- package/dist/{cli-pqd2qe7v.js → cli-btqjpf1q.js} +1 -1
- package/dist/{cli-71jgs14h.js → cli-fhta3tr8.js} +15 -1
- package/dist/{cli-ygt2w4e1.js → cli-hz0r7zw8.js} +27 -28
- package/dist/{cli-qrxgkskr.js → cli-ph0gp56k.js} +6 -21
- package/dist/{cli-pick-w9qk71fy.js → cli-pick-yjd4qpd9.js} +64 -153
- package/dist/cli-s5qcjcwk.js +25 -0
- package/dist/{cli-3ya15je0.js → cli-sre95k9x.js} +6 -33
- package/dist/{cli-update-7exha1em.js → cli-update-x0r4b4xk.js} +82 -334
- package/dist/{cli-rcw5adqd.js → cli-wcnyhk4w.js} +1 -1
- package/dist/{cli-7jg5qqs9.js → cli-y8vsqre6.js} +22 -13
- package/dist/cli.js +56 -58
- package/dist/{init-s0dafa83.js → init-167d1bbs.js} +9 -10
- package/dist/{jump-nvdkeega.js → jump-1zkraat1.js} +10 -5
- package/dist/{ls-kvz4wmc9.js → ls-3hyjf60d.js} +3 -3
- package/dist/{render-ls-6r3vv7y0.js → render-ls-x4hpnsvy.js} +16 -27
- package/dist/rm-eg3j8ae1.js +7 -0
- package/dist/root-49vcb8x2.js +7 -0
- package/package.json +3 -4
- package/dist/rm-231qjgd8.js +0 -7
- package/dist/root-mmyazwc3.js +0 -7
- package/shell/init.zsh +0 -53
|
@@ -1,26 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EXIT_GENERAL_ERROR,
|
|
3
3
|
EXIT_SAFE_REJECTION
|
|
4
|
-
} from "./cli-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const trimmed = withoutTrailingSlash(path);
|
|
10
|
-
const index = trimmed.lastIndexOf("/");
|
|
11
|
-
if (index === -1) {
|
|
12
|
-
return ".";
|
|
13
|
-
}
|
|
14
|
-
return index === 0 ? "/" : trimmed.slice(0, index);
|
|
15
|
-
};
|
|
16
|
-
var baseName = (path) => {
|
|
17
|
-
const trimmed = withoutTrailingSlash(path);
|
|
18
|
-
return trimmed.slice(trimmed.lastIndexOf("/") + 1);
|
|
19
|
-
};
|
|
20
|
-
var absoluteCandidates = (dirs, name) => [
|
|
21
|
-
...new Set(dirs.map((entry) => entry.trim()).filter((entry) => entry.startsWith("/")).map((dir) => `${dir.endsWith("/") ? dir.slice(0, -1) : dir}/${name}`))
|
|
22
|
-
];
|
|
23
|
-
var splitPathEnv = (pathEnv) => (pathEnv ?? "").split(":");
|
|
4
|
+
} from "./cli-77yanq37.js";
|
|
5
|
+
import {
|
|
6
|
+
absoluteCandidates,
|
|
7
|
+
splitPathEnv
|
|
8
|
+
} from "./cli-s5qcjcwk.js";
|
|
24
9
|
|
|
25
10
|
// src/domain/git-executable.ts
|
|
26
11
|
var GIT_EXECUTABLE_OVERRIDE_ENV = "HOP_GIT";
|
|
@@ -66,4 +51,4 @@ var describeFatalError = (error) => {
|
|
|
66
51
|
return { message: messageOf(error), exitCode: EXIT_GENERAL_ERROR };
|
|
67
52
|
};
|
|
68
53
|
|
|
69
|
-
export {
|
|
54
|
+
export { GIT_EXECUTABLE_OVERRIDE_ENV, GIT_NOT_FOUND_ERROR_CODE, gitExecutableCandidates, gitNotFoundMessage, messageOf, describeFatalError };
|
|
@@ -1,29 +1,39 @@
|
|
|
1
|
-
import"./cli-
|
|
1
|
+
import"./cli-ph0gp56k.js";
|
|
2
2
|
import {
|
|
3
3
|
rm2
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-9n04gsq1.js";
|
|
5
5
|
import {
|
|
6
6
|
root2
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-hz0r7zw8.js";
|
|
8
8
|
import {
|
|
9
9
|
graphemes,
|
|
10
10
|
displayWidth,
|
|
11
11
|
padToWidth,
|
|
12
12
|
truncateToWidth,
|
|
13
|
-
truncateToWidthKeepingTail
|
|
14
|
-
|
|
13
|
+
truncateToWidthKeepingTail,
|
|
14
|
+
ESC,
|
|
15
|
+
SGR,
|
|
16
|
+
SGR_RESET
|
|
17
|
+
} from "./cli-fhta3tr8.js";
|
|
18
|
+
import {
|
|
19
|
+
colorEnabled
|
|
20
|
+
} from "./cli-26d2drt6.js";
|
|
15
21
|
import {
|
|
16
22
|
render,
|
|
17
23
|
reportResult
|
|
18
24
|
} from "./cli-dbzx9nzg.js";
|
|
19
25
|
import {
|
|
26
|
+
isOptionLikeRef,
|
|
20
27
|
loadRepoContext,
|
|
21
28
|
worktreeDirtyState
|
|
22
|
-
} from "./cli-
|
|
29
|
+
} from "./cli-y8vsqre6.js";
|
|
23
30
|
import {
|
|
24
31
|
EXIT_CANCELLED,
|
|
25
32
|
ok
|
|
26
|
-
} from "./cli-
|
|
33
|
+
} from "./cli-77yanq37.js";
|
|
34
|
+
import {
|
|
35
|
+
shortenHome
|
|
36
|
+
} from "./cli-s5qcjcwk.js";
|
|
27
37
|
|
|
28
38
|
// src/domain/candidates.ts
|
|
29
39
|
var buildPickCandidates = (worktrees, dirtyByPath, localBranches, remoteBranches) => {
|
|
@@ -33,9 +43,10 @@ var buildPickCandidates = (worktrees, dirtyByPath, localBranches, remoteBranches
|
|
|
33
43
|
worktree,
|
|
34
44
|
dirty: dirtyByPath.get(worktree.path) ?? null
|
|
35
45
|
}));
|
|
36
|
-
const
|
|
46
|
+
const usable = (branch) => !existingBranches.has(branch) && !isOptionLikeRef(branch);
|
|
47
|
+
const localOnly = localBranches.filter((branch) => usable(branch));
|
|
37
48
|
const localSet = new Set(localBranches);
|
|
38
|
-
const remoteOnly = remoteBranches.filter((branch) =>
|
|
49
|
+
const remoteOnly = remoteBranches.filter((branch) => usable(branch) && !localSet.has(branch));
|
|
39
50
|
return [
|
|
40
51
|
...worktreeCandidates,
|
|
41
52
|
...localOnly.map((branch) => ({
|
|
@@ -72,30 +83,16 @@ var pick = async (git, fs, options) => {
|
|
|
72
83
|
// src/ui/picker-render.ts
|
|
73
84
|
import { homedir } from "node:os";
|
|
74
85
|
|
|
75
|
-
// src/ui/ansi.ts
|
|
76
|
-
var ESC = "\x1B";
|
|
77
|
-
|
|
78
86
|
// src/ui/picker-frame.ts
|
|
79
87
|
var CURSOR_HOME = `${ESC}[H`;
|
|
80
88
|
var CLEAR_TO_END = `${ESC}[J`;
|
|
81
|
-
var
|
|
82
|
-
var SGR_CODES = {
|
|
83
|
-
plain: "",
|
|
84
|
-
cyan: `${ESC}[36m`,
|
|
85
|
-
dim: `${ESC}[2m`,
|
|
86
|
-
"bold-dim": `${ESC}[1m${ESC}[2m`,
|
|
87
|
-
inverse: `${ESC}[7m`,
|
|
88
|
-
red: `${ESC}[31m`,
|
|
89
|
-
green: `${ESC}[32m`,
|
|
90
|
-
yellow: `${ESC}[33m`,
|
|
91
|
-
magenta: `${ESC}[35m`
|
|
92
|
-
};
|
|
89
|
+
var sgrCode = (style) => style === "bold-dim" ? `${SGR.bold}${SGR.dim}` : SGR[style];
|
|
93
90
|
var renderSpan = (span, colorEnabled) => {
|
|
94
91
|
const style = span.style ?? "plain";
|
|
95
92
|
if (!colorEnabled || style === "plain") {
|
|
96
93
|
return span.text;
|
|
97
94
|
}
|
|
98
|
-
return `${
|
|
95
|
+
return `${sgrCode(style)}${span.text}${SGR_RESET}`;
|
|
99
96
|
};
|
|
100
97
|
var lineWidth = (line) => line.reduce((total, span) => total + displayWidth(span.text), 0);
|
|
101
98
|
var renderLine = (line, colorEnabled) => line.map((span) => renderSpan(span, colorEnabled)).join("");
|
|
@@ -268,20 +265,16 @@ var sortCandidatesForDisplay = (candidates) => [
|
|
|
268
265
|
...candidates.filter((candidate) => isCreatableCandidate(candidate)).toSorted((a, b) => compareCreatableCandidates(a, b))
|
|
269
266
|
];
|
|
270
267
|
var KIND_COLUMN_WIDTH = Math.max(...Object.values(WORKTREE_KIND_LABELS).map((label) => label.length), ...Object.values(CREATABLE_SOURCE_LABELS).map((label) => label.length));
|
|
271
|
-
var shortenPath = (path, homeDir, maxLength = MAX_PATH_LENGTH) =>
|
|
272
|
-
const withTilde = homeDir.length > 0 && (path === homeDir || path.startsWith(`${homeDir}/`)) ? `~${path.slice(homeDir.length)}` : path;
|
|
273
|
-
return truncateToWidthKeepingTail(withTilde, maxLength);
|
|
274
|
-
};
|
|
268
|
+
var shortenPath = (path, homeDir, maxLength = MAX_PATH_LENGTH) => truncateToWidthKeepingTail(shortenHome(path, homeDir), maxLength);
|
|
275
269
|
var candidatePathLabel = (candidate, homeDir, maxLength) => candidate.kind === "worktree" ? shortenPath(candidate.worktree.path, homeDir, maxLength) : "";
|
|
276
270
|
var rawBranchColumnWidth = (candidates) => candidates.reduce((max, candidate) => Math.max(max, displayWidth(candidateBranchLabel(candidate))), 0);
|
|
277
271
|
var branchColumnWidth = (candidates) => Math.min(MAX_BRANCH_COLUMN_WIDTH, rawBranchColumnWidth(candidates));
|
|
278
|
-
var padBranchLabel = (label, width) => padToWidth(label, width);
|
|
279
272
|
var toCandidateRow = (candidate, options) => ({
|
|
280
273
|
kind: "candidate",
|
|
281
274
|
index: options.index,
|
|
282
275
|
section: options.section,
|
|
283
276
|
statusMarker: statusMarker(candidate),
|
|
284
|
-
branchLabel:
|
|
277
|
+
branchLabel: padToWidth(truncateToWidth(candidateBranchLabel(candidate), options.branchWidth), options.branchWidth),
|
|
285
278
|
kindLabel: candidateKindLabel(candidate).padEnd(KIND_COLUMN_WIDTH, " "),
|
|
286
279
|
pathLabel: candidatePathLabel(candidate, options.homeDir, options.pathMaxLength)
|
|
287
280
|
});
|
|
@@ -575,8 +568,6 @@ var renderPickerFrame = ({
|
|
|
575
568
|
};
|
|
576
569
|
|
|
577
570
|
// src/ui/picker-keys.ts
|
|
578
|
-
var isCtrlJByte = (input) => input === `
|
|
579
|
-
`;
|
|
580
571
|
var resolvePickerKeyAction = (input, key) => {
|
|
581
572
|
if (key.escape) {
|
|
582
573
|
return { type: "cancel", reason: "esc" };
|
|
@@ -599,7 +590,7 @@ var resolvePickerKeyAction = (input, key) => {
|
|
|
599
590
|
if (key.upArrow || key.ctrl && (input === "p" || input === "k")) {
|
|
600
591
|
return { type: "up" };
|
|
601
592
|
}
|
|
602
|
-
if (key.downArrow || key.ctrl &&
|
|
593
|
+
if (key.downArrow || key.ctrl && input === "n") {
|
|
603
594
|
return { type: "down" };
|
|
604
595
|
}
|
|
605
596
|
if (key.ctrl && input === "u") {
|
|
@@ -608,7 +599,7 @@ var resolvePickerKeyAction = (input, key) => {
|
|
|
608
599
|
if (key.backspace || key.delete) {
|
|
609
600
|
return { type: "backspace" };
|
|
610
601
|
}
|
|
611
|
-
if (input.length > 0 && !key.ctrl
|
|
602
|
+
if (input.length > 0 && !key.ctrl) {
|
|
612
603
|
return { type: "char", char: input };
|
|
613
604
|
}
|
|
614
605
|
return { type: "ignore" };
|
|
@@ -624,17 +615,17 @@ var resolvePanelKeyAction = (input, key) => {
|
|
|
624
615
|
if (key.upArrow || key.ctrl && (input === "p" || input === "k")) {
|
|
625
616
|
return { type: "up" };
|
|
626
617
|
}
|
|
627
|
-
if (key.downArrow || key.ctrl &&
|
|
618
|
+
if (key.downArrow || key.ctrl && input === "n") {
|
|
628
619
|
return { type: "down" };
|
|
629
620
|
}
|
|
630
|
-
if (!key.ctrl &&
|
|
621
|
+
if (!key.ctrl && isPanelLetterShortcut(input)) {
|
|
631
622
|
return { type: "letter", char: input };
|
|
632
623
|
}
|
|
633
624
|
return { type: "ignore" };
|
|
634
625
|
};
|
|
635
626
|
var isPanelLetterShortcut = (input) => PANEL_LETTER_SHORTCUTS.includes(input);
|
|
636
627
|
var resolveConfirmKeyAction = (input, key) => {
|
|
637
|
-
if (!key.ctrl &&
|
|
628
|
+
if (!key.ctrl && (input === "y" || input === "Y")) {
|
|
638
629
|
return { type: "yes" };
|
|
639
630
|
}
|
|
640
631
|
return { type: "no" };
|
|
@@ -789,20 +780,14 @@ var createFilteredSelector = () => {
|
|
|
789
780
|
var runMutation = async (callbacks, candidate, action) => {
|
|
790
781
|
if (action === "switchRoot") {
|
|
791
782
|
const result = await callbacks.switchRootHere(candidate);
|
|
792
|
-
if (!result.ok
|
|
793
|
-
return {
|
|
794
|
-
type: "patch",
|
|
795
|
-
patch: panelErrorTransition(candidate, result.message ?? "Failed to switch root.")
|
|
796
|
-
};
|
|
783
|
+
if (!result.ok) {
|
|
784
|
+
return { type: "patch", patch: panelErrorTransition(candidate, result.message) };
|
|
797
785
|
}
|
|
798
786
|
return { type: "exit", outcome: { type: "path", path: result.path } };
|
|
799
787
|
}
|
|
800
788
|
const result = await callbacks.deleteWorktree(candidate);
|
|
801
789
|
if (!result.ok) {
|
|
802
|
-
return {
|
|
803
|
-
type: "patch",
|
|
804
|
-
patch: panelErrorTransition(candidate, result.message ?? "Failed to delete worktree.")
|
|
805
|
-
};
|
|
790
|
+
return { type: "patch", patch: panelErrorTransition(candidate, result.message) };
|
|
806
791
|
}
|
|
807
792
|
const fresh = await callbacks.reloadCandidates();
|
|
808
793
|
return {
|
|
@@ -953,7 +938,6 @@ var leaveAltScreen = (target) => {
|
|
|
953
938
|
// src/ui/picker-key-event.ts
|
|
954
939
|
var NO_MODIFIERS = {
|
|
955
940
|
ctrl: false,
|
|
956
|
-
meta: false,
|
|
957
941
|
escape: false,
|
|
958
942
|
return: false,
|
|
959
943
|
tab: false,
|
|
@@ -968,89 +952,40 @@ var event = (input, key = {}) => ({
|
|
|
968
952
|
input,
|
|
969
953
|
key: { ...NO_MODIFIERS, ...key }
|
|
970
954
|
});
|
|
971
|
-
var withMeta = (keyEvent) => ({
|
|
972
|
-
input: keyEvent.input,
|
|
973
|
-
key: { ...keyEvent.key, meta: true }
|
|
974
|
-
});
|
|
975
955
|
|
|
976
956
|
// src/ui/picker-key-csi.ts
|
|
977
|
-
var
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
return "upArrow";
|
|
984
|
-
}
|
|
985
|
-
if (finalByte === ARROW_FINAL_BYTE_B) {
|
|
986
|
-
return "downArrow";
|
|
987
|
-
}
|
|
988
|
-
if (finalByte === ARROW_FINAL_BYTE_C) {
|
|
989
|
-
return "rightArrow";
|
|
990
|
-
}
|
|
991
|
-
if (finalByte === ARROW_FINAL_BYTE_D) {
|
|
992
|
-
return "leftArrow";
|
|
993
|
-
}
|
|
994
|
-
return null;
|
|
995
|
-
};
|
|
996
|
-
var modifierBitsFromParam = (param) => {
|
|
997
|
-
const bits = param - 1;
|
|
998
|
-
const CTRL_BIT = 4;
|
|
999
|
-
const ALT_BIT = 2;
|
|
1000
|
-
return { ctrl: (bits & CTRL_BIT) !== 0, meta: (bits & ALT_BIT) !== 0 };
|
|
1001
|
-
};
|
|
957
|
+
var ARROW_KEYS = new Map([
|
|
958
|
+
["A", "upArrow"],
|
|
959
|
+
["B", "downArrow"],
|
|
960
|
+
["C", "rightArrow"],
|
|
961
|
+
["D", "leftArrow"]
|
|
962
|
+
]);
|
|
1002
963
|
var CSI_FINAL_BYTE_MIN = 64;
|
|
1003
964
|
var CSI_FINAL_BYTE_MAX = 126;
|
|
1004
965
|
var isCsiFinalByte = (byte) => byte >= CSI_FINAL_BYTE_MIN && byte <= CSI_FINAL_BYTE_MAX;
|
|
1005
|
-
var
|
|
1006
|
-
var
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
const DELETE_PARAM = "3";
|
|
1011
|
-
if (finalByte === "~" && (paramText === DELETE_PARAM || paramText.startsWith(`${DELETE_PARAM};`))) {
|
|
1012
|
-
return event("", { delete: true });
|
|
1013
|
-
}
|
|
1014
|
-
const arrowKey = arrowModifierKey(finalByte.codePointAt(0));
|
|
1015
|
-
if (arrowKey === null || !(paramText === "" || MODIFIED_PATTERN.test(paramText))) {
|
|
1016
|
-
return null;
|
|
966
|
+
var DELETE_PARAM = "3";
|
|
967
|
+
var csiEvent = (paramText, finalByte) => {
|
|
968
|
+
if (finalByte === "~") {
|
|
969
|
+
const [first] = paramText.split(";");
|
|
970
|
+
return first === DELETE_PARAM ? event("", { delete: true }) : null;
|
|
1017
971
|
}
|
|
1018
|
-
const
|
|
1019
|
-
|
|
1020
|
-
return event("", { [arrowKey]: true, ...mods });
|
|
972
|
+
const arrowKey = ARROW_KEYS.get(finalByte);
|
|
973
|
+
return arrowKey === undefined ? null : event("", { [arrowKey]: true });
|
|
1021
974
|
};
|
|
1022
975
|
var parseCsi = (buf) => {
|
|
1023
976
|
const CSI_PREFIX_LENGTH = 2;
|
|
1024
977
|
let index = CSI_PREFIX_LENGTH;
|
|
1025
|
-
let paramText = "";
|
|
1026
978
|
while (index < buf.length && !isCsiFinalByte(buf[index])) {
|
|
1027
|
-
const paramByte = buf[index];
|
|
1028
|
-
if (paramByte === CTRL_C_BYTE) {
|
|
1029
|
-
return {
|
|
1030
|
-
kind: "interrupted",
|
|
1031
|
-
consumed: index + 1,
|
|
1032
|
-
event: event("c", { ctrl: true })
|
|
1033
|
-
};
|
|
1034
|
-
}
|
|
1035
|
-
paramText += String.fromCodePoint(paramByte);
|
|
1036
979
|
index += 1;
|
|
1037
980
|
}
|
|
1038
981
|
if (index >= buf.length) {
|
|
1039
982
|
return { kind: "incomplete" };
|
|
1040
983
|
}
|
|
1041
|
-
const
|
|
1042
|
-
const consumed = index + 1;
|
|
1043
|
-
const full = paramText + finalByte;
|
|
1044
|
-
if (full === BRACKETED_PASTE_START) {
|
|
1045
|
-
return { kind: "resolved", consumed, event: null, pasteStarted: true };
|
|
1046
|
-
}
|
|
1047
|
-
if (full === BRACKETED_PASTE_END) {
|
|
1048
|
-
return { kind: "resolved", consumed, event: null, pasteEnded: true };
|
|
1049
|
-
}
|
|
984
|
+
const paramText = buf.subarray(CSI_PREFIX_LENGTH, index).toString("latin1");
|
|
1050
985
|
return {
|
|
1051
986
|
kind: "resolved",
|
|
1052
|
-
consumed,
|
|
1053
|
-
event:
|
|
987
|
+
consumed: index + 1,
|
|
988
|
+
event: csiEvent(paramText, String.fromCodePoint(buf[index]))
|
|
1054
989
|
};
|
|
1055
990
|
};
|
|
1056
991
|
var SS3_SEQUENCE_LENGTH = 3;
|
|
@@ -1058,19 +993,11 @@ var parseSs3 = (buf) => {
|
|
|
1058
993
|
if (buf.length < SS3_SEQUENCE_LENGTH) {
|
|
1059
994
|
return { kind: "incomplete" };
|
|
1060
995
|
}
|
|
1061
|
-
const
|
|
1062
|
-
if (finalByte === CTRL_C_BYTE) {
|
|
1063
|
-
return {
|
|
1064
|
-
kind: "interrupted",
|
|
1065
|
-
consumed: SS3_SEQUENCE_LENGTH,
|
|
1066
|
-
event: event("c", { ctrl: true })
|
|
1067
|
-
};
|
|
1068
|
-
}
|
|
1069
|
-
const arrowKey = arrowModifierKey(finalByte);
|
|
996
|
+
const arrowKey = ARROW_KEYS.get(String.fromCodePoint(buf[2]));
|
|
1070
997
|
return {
|
|
1071
998
|
kind: "resolved",
|
|
1072
999
|
consumed: SS3_SEQUENCE_LENGTH,
|
|
1073
|
-
event: arrowKey ===
|
|
1000
|
+
event: arrowKey === undefined ? null : event("", { [arrowKey]: true })
|
|
1074
1001
|
};
|
|
1075
1002
|
};
|
|
1076
1003
|
|
|
@@ -1124,13 +1051,11 @@ var isPrintableChar = (char) => {
|
|
|
1124
1051
|
return codePoint < C1_CONTROL_MIN || codePoint > C1_CONTROL_MAX;
|
|
1125
1052
|
};
|
|
1126
1053
|
var pastedTextToEvents = (text) => [...text].filter((char) => isPrintableChar(char)).map((char) => event(char));
|
|
1054
|
+
var PASTE_START_MARKER = Buffer.from("\x1B[200~", "latin1");
|
|
1055
|
+
var PASTE_END_MARKER = Buffer.from("\x1B[201~", "latin1");
|
|
1127
1056
|
var CSI_INTRODUCER_CODE = "[".codePointAt(0);
|
|
1128
1057
|
var SS3_INTRODUCER_CODE = "O".codePointAt(0);
|
|
1129
1058
|
var MAX_PENDING_SEQUENCE_BYTES = 32;
|
|
1130
|
-
var PASTE_END_MARKER = Buffer.concat([
|
|
1131
|
-
Buffer.from([ESC2]),
|
|
1132
|
-
Buffer.from(`[${BRACKETED_PASTE_END}`)
|
|
1133
|
-
]);
|
|
1134
1059
|
|
|
1135
1060
|
class PickerKeyParser {
|
|
1136
1061
|
buffer = Buffer.alloc(0);
|
|
@@ -1166,11 +1091,9 @@ class PickerKeyParser {
|
|
|
1166
1091
|
this.inPaste = false;
|
|
1167
1092
|
return pastedTextToEvents(text);
|
|
1168
1093
|
}
|
|
1169
|
-
const maxOverlap = Math.min(PASTE_END_MARKER.length - 1, this.buffer.length);
|
|
1170
1094
|
let overlap = 0;
|
|
1171
|
-
for (let candidate =
|
|
1172
|
-
|
|
1173
|
-
if (tail.equals(PASTE_END_MARKER.subarray(0, candidate))) {
|
|
1095
|
+
for (let candidate = Math.min(PASTE_END_MARKER.length - 1, this.buffer.length);candidate > 0; candidate -= 1) {
|
|
1096
|
+
if (this.buffer.subarray(this.buffer.length - candidate).equals(PASTE_END_MARKER.subarray(0, candidate))) {
|
|
1174
1097
|
overlap = candidate;
|
|
1175
1098
|
break;
|
|
1176
1099
|
}
|
|
@@ -1197,8 +1120,7 @@ class PickerKeyParser {
|
|
|
1197
1120
|
}
|
|
1198
1121
|
if (first === LF) {
|
|
1199
1122
|
this.buffer = this.buffer.subarray(1);
|
|
1200
|
-
return [
|
|
1201
|
-
`)];
|
|
1123
|
+
return [];
|
|
1202
1124
|
}
|
|
1203
1125
|
if (first === TAB) {
|
|
1204
1126
|
this.buffer = this.buffer.subarray(1);
|
|
@@ -1224,14 +1146,18 @@ class PickerKeyParser {
|
|
|
1224
1146
|
}
|
|
1225
1147
|
const second = this.buffer[1];
|
|
1226
1148
|
if (second === CSI_INTRODUCER_CODE) {
|
|
1149
|
+
if (this.buffer.subarray(0, PASTE_START_MARKER.length).equals(PASTE_START_MARKER)) {
|
|
1150
|
+
this.buffer = this.buffer.subarray(PASTE_START_MARKER.length);
|
|
1151
|
+
this.inPaste = true;
|
|
1152
|
+
return [];
|
|
1153
|
+
}
|
|
1227
1154
|
return this.applySequence(parseCsi(this.buffer));
|
|
1228
1155
|
}
|
|
1229
1156
|
if (second === SS3_INTRODUCER_CODE) {
|
|
1230
1157
|
return this.applySequence(parseSs3(this.buffer));
|
|
1231
1158
|
}
|
|
1232
1159
|
this.buffer = this.buffer.subarray(1);
|
|
1233
|
-
|
|
1234
|
-
return inner === null ? null : inner.map((keyEvent) => withMeta(keyEvent));
|
|
1160
|
+
return [event("", { escape: true })];
|
|
1235
1161
|
}
|
|
1236
1162
|
applySequence(result) {
|
|
1237
1163
|
if (result.kind === "incomplete") {
|
|
@@ -1240,17 +1166,7 @@ class PickerKeyParser {
|
|
|
1240
1166
|
}
|
|
1241
1167
|
return null;
|
|
1242
1168
|
}
|
|
1243
|
-
if (result.kind === "interrupted") {
|
|
1244
|
-
this.buffer = this.buffer.subarray(result.consumed);
|
|
1245
|
-
return [result.event];
|
|
1246
|
-
}
|
|
1247
1169
|
this.buffer = this.buffer.subarray(result.consumed);
|
|
1248
|
-
if (result.pasteStarted === true) {
|
|
1249
|
-
this.inPaste = true;
|
|
1250
|
-
}
|
|
1251
|
-
if (result.pasteEnded === true) {
|
|
1252
|
-
this.inPaste = false;
|
|
1253
|
-
}
|
|
1254
1170
|
return result.event === null ? [] : [result.event];
|
|
1255
1171
|
}
|
|
1256
1172
|
stepUtf8Char() {
|
|
@@ -1432,7 +1348,6 @@ var runTerminalSession = (createHandlers, streams = defaultStreams()) => new Pro
|
|
|
1432
1348
|
// src/ui/picker.ts
|
|
1433
1349
|
var DEFAULT_TERMINAL_WIDTH = 80;
|
|
1434
1350
|
var terminalDimension = (value, fallback) => value !== undefined && value > 0 ? value : fallback;
|
|
1435
|
-
var colorEnabled = (stderr) => stderr.isTTY === true && (process.env["NO_COLOR"] ?? "") === "";
|
|
1436
1351
|
var isCtrlC = (event) => event.key.ctrl && event.input === "c";
|
|
1437
1352
|
var runPicker = (candidates, callbacks) => runTerminalSession(({ requestRender, finish }) => {
|
|
1438
1353
|
const store = createPickerStore(candidates, callbacks, (outcome) => finish(outcome), (reason) => finish({ type: "cancelled", reason }));
|
|
@@ -1473,8 +1388,7 @@ var deleteWorktree = async (git, fs, candidate) => {
|
|
|
1473
1388
|
branch,
|
|
1474
1389
|
...candidate.kind === "worktree" ? { expectedPath: candidate.worktree.path } : {},
|
|
1475
1390
|
allowPrunable: candidate.kind === "worktree" && candidate.worktree.prunable,
|
|
1476
|
-
force: false
|
|
1477
|
-
ext: false
|
|
1391
|
+
force: false
|
|
1478
1392
|
});
|
|
1479
1393
|
if (!result.ok) {
|
|
1480
1394
|
return {
|
|
@@ -1500,7 +1414,7 @@ var createPickerCallbacks = (git, fs, json, onSwitchedBranch) => ({
|
|
|
1500
1414
|
allowExternalHolderSwap: candidate.kind === "worktree" && candidate.worktree.kind === "external",
|
|
1501
1415
|
...candidate.kind === "worktree" ? { expectedHolderPath: candidate.worktree.path } : {}
|
|
1502
1416
|
});
|
|
1503
|
-
if (!result.ok) {
|
|
1417
|
+
if (!result.ok || result.path === undefined) {
|
|
1504
1418
|
return {
|
|
1505
1419
|
ok: false,
|
|
1506
1420
|
message: result.errorMessage ?? "Failed to switch root."
|
|
@@ -1511,10 +1425,7 @@ var createPickerCallbacks = (git, fs, json, onSwitchedBranch) => ({
|
|
|
1511
1425
|
detachedHolder: result.data?.detachedHolder ?? null,
|
|
1512
1426
|
warnings: result.warnings ?? []
|
|
1513
1427
|
});
|
|
1514
|
-
return {
|
|
1515
|
-
ok: true,
|
|
1516
|
-
...result.path === undefined ? {} : { path: result.path }
|
|
1517
|
-
};
|
|
1428
|
+
return { ok: true, path: result.path };
|
|
1518
1429
|
},
|
|
1519
1430
|
reloadCandidates: async () => await loadPickCandidates(git, fs, json) ?? []
|
|
1520
1431
|
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/domain/posix-path.ts
|
|
2
|
+
var withoutTrailingSlash = (path) => path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
|
|
3
|
+
var shortenHome = (path, home) => {
|
|
4
|
+
if (home === "" || home === "/") {
|
|
5
|
+
return path;
|
|
6
|
+
}
|
|
7
|
+
if (path === home) {
|
|
8
|
+
return "~";
|
|
9
|
+
}
|
|
10
|
+
return path.startsWith(`${home}/`) ? `~${path.slice(home.length)}` : path;
|
|
11
|
+
};
|
|
12
|
+
var parentDir = (path) => {
|
|
13
|
+
const trimmed = withoutTrailingSlash(path);
|
|
14
|
+
const index = trimmed.lastIndexOf("/");
|
|
15
|
+
if (index === -1) {
|
|
16
|
+
return ".";
|
|
17
|
+
}
|
|
18
|
+
return index === 0 ? "/" : trimmed.slice(0, index);
|
|
19
|
+
};
|
|
20
|
+
var absoluteCandidates = (dirs, name) => [
|
|
21
|
+
...new Set(dirs.map((entry) => entry.trim()).filter((entry) => entry.startsWith("/")).map((dir) => `${dir.endsWith("/") ? dir.slice(0, -1) : dir}/${name}`))
|
|
22
|
+
];
|
|
23
|
+
var splitPathEnv = (pathEnv) => (pathEnv ?? "").split(":");
|
|
24
|
+
|
|
25
|
+
export { shortenHome, parentDir, absoluteCandidates, splitPathEnv };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
describeFatalError
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-ph0gp56k.js";
|
|
4
4
|
import {
|
|
5
5
|
reportResult
|
|
6
6
|
} from "./cli-dbzx9nzg.js";
|
|
7
7
|
import {
|
|
8
8
|
fail
|
|
9
|
-
} from "./cli-
|
|
9
|
+
} from "./cli-77yanq37.js";
|
|
10
10
|
|
|
11
11
|
// src/cli-dispatch.ts
|
|
12
12
|
var normalizeCliArgs = (rawArgs, argv0, isCompiledBinary) => isCompiledBinary && rawArgs.length === 1 && rawArgs[0] === argv0 ? [] : rawArgs;
|
|
@@ -37,7 +37,7 @@ var reportFatalError = (command, json, error) => {
|
|
|
37
37
|
// package.json
|
|
38
38
|
var package_default = {
|
|
39
39
|
name: "@n-seiji/nuthatch",
|
|
40
|
-
version: "0.1
|
|
40
|
+
version: "0.2.1",
|
|
41
41
|
description: "git worktree manager (hop)",
|
|
42
42
|
homepage: "https://github.com/n-seiji/nuthatch#readme",
|
|
43
43
|
bugs: {
|
|
@@ -52,8 +52,7 @@ var package_default = {
|
|
|
52
52
|
hop: "dist/cli.js"
|
|
53
53
|
},
|
|
54
54
|
files: [
|
|
55
|
-
"dist"
|
|
56
|
-
"shell"
|
|
55
|
+
"dist"
|
|
57
56
|
],
|
|
58
57
|
type: "module",
|
|
59
58
|
publishConfig: {
|
|
@@ -73,7 +72,7 @@ var package_default = {
|
|
|
73
72
|
},
|
|
74
73
|
devDependencies: {
|
|
75
74
|
"@types/bun": "latest",
|
|
76
|
-
oxfmt: "^0.
|
|
75
|
+
oxfmt: "^0.72.0",
|
|
77
76
|
oxlint: "^1.81.0",
|
|
78
77
|
typescript: "^5.6.0"
|
|
79
78
|
},
|
|
@@ -85,30 +84,4 @@ var package_default = {
|
|
|
85
84
|
// src/version.ts
|
|
86
85
|
var VERSION = package_default.version;
|
|
87
86
|
|
|
88
|
-
|
|
89
|
-
import { constants } from "node:fs";
|
|
90
|
-
import { access, stat } from "node:fs/promises";
|
|
91
|
-
var isExecutableFile = async (path) => {
|
|
92
|
-
try {
|
|
93
|
-
const stats = await stat(path);
|
|
94
|
-
if (!stats.isFile()) {
|
|
95
|
-
return false;
|
|
96
|
-
}
|
|
97
|
-
await access(path, constants.X_OK);
|
|
98
|
-
return true;
|
|
99
|
-
} catch {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
var firstExecutable = async (candidates) => {
|
|
104
|
-
const probes = candidates.map(async (candidate) => await isExecutableFile(candidate) ? candidate : null);
|
|
105
|
-
for (const probe of probes) {
|
|
106
|
-
const found = await probe;
|
|
107
|
-
if (found !== null) {
|
|
108
|
-
return found;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return null;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
export { normalizeCliArgs, isRunningAsCompiledBinary, isUpdateRequest, isHelpRequest, isVersionRequest, dispatchCliArgs, wantsJson, reportFatalError, firstExecutable, VERSION };
|
|
87
|
+
export { normalizeCliArgs, isRunningAsCompiledBinary, isUpdateRequest, isHelpRequest, isVersionRequest, dispatchCliArgs, wantsJson, reportFatalError, VERSION };
|