@n-seiji/nuthatch 0.1.7 → 0.2.0
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 +21 -21
- package/README.md +21 -21
- package/dist/{clean-n2f9z8n3.js → clean-dkrfmz85.js} +24 -25
- package/dist/cli-26d2drt6.js +30 -0
- package/dist/{cli-2bhb9p0x.js → cli-77yanq37.js} +3 -1
- package/dist/{cli-ygt2w4e1.js → cli-9y31xrsx.js} +20 -28
- 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-7jg5qqs9.js → cli-fqz7emfm.js} +12 -12
- package/dist/{cli-3ya15je0.js → cli-mfz1rx2x.js} +6 -33
- package/dist/{cli-qrxgkskr.js → cli-ph0gp56k.js} +6 -21
- package/dist/{cli-pick-w9qk71fy.js → cli-pick-wdtja21m.js} +60 -151
- package/dist/{cli-23z98dw1.js → cli-r39xsdym.js} +17 -30
- package/dist/cli-s5qcjcwk.js +25 -0
- package/dist/{cli-update-7exha1em.js → cli-update-kepe7h0z.js} +82 -334
- package/dist/{cli-rcw5adqd.js → cli-wcnyhk4w.js} +1 -1
- package/dist/cli.js +52 -54
- package/dist/{init-s0dafa83.js → init-2x8g9295.js} +1 -10
- package/dist/{jump-nvdkeega.js → jump-tnpgxcsz.js} +5 -5
- package/dist/{ls-kvz4wmc9.js → ls-ky84e8ep.js} +3 -3
- package/dist/{render-ls-6r3vv7y0.js → render-ls-x4hpnsvy.js} +16 -27
- package/dist/rm-0g8cxees.js +7 -0
- package/dist/root-czmzc98y.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,17 +1,23 @@
|
|
|
1
|
-
import"./cli-
|
|
1
|
+
import"./cli-ph0gp56k.js";
|
|
2
2
|
import {
|
|
3
3
|
rm2
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-r39xsdym.js";
|
|
5
5
|
import {
|
|
6
6
|
root2
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-9y31xrsx.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
|
|
@@ -19,11 +25,14 @@ import {
|
|
|
19
25
|
import {
|
|
20
26
|
loadRepoContext,
|
|
21
27
|
worktreeDirtyState
|
|
22
|
-
} from "./cli-
|
|
28
|
+
} from "./cli-fqz7emfm.js";
|
|
23
29
|
import {
|
|
24
30
|
EXIT_CANCELLED,
|
|
25
31
|
ok
|
|
26
|
-
} from "./cli-
|
|
32
|
+
} from "./cli-77yanq37.js";
|
|
33
|
+
import {
|
|
34
|
+
shortenHome
|
|
35
|
+
} from "./cli-s5qcjcwk.js";
|
|
27
36
|
|
|
28
37
|
// src/domain/candidates.ts
|
|
29
38
|
var buildPickCandidates = (worktrees, dirtyByPath, localBranches, remoteBranches) => {
|
|
@@ -72,30 +81,16 @@ var pick = async (git, fs, options) => {
|
|
|
72
81
|
// src/ui/picker-render.ts
|
|
73
82
|
import { homedir } from "node:os";
|
|
74
83
|
|
|
75
|
-
// src/ui/ansi.ts
|
|
76
|
-
var ESC = "\x1B";
|
|
77
|
-
|
|
78
84
|
// src/ui/picker-frame.ts
|
|
79
85
|
var CURSOR_HOME = `${ESC}[H`;
|
|
80
86
|
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
|
-
};
|
|
87
|
+
var sgrCode = (style) => style === "bold-dim" ? `${SGR.bold}${SGR.dim}` : SGR[style];
|
|
93
88
|
var renderSpan = (span, colorEnabled) => {
|
|
94
89
|
const style = span.style ?? "plain";
|
|
95
90
|
if (!colorEnabled || style === "plain") {
|
|
96
91
|
return span.text;
|
|
97
92
|
}
|
|
98
|
-
return `${
|
|
93
|
+
return `${sgrCode(style)}${span.text}${SGR_RESET}`;
|
|
99
94
|
};
|
|
100
95
|
var lineWidth = (line) => line.reduce((total, span) => total + displayWidth(span.text), 0);
|
|
101
96
|
var renderLine = (line, colorEnabled) => line.map((span) => renderSpan(span, colorEnabled)).join("");
|
|
@@ -268,20 +263,16 @@ var sortCandidatesForDisplay = (candidates) => [
|
|
|
268
263
|
...candidates.filter((candidate) => isCreatableCandidate(candidate)).toSorted((a, b) => compareCreatableCandidates(a, b))
|
|
269
264
|
];
|
|
270
265
|
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
|
-
};
|
|
266
|
+
var shortenPath = (path, homeDir, maxLength = MAX_PATH_LENGTH) => truncateToWidthKeepingTail(shortenHome(path, homeDir), maxLength);
|
|
275
267
|
var candidatePathLabel = (candidate, homeDir, maxLength) => candidate.kind === "worktree" ? shortenPath(candidate.worktree.path, homeDir, maxLength) : "";
|
|
276
268
|
var rawBranchColumnWidth = (candidates) => candidates.reduce((max, candidate) => Math.max(max, displayWidth(candidateBranchLabel(candidate))), 0);
|
|
277
269
|
var branchColumnWidth = (candidates) => Math.min(MAX_BRANCH_COLUMN_WIDTH, rawBranchColumnWidth(candidates));
|
|
278
|
-
var padBranchLabel = (label, width) => padToWidth(label, width);
|
|
279
270
|
var toCandidateRow = (candidate, options) => ({
|
|
280
271
|
kind: "candidate",
|
|
281
272
|
index: options.index,
|
|
282
273
|
section: options.section,
|
|
283
274
|
statusMarker: statusMarker(candidate),
|
|
284
|
-
branchLabel:
|
|
275
|
+
branchLabel: padToWidth(truncateToWidth(candidateBranchLabel(candidate), options.branchWidth), options.branchWidth),
|
|
285
276
|
kindLabel: candidateKindLabel(candidate).padEnd(KIND_COLUMN_WIDTH, " "),
|
|
286
277
|
pathLabel: candidatePathLabel(candidate, options.homeDir, options.pathMaxLength)
|
|
287
278
|
});
|
|
@@ -575,8 +566,6 @@ var renderPickerFrame = ({
|
|
|
575
566
|
};
|
|
576
567
|
|
|
577
568
|
// src/ui/picker-keys.ts
|
|
578
|
-
var isCtrlJByte = (input) => input === `
|
|
579
|
-
`;
|
|
580
569
|
var resolvePickerKeyAction = (input, key) => {
|
|
581
570
|
if (key.escape) {
|
|
582
571
|
return { type: "cancel", reason: "esc" };
|
|
@@ -599,7 +588,7 @@ var resolvePickerKeyAction = (input, key) => {
|
|
|
599
588
|
if (key.upArrow || key.ctrl && (input === "p" || input === "k")) {
|
|
600
589
|
return { type: "up" };
|
|
601
590
|
}
|
|
602
|
-
if (key.downArrow || key.ctrl &&
|
|
591
|
+
if (key.downArrow || key.ctrl && input === "n") {
|
|
603
592
|
return { type: "down" };
|
|
604
593
|
}
|
|
605
594
|
if (key.ctrl && input === "u") {
|
|
@@ -608,7 +597,7 @@ var resolvePickerKeyAction = (input, key) => {
|
|
|
608
597
|
if (key.backspace || key.delete) {
|
|
609
598
|
return { type: "backspace" };
|
|
610
599
|
}
|
|
611
|
-
if (input.length > 0 && !key.ctrl
|
|
600
|
+
if (input.length > 0 && !key.ctrl) {
|
|
612
601
|
return { type: "char", char: input };
|
|
613
602
|
}
|
|
614
603
|
return { type: "ignore" };
|
|
@@ -624,17 +613,17 @@ var resolvePanelKeyAction = (input, key) => {
|
|
|
624
613
|
if (key.upArrow || key.ctrl && (input === "p" || input === "k")) {
|
|
625
614
|
return { type: "up" };
|
|
626
615
|
}
|
|
627
|
-
if (key.downArrow || key.ctrl &&
|
|
616
|
+
if (key.downArrow || key.ctrl && input === "n") {
|
|
628
617
|
return { type: "down" };
|
|
629
618
|
}
|
|
630
|
-
if (!key.ctrl &&
|
|
619
|
+
if (!key.ctrl && isPanelLetterShortcut(input)) {
|
|
631
620
|
return { type: "letter", char: input };
|
|
632
621
|
}
|
|
633
622
|
return { type: "ignore" };
|
|
634
623
|
};
|
|
635
624
|
var isPanelLetterShortcut = (input) => PANEL_LETTER_SHORTCUTS.includes(input);
|
|
636
625
|
var resolveConfirmKeyAction = (input, key) => {
|
|
637
|
-
if (!key.ctrl &&
|
|
626
|
+
if (!key.ctrl && (input === "y" || input === "Y")) {
|
|
638
627
|
return { type: "yes" };
|
|
639
628
|
}
|
|
640
629
|
return { type: "no" };
|
|
@@ -789,20 +778,14 @@ var createFilteredSelector = () => {
|
|
|
789
778
|
var runMutation = async (callbacks, candidate, action) => {
|
|
790
779
|
if (action === "switchRoot") {
|
|
791
780
|
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
|
-
};
|
|
781
|
+
if (!result.ok) {
|
|
782
|
+
return { type: "patch", patch: panelErrorTransition(candidate, result.message) };
|
|
797
783
|
}
|
|
798
784
|
return { type: "exit", outcome: { type: "path", path: result.path } };
|
|
799
785
|
}
|
|
800
786
|
const result = await callbacks.deleteWorktree(candidate);
|
|
801
787
|
if (!result.ok) {
|
|
802
|
-
return {
|
|
803
|
-
type: "patch",
|
|
804
|
-
patch: panelErrorTransition(candidate, result.message ?? "Failed to delete worktree.")
|
|
805
|
-
};
|
|
788
|
+
return { type: "patch", patch: panelErrorTransition(candidate, result.message) };
|
|
806
789
|
}
|
|
807
790
|
const fresh = await callbacks.reloadCandidates();
|
|
808
791
|
return {
|
|
@@ -953,7 +936,6 @@ var leaveAltScreen = (target) => {
|
|
|
953
936
|
// src/ui/picker-key-event.ts
|
|
954
937
|
var NO_MODIFIERS = {
|
|
955
938
|
ctrl: false,
|
|
956
|
-
meta: false,
|
|
957
939
|
escape: false,
|
|
958
940
|
return: false,
|
|
959
941
|
tab: false,
|
|
@@ -968,89 +950,40 @@ var event = (input, key = {}) => ({
|
|
|
968
950
|
input,
|
|
969
951
|
key: { ...NO_MODIFIERS, ...key }
|
|
970
952
|
});
|
|
971
|
-
var withMeta = (keyEvent) => ({
|
|
972
|
-
input: keyEvent.input,
|
|
973
|
-
key: { ...keyEvent.key, meta: true }
|
|
974
|
-
});
|
|
975
953
|
|
|
976
954
|
// 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
|
-
};
|
|
955
|
+
var ARROW_KEYS = new Map([
|
|
956
|
+
["A", "upArrow"],
|
|
957
|
+
["B", "downArrow"],
|
|
958
|
+
["C", "rightArrow"],
|
|
959
|
+
["D", "leftArrow"]
|
|
960
|
+
]);
|
|
1002
961
|
var CSI_FINAL_BYTE_MIN = 64;
|
|
1003
962
|
var CSI_FINAL_BYTE_MAX = 126;
|
|
1004
963
|
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;
|
|
964
|
+
var DELETE_PARAM = "3";
|
|
965
|
+
var csiEvent = (paramText, finalByte) => {
|
|
966
|
+
if (finalByte === "~") {
|
|
967
|
+
const [first] = paramText.split(";");
|
|
968
|
+
return first === DELETE_PARAM ? event("", { delete: true }) : null;
|
|
1017
969
|
}
|
|
1018
|
-
const
|
|
1019
|
-
|
|
1020
|
-
return event("", { [arrowKey]: true, ...mods });
|
|
970
|
+
const arrowKey = ARROW_KEYS.get(finalByte);
|
|
971
|
+
return arrowKey === undefined ? null : event("", { [arrowKey]: true });
|
|
1021
972
|
};
|
|
1022
973
|
var parseCsi = (buf) => {
|
|
1023
974
|
const CSI_PREFIX_LENGTH = 2;
|
|
1024
975
|
let index = CSI_PREFIX_LENGTH;
|
|
1025
|
-
let paramText = "";
|
|
1026
976
|
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
977
|
index += 1;
|
|
1037
978
|
}
|
|
1038
979
|
if (index >= buf.length) {
|
|
1039
980
|
return { kind: "incomplete" };
|
|
1040
981
|
}
|
|
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
|
-
}
|
|
982
|
+
const paramText = buf.subarray(CSI_PREFIX_LENGTH, index).toString("latin1");
|
|
1050
983
|
return {
|
|
1051
984
|
kind: "resolved",
|
|
1052
|
-
consumed,
|
|
1053
|
-
event:
|
|
985
|
+
consumed: index + 1,
|
|
986
|
+
event: csiEvent(paramText, String.fromCodePoint(buf[index]))
|
|
1054
987
|
};
|
|
1055
988
|
};
|
|
1056
989
|
var SS3_SEQUENCE_LENGTH = 3;
|
|
@@ -1058,19 +991,11 @@ var parseSs3 = (buf) => {
|
|
|
1058
991
|
if (buf.length < SS3_SEQUENCE_LENGTH) {
|
|
1059
992
|
return { kind: "incomplete" };
|
|
1060
993
|
}
|
|
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);
|
|
994
|
+
const arrowKey = ARROW_KEYS.get(String.fromCodePoint(buf[2]));
|
|
1070
995
|
return {
|
|
1071
996
|
kind: "resolved",
|
|
1072
997
|
consumed: SS3_SEQUENCE_LENGTH,
|
|
1073
|
-
event: arrowKey ===
|
|
998
|
+
event: arrowKey === undefined ? null : event("", { [arrowKey]: true })
|
|
1074
999
|
};
|
|
1075
1000
|
};
|
|
1076
1001
|
|
|
@@ -1124,13 +1049,11 @@ var isPrintableChar = (char) => {
|
|
|
1124
1049
|
return codePoint < C1_CONTROL_MIN || codePoint > C1_CONTROL_MAX;
|
|
1125
1050
|
};
|
|
1126
1051
|
var pastedTextToEvents = (text) => [...text].filter((char) => isPrintableChar(char)).map((char) => event(char));
|
|
1052
|
+
var PASTE_START_MARKER = Buffer.from("\x1B[200~", "latin1");
|
|
1053
|
+
var PASTE_END_MARKER = Buffer.from("\x1B[201~", "latin1");
|
|
1127
1054
|
var CSI_INTRODUCER_CODE = "[".codePointAt(0);
|
|
1128
1055
|
var SS3_INTRODUCER_CODE = "O".codePointAt(0);
|
|
1129
1056
|
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
1057
|
|
|
1135
1058
|
class PickerKeyParser {
|
|
1136
1059
|
buffer = Buffer.alloc(0);
|
|
@@ -1166,11 +1089,9 @@ class PickerKeyParser {
|
|
|
1166
1089
|
this.inPaste = false;
|
|
1167
1090
|
return pastedTextToEvents(text);
|
|
1168
1091
|
}
|
|
1169
|
-
const maxOverlap = Math.min(PASTE_END_MARKER.length - 1, this.buffer.length);
|
|
1170
1092
|
let overlap = 0;
|
|
1171
|
-
for (let candidate =
|
|
1172
|
-
|
|
1173
|
-
if (tail.equals(PASTE_END_MARKER.subarray(0, candidate))) {
|
|
1093
|
+
for (let candidate = Math.min(PASTE_END_MARKER.length - 1, this.buffer.length);candidate > 0; candidate -= 1) {
|
|
1094
|
+
if (this.buffer.subarray(this.buffer.length - candidate).equals(PASTE_END_MARKER.subarray(0, candidate))) {
|
|
1174
1095
|
overlap = candidate;
|
|
1175
1096
|
break;
|
|
1176
1097
|
}
|
|
@@ -1197,8 +1118,7 @@ class PickerKeyParser {
|
|
|
1197
1118
|
}
|
|
1198
1119
|
if (first === LF) {
|
|
1199
1120
|
this.buffer = this.buffer.subarray(1);
|
|
1200
|
-
return [
|
|
1201
|
-
`)];
|
|
1121
|
+
return [];
|
|
1202
1122
|
}
|
|
1203
1123
|
if (first === TAB) {
|
|
1204
1124
|
this.buffer = this.buffer.subarray(1);
|
|
@@ -1224,14 +1144,18 @@ class PickerKeyParser {
|
|
|
1224
1144
|
}
|
|
1225
1145
|
const second = this.buffer[1];
|
|
1226
1146
|
if (second === CSI_INTRODUCER_CODE) {
|
|
1147
|
+
if (this.buffer.subarray(0, PASTE_START_MARKER.length).equals(PASTE_START_MARKER)) {
|
|
1148
|
+
this.buffer = this.buffer.subarray(PASTE_START_MARKER.length);
|
|
1149
|
+
this.inPaste = true;
|
|
1150
|
+
return [];
|
|
1151
|
+
}
|
|
1227
1152
|
return this.applySequence(parseCsi(this.buffer));
|
|
1228
1153
|
}
|
|
1229
1154
|
if (second === SS3_INTRODUCER_CODE) {
|
|
1230
1155
|
return this.applySequence(parseSs3(this.buffer));
|
|
1231
1156
|
}
|
|
1232
1157
|
this.buffer = this.buffer.subarray(1);
|
|
1233
|
-
|
|
1234
|
-
return inner === null ? null : inner.map((keyEvent) => withMeta(keyEvent));
|
|
1158
|
+
return [event("", { escape: true })];
|
|
1235
1159
|
}
|
|
1236
1160
|
applySequence(result) {
|
|
1237
1161
|
if (result.kind === "incomplete") {
|
|
@@ -1240,17 +1164,7 @@ class PickerKeyParser {
|
|
|
1240
1164
|
}
|
|
1241
1165
|
return null;
|
|
1242
1166
|
}
|
|
1243
|
-
if (result.kind === "interrupted") {
|
|
1244
|
-
this.buffer = this.buffer.subarray(result.consumed);
|
|
1245
|
-
return [result.event];
|
|
1246
|
-
}
|
|
1247
1167
|
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
1168
|
return result.event === null ? [] : [result.event];
|
|
1255
1169
|
}
|
|
1256
1170
|
stepUtf8Char() {
|
|
@@ -1432,7 +1346,6 @@ var runTerminalSession = (createHandlers, streams = defaultStreams()) => new Pro
|
|
|
1432
1346
|
// src/ui/picker.ts
|
|
1433
1347
|
var DEFAULT_TERMINAL_WIDTH = 80;
|
|
1434
1348
|
var terminalDimension = (value, fallback) => value !== undefined && value > 0 ? value : fallback;
|
|
1435
|
-
var colorEnabled = (stderr) => stderr.isTTY === true && (process.env["NO_COLOR"] ?? "") === "";
|
|
1436
1349
|
var isCtrlC = (event) => event.key.ctrl && event.input === "c";
|
|
1437
1350
|
var runPicker = (candidates, callbacks) => runTerminalSession(({ requestRender, finish }) => {
|
|
1438
1351
|
const store = createPickerStore(candidates, callbacks, (outcome) => finish(outcome), (reason) => finish({ type: "cancelled", reason }));
|
|
@@ -1473,8 +1386,7 @@ var deleteWorktree = async (git, fs, candidate) => {
|
|
|
1473
1386
|
branch,
|
|
1474
1387
|
...candidate.kind === "worktree" ? { expectedPath: candidate.worktree.path } : {},
|
|
1475
1388
|
allowPrunable: candidate.kind === "worktree" && candidate.worktree.prunable,
|
|
1476
|
-
force: false
|
|
1477
|
-
ext: false
|
|
1389
|
+
force: false
|
|
1478
1390
|
});
|
|
1479
1391
|
if (!result.ok) {
|
|
1480
1392
|
return {
|
|
@@ -1500,7 +1412,7 @@ var createPickerCallbacks = (git, fs, json, onSwitchedBranch) => ({
|
|
|
1500
1412
|
allowExternalHolderSwap: candidate.kind === "worktree" && candidate.worktree.kind === "external",
|
|
1501
1413
|
...candidate.kind === "worktree" ? { expectedHolderPath: candidate.worktree.path } : {}
|
|
1502
1414
|
});
|
|
1503
|
-
if (!result.ok) {
|
|
1415
|
+
if (!result.ok || result.path === undefined) {
|
|
1504
1416
|
return {
|
|
1505
1417
|
ok: false,
|
|
1506
1418
|
message: result.errorMessage ?? "Failed to switch root."
|
|
@@ -1511,10 +1423,7 @@ var createPickerCallbacks = (git, fs, json, onSwitchedBranch) => ({
|
|
|
1511
1423
|
detachedHolder: result.data?.detachedHolder ?? null,
|
|
1512
1424
|
warnings: result.warnings ?? []
|
|
1513
1425
|
});
|
|
1514
|
-
return {
|
|
1515
|
-
ok: true,
|
|
1516
|
-
...result.path === undefined ? {} : { path: result.path }
|
|
1517
|
-
};
|
|
1426
|
+
return { ok: true, path: result.path };
|
|
1518
1427
|
},
|
|
1519
1428
|
reloadCandidates: async () => await loadPickCandidates(git, fs, json) ?? []
|
|
1520
1429
|
});
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
messageOf
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-ph0gp56k.js";
|
|
4
4
|
import {
|
|
5
5
|
withRepoLock
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-wcnyhk4w.js";
|
|
7
7
|
import {
|
|
8
8
|
loadRepoContext,
|
|
9
9
|
nestedWorktrees,
|
|
10
10
|
worktreeDirtyState
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-fqz7emfm.js";
|
|
12
12
|
import {
|
|
13
13
|
EXIT_GENERAL_ERROR,
|
|
14
14
|
EXIT_USAGE_ERROR,
|
|
15
15
|
EXIT_SAFE_REJECTION,
|
|
16
16
|
ok,
|
|
17
|
-
fail
|
|
18
|
-
|
|
17
|
+
fail,
|
|
18
|
+
pass,
|
|
19
|
+
reject
|
|
20
|
+
} from "./cli-77yanq37.js";
|
|
19
21
|
|
|
20
22
|
// src/commands/rm.ts
|
|
21
|
-
var EXT_DEPRECATION_WARNING = "--ext is deprecated and no longer required: hop rm can now remove external worktrees without it.";
|
|
22
23
|
var lockedRejection = (branch, lockReason) => fail(EXIT_SAFE_REJECTION, `Worktree for "${branch}" is locked by git${lockReason === null ? "" : ` (${lockReason})`}. hop never unlocks worktrees automatically — run "git worktree unlock" yourself first if you're sure.`);
|
|
23
24
|
var turnedPrunableRejection = (branch) => fail(EXIT_SAFE_REJECTION, `The selected worktree for "${branch}" changed before removal (git now reports it prunable). Refresh the picker and retry.`);
|
|
24
25
|
var stalePrunableWarning = ({ path, prunableReason }) => `Worktree at ${path} no longer exists${prunableReason === null ? "" : ` (${prunableReason})`}; removed its stale registration — if it had been moved by hand, the moved copy is no longer linked to this repository.`;
|
|
@@ -26,17 +27,13 @@ var resolveTarget = (worktrees, branch, expectedPath) => {
|
|
|
26
27
|
const matches = worktrees.filter((wt) => wt.branch === branch);
|
|
27
28
|
if (expectedPath !== undefined) {
|
|
28
29
|
const target = matches.find((wt) => wt.path === expectedPath);
|
|
29
|
-
return target === undefined ? {
|
|
30
|
-
rejection: fail(EXIT_SAFE_REJECTION, `The selected worktree for "${branch}" changed before removal. Refresh the picker and retry.`)
|
|
31
|
-
} : { target };
|
|
30
|
+
return target === undefined ? reject(fail(EXIT_SAFE_REJECTION, `The selected worktree for "${branch}" changed before removal. Refresh the picker and retry.`)) : pass(target);
|
|
32
31
|
}
|
|
33
32
|
if (matches.length > 1) {
|
|
34
|
-
return {
|
|
35
|
-
rejection: fail(EXIT_SAFE_REJECTION, `Branch "${branch}" is checked out at ${matches.length} worktrees (${matches.map((wt) => wt.path).join(", ")}). Refusing to guess which one to remove.`)
|
|
36
|
-
};
|
|
33
|
+
return reject(fail(EXIT_SAFE_REJECTION, `Branch "${branch}" is checked out at ${matches.length} worktrees (${matches.map((wt) => wt.path).join(", ")}). Refusing to guess which one to remove.`));
|
|
37
34
|
}
|
|
38
35
|
const [target] = matches;
|
|
39
|
-
return target === undefined ? {} :
|
|
36
|
+
return target === undefined ? reject(fail(EXIT_GENERAL_ERROR, `No worktree found for branch "${branch}".`)) : pass(target);
|
|
40
37
|
};
|
|
41
38
|
var nestedWorktreeRejection = (branch, targetPath, worktrees) => {
|
|
42
39
|
const nested = nestedWorktrees(worktrees, targetPath);
|
|
@@ -67,26 +64,16 @@ var targetSafetyRejection = async ({ git, fs, context, options }, target) => {
|
|
|
67
64
|
var validateRemoval = async (check) => {
|
|
68
65
|
const { context, options } = check;
|
|
69
66
|
const resolved = resolveTarget(context.worktrees, options.branch, options.expectedPath);
|
|
70
|
-
if (resolved.
|
|
71
|
-
return
|
|
72
|
-
}
|
|
73
|
-
const { target } = resolved;
|
|
74
|
-
if (target === undefined) {
|
|
75
|
-
return {
|
|
76
|
-
ok: false,
|
|
77
|
-
rejection: fail(EXIT_GENERAL_ERROR, `No worktree found for branch "${options.branch}".`)
|
|
78
|
-
};
|
|
67
|
+
if (!resolved.ok) {
|
|
68
|
+
return resolved;
|
|
79
69
|
}
|
|
70
|
+
const target = resolved.value;
|
|
80
71
|
if (target.kind === "root") {
|
|
81
|
-
return
|
|
72
|
+
return reject(fail(EXIT_USAGE_ERROR, "Cannot remove the root clone."));
|
|
82
73
|
}
|
|
83
74
|
const rejection = await targetSafetyRejection(check, target);
|
|
84
|
-
return rejection === null ?
|
|
75
|
+
return rejection === null ? resolved : reject(rejection);
|
|
85
76
|
};
|
|
86
|
-
var withExtWarning = (ext, result) => ext ? {
|
|
87
|
-
...result,
|
|
88
|
-
warnings: [...result.warnings ?? [], EXT_DEPRECATION_WARNING]
|
|
89
|
-
} : result;
|
|
90
77
|
var removeWorktree = async (git, fs, options) => {
|
|
91
78
|
const context = await loadRepoContext(git, fs, options.cwd);
|
|
92
79
|
const validation = await validateRemoval({ git, fs, context, options });
|
|
@@ -100,7 +87,7 @@ var removeWorktree = async (git, fs, options) => {
|
|
|
100
87
|
if (!freshValidation.ok) {
|
|
101
88
|
return freshValidation.rejection;
|
|
102
89
|
}
|
|
103
|
-
const
|
|
90
|
+
const target = freshValidation.value;
|
|
104
91
|
await git.removeWorktree(context.rootPath, target.path, options.force);
|
|
105
92
|
return ok({
|
|
106
93
|
data: { branch: options.branch, path: target.path },
|
|
@@ -111,6 +98,6 @@ var removeWorktree = async (git, fs, options) => {
|
|
|
111
98
|
}
|
|
112
99
|
});
|
|
113
100
|
};
|
|
114
|
-
var rm2 =
|
|
101
|
+
var rm2 = (git, fs, options) => removeWorktree(git, fs, options);
|
|
115
102
|
|
|
116
103
|
export { rm2 };
|
|
@@ -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 };
|