@simon_he/pi 0.2.8 → 0.2.10
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 +15 -3
- package/dist/index.cjs +436 -116
- package/dist/index.mjs +436 -116
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -125,15 +125,21 @@ eval "$(prun --init bash)"
|
|
|
125
125
|
|
|
126
126
|
# fish
|
|
127
127
|
eval (prun --init fish)
|
|
128
|
+
|
|
129
|
+
# Windows PowerShell
|
|
130
|
+
prun --init powershell | Out-String | Invoke-Expression
|
|
131
|
+
|
|
132
|
+
# PowerShell 7+
|
|
133
|
+
prun --init pwsh | Out-String | Invoke-Expression
|
|
128
134
|
```
|
|
129
135
|
|
|
130
|
-
> Note: This lets the command selected by prun be available immediately in your shell history (press ↑ to recall).
|
|
136
|
+
> Note: This lets the command selected by `prun` or `pfind` be available immediately in your shell history (press ↑ to recall).
|
|
131
137
|
|
|
132
138
|
Auto integration (built-in):
|
|
133
139
|
|
|
134
|
-
- In interactive shells, the first `prun` run will append the right line to your shell rc (zsh: `~/.zshrc`, bash: `~/.bashrc`, fish: `~/.config/fish/config.fish`).
|
|
140
|
+
- In interactive shells, the first `prun` run will append the right line to your shell rc/profile (zsh: `~/.zshrc`, bash: `~/.bashrc`, fish: `~/.config/fish/config.fish`, PowerShell: `$PROFILE`).
|
|
135
141
|
- Disable with `PI_NO_AUTO_INIT=1` (or set `PI_AUTO_INIT=0`).
|
|
136
|
-
- Open a new terminal (or source the rc
|
|
142
|
+
- Open a new terminal (or source the rc/profile) after the first run.
|
|
137
143
|
|
|
138
144
|
Make it persistent:
|
|
139
145
|
|
|
@@ -146,6 +152,12 @@ echo 'eval "$(prun --init bash)"' >> ~/.bashrc
|
|
|
146
152
|
|
|
147
153
|
# fish
|
|
148
154
|
echo 'prun --init fish | source' >> ~/.config/fish/config.fish
|
|
155
|
+
|
|
156
|
+
# Windows PowerShell
|
|
157
|
+
Add-Content -Path $PROFILE -Value 'prun --init powershell | Out-String | Invoke-Expression'
|
|
158
|
+
|
|
159
|
+
# PowerShell 7+
|
|
160
|
+
Add-Content -Path $PROFILE -Value 'prun --init pwsh | Out-String | Invoke-Expression'
|
|
149
161
|
```
|
|
150
162
|
|
|
151
163
|
Reload your shell config (or open a new terminal) after adding the line.
|
package/dist/index.cjs
CHANGED
|
@@ -47,7 +47,7 @@ let node_module = require("node:module");
|
|
|
47
47
|
let node_url = require("node:url");
|
|
48
48
|
|
|
49
49
|
//#region package.json
|
|
50
|
-
var version = "0.2.
|
|
50
|
+
var version = "0.2.10";
|
|
51
51
|
|
|
52
52
|
//#endregion
|
|
53
53
|
//#region src/tty.ts
|
|
@@ -557,8 +557,30 @@ async function detectNode() {
|
|
|
557
557
|
|
|
558
558
|
//#endregion
|
|
559
559
|
//#region src/pkgManager.ts
|
|
560
|
+
function normalizeDir$1(dir) {
|
|
561
|
+
return node_path.default.resolve(dir);
|
|
562
|
+
}
|
|
563
|
+
function findUpSync$1(startDir, predicate) {
|
|
564
|
+
let current = normalizeDir$1(startDir);
|
|
565
|
+
while (true) {
|
|
566
|
+
if (predicate(current)) return current;
|
|
567
|
+
const parent = node_path.default.dirname(current);
|
|
568
|
+
if (parent === current) return null;
|
|
569
|
+
current = parent;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
function inferToolFromRepoLayout(cwd) {
|
|
573
|
+
if (findUpSync$1(cwd, (dir) => (0, lazy_js_utils.isFile)(node_path.default.join(dir, "pnpm-workspace.yaml")) || (0, lazy_js_utils.isFile)(node_path.default.join(dir, "pnpm-lock.yaml")))) return "pnpm";
|
|
574
|
+
if (findUpSync$1(cwd, (dir) => (0, lazy_js_utils.isFile)(node_path.default.join(dir, "yarn.lock")) || (0, lazy_js_utils.isFile)(node_path.default.join(dir, ".yarnrc.yml")))) return "yarn";
|
|
575
|
+
if (findUpSync$1(cwd, (dir) => (0, lazy_js_utils.isFile)(node_path.default.join(dir, "bun.lockb")))) return "bun";
|
|
576
|
+
return null;
|
|
577
|
+
}
|
|
560
578
|
async function resolvePkgTool() {
|
|
561
|
-
|
|
579
|
+
let detected = await (0, lazy_js_utils_node.getPkgTool)() || "npm";
|
|
580
|
+
if (detected === "npm") {
|
|
581
|
+
const inferred = inferToolFromRepoLayout(node_process.default.cwd());
|
|
582
|
+
if (inferred) detected = inferred;
|
|
583
|
+
}
|
|
562
584
|
const fallback = node_process.default.env.PI_DEFAULT;
|
|
563
585
|
return {
|
|
564
586
|
detected,
|
|
@@ -622,7 +644,13 @@ async function findUpAsync(startDir, predicate) {
|
|
|
622
644
|
async function getParams(params) {
|
|
623
645
|
const cwd = node_process.default.cwd();
|
|
624
646
|
try {
|
|
625
|
-
|
|
647
|
+
let tool = await (0, lazy_js_utils_node.getPkgTool)() || "npm";
|
|
648
|
+
if (tool === "npm") {
|
|
649
|
+
if (findUpSync(cwd, (dir) => (0, lazy_js_utils.isFile)(node_path.default.join(dir, "pnpm-workspace.yaml")) || (0, lazy_js_utils.isFile)(node_path.default.join(dir, "pnpm-lock.yaml")))) tool = "pnpm";
|
|
650
|
+
else if (findUpSync(cwd, (dir) => (0, lazy_js_utils.isFile)(node_path.default.join(dir, "yarn.lock")) || (0, lazy_js_utils.isFile)(node_path.default.join(dir, ".yarnrc.yml")))) tool = "yarn";
|
|
651
|
+
else if (findUpSync(cwd, (dir) => (0, lazy_js_utils.isFile)(node_path.default.join(dir, "bun.lockb")))) tool = "bun";
|
|
652
|
+
}
|
|
653
|
+
switch (tool) {
|
|
626
654
|
case "pnpm": {
|
|
627
655
|
const pnpmWorkspaceRoot = findUpSync(cwd, (dir) => (0, lazy_js_utils.isFile)(node_path.default.join(dir, "pnpm-workspace.yaml")));
|
|
628
656
|
const inPnpmWorkspace = Boolean(pnpmWorkspaceRoot);
|
|
@@ -928,16 +956,419 @@ function getCcommand() {
|
|
|
928
956
|
}
|
|
929
957
|
|
|
930
958
|
//#endregion
|
|
931
|
-
//#region src/
|
|
959
|
+
//#region src/prun.ts
|
|
960
|
+
async function prun(params) {
|
|
961
|
+
ensurePrunAutoInit();
|
|
962
|
+
const hadNoHistoryEnv = node_process.default.env.CCOMMAND_NO_HISTORY != null || node_process.default.env.NO_HISTORY != null;
|
|
963
|
+
const initialNoHistory = node_process.default.env.CCOMMAND_NO_HISTORY ?? node_process.default.env.NO_HISTORY;
|
|
964
|
+
const prevNoHistory = node_process.default.env.CCOMMAND_NO_HISTORY;
|
|
965
|
+
if (!(hadNoHistoryEnv && isNoHistory$1(initialNoHistory))) delete node_process.default.env.CCOMMAND_NO_HISTORY;
|
|
966
|
+
else node_process.default.env.CCOMMAND_NO_HISTORY = "1";
|
|
967
|
+
const { ccommand } = getCcommand();
|
|
968
|
+
try {
|
|
969
|
+
await ccommand(params);
|
|
970
|
+
} finally {
|
|
971
|
+
if (prevNoHistory == null) delete node_process.default.env.CCOMMAND_NO_HISTORY;
|
|
972
|
+
else node_process.default.env.CCOMMAND_NO_HISTORY = prevNoHistory;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
const isZh$2 = node_process.default.env.PI_Lang === "zh";
|
|
976
|
+
const safeShellValue = /^[\w./:@%+=,-]+$/;
|
|
932
977
|
function isNoHistory$1(value) {
|
|
933
978
|
if (!value) return false;
|
|
934
979
|
const normalized = value.toLowerCase();
|
|
935
980
|
return normalized === "1" || normalized === "true" || normalized === "yes";
|
|
936
981
|
}
|
|
982
|
+
function shellQuote(value) {
|
|
983
|
+
if (value === "") return "''";
|
|
984
|
+
if (safeShellValue.test(value)) return value;
|
|
985
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
986
|
+
}
|
|
987
|
+
function powerShellQuote(value) {
|
|
988
|
+
if (value === "") return "''";
|
|
989
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
990
|
+
}
|
|
991
|
+
function splitCommand(value) {
|
|
992
|
+
const parts = [];
|
|
993
|
+
let current = "";
|
|
994
|
+
let quote = null;
|
|
995
|
+
let hasValue = false;
|
|
996
|
+
const pushCurrent = () => {
|
|
997
|
+
if (!hasValue) return;
|
|
998
|
+
parts.push(current);
|
|
999
|
+
current = "";
|
|
1000
|
+
hasValue = false;
|
|
1001
|
+
};
|
|
1002
|
+
for (let i = 0; i < value.length; i++) {
|
|
1003
|
+
const char = value[i];
|
|
1004
|
+
if (quote) {
|
|
1005
|
+
if (char === quote) {
|
|
1006
|
+
quote = null;
|
|
1007
|
+
hasValue = true;
|
|
1008
|
+
continue;
|
|
1009
|
+
}
|
|
1010
|
+
if (quote === "\"" && char === "\\") {
|
|
1011
|
+
const next = value[i + 1];
|
|
1012
|
+
if (next) {
|
|
1013
|
+
current += next;
|
|
1014
|
+
hasValue = true;
|
|
1015
|
+
i++;
|
|
1016
|
+
continue;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
current += char;
|
|
1020
|
+
hasValue = true;
|
|
1021
|
+
continue;
|
|
1022
|
+
}
|
|
1023
|
+
if (char === "\"" || char === "'") {
|
|
1024
|
+
quote = char;
|
|
1025
|
+
hasValue = true;
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
1028
|
+
if (/\s/.test(char)) {
|
|
1029
|
+
pushCurrent();
|
|
1030
|
+
while (i + 1 < value.length && /\s/.test(value[i + 1])) i++;
|
|
1031
|
+
continue;
|
|
1032
|
+
}
|
|
1033
|
+
if (char === "\\") {
|
|
1034
|
+
const next = value[i + 1];
|
|
1035
|
+
if (next) {
|
|
1036
|
+
current += next;
|
|
1037
|
+
hasValue = true;
|
|
1038
|
+
i++;
|
|
1039
|
+
continue;
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
current += char;
|
|
1043
|
+
hasValue = true;
|
|
1044
|
+
}
|
|
1045
|
+
pushCurrent();
|
|
1046
|
+
return parts;
|
|
1047
|
+
}
|
|
1048
|
+
function normalizeShellName(value) {
|
|
1049
|
+
const shell = (value || "").toLowerCase().replace(/\.exe$/, "");
|
|
1050
|
+
if (shell === "powershell") return "powershell";
|
|
1051
|
+
if (shell === "pwsh") return "pwsh";
|
|
1052
|
+
if (shell === "fish" || shell === "zsh" || shell === "bash") return shell;
|
|
1053
|
+
return shell;
|
|
1054
|
+
}
|
|
1055
|
+
function detectShell() {
|
|
1056
|
+
const envShell = normalizeShellName(node_path.default.basename(node_process.default.env.SHELL || ""));
|
|
1057
|
+
if (node_process.default.env.FISH_VERSION) return "fish";
|
|
1058
|
+
if (node_process.default.env.ZSH_VERSION) return "zsh";
|
|
1059
|
+
if (node_process.default.env.BASH_VERSION) return "bash";
|
|
1060
|
+
if (node_process.default.env.POWERSHELL_DISTRIBUTION_CHANNEL) return "pwsh";
|
|
1061
|
+
if (envShell) return envShell;
|
|
1062
|
+
if (node_process.default.platform === "win32") return "powershell";
|
|
1063
|
+
return "zsh";
|
|
1064
|
+
}
|
|
1065
|
+
function getPowerShellProfilePath(shell, home) {
|
|
1066
|
+
if (node_process.default.platform === "win32") {
|
|
1067
|
+
const documentsHome = node_process.default.env.USERPROFILE || home;
|
|
1068
|
+
const profileDir = shell === "pwsh" ? "PowerShell" : "WindowsPowerShell";
|
|
1069
|
+
return node_path.default.join(documentsHome, "Documents", profileDir, "Microsoft.PowerShell_profile.ps1");
|
|
1070
|
+
}
|
|
1071
|
+
const configHome = node_process.default.env.XDG_CONFIG_HOME || node_path.default.join(home, ".config");
|
|
1072
|
+
return node_path.default.join(configHome, "powershell", "Microsoft.PowerShell_profile.ps1");
|
|
1073
|
+
}
|
|
1074
|
+
function ensurePrunAutoInit() {
|
|
1075
|
+
if (!shouldAutoInit()) return;
|
|
1076
|
+
const shell = detectShell();
|
|
1077
|
+
const home = node_process.default.env.HOME || node_os.default.homedir();
|
|
1078
|
+
let rcFile = "";
|
|
1079
|
+
let initLine = "";
|
|
1080
|
+
if (shell === "zsh") {
|
|
1081
|
+
const zdotdir = node_process.default.env.ZDOTDIR || home;
|
|
1082
|
+
rcFile = node_path.default.join(zdotdir, ".zshrc");
|
|
1083
|
+
initLine = "eval \"$(prun --init zsh)\"";
|
|
1084
|
+
} else if (shell === "bash") {
|
|
1085
|
+
rcFile = node_path.default.join(home, ".bashrc");
|
|
1086
|
+
initLine = "eval \"$(prun --init bash)\"";
|
|
1087
|
+
} else if (shell === "fish") {
|
|
1088
|
+
const configHome = node_process.default.env.XDG_CONFIG_HOME || node_path.default.join(home, ".config");
|
|
1089
|
+
rcFile = node_path.default.join(configHome, "fish", "config.fish");
|
|
1090
|
+
initLine = "prun --init fish | source";
|
|
1091
|
+
} else if (shell === "powershell" || shell === "pwsh") {
|
|
1092
|
+
rcFile = getPowerShellProfilePath(shell, home);
|
|
1093
|
+
initLine = `prun --init ${shell} | Out-String | Invoke-Expression`;
|
|
1094
|
+
} else return;
|
|
1095
|
+
try {
|
|
1096
|
+
const dir = node_path.default.dirname(rcFile);
|
|
1097
|
+
if (!node_fs.default.existsSync(dir)) node_fs.default.mkdirSync(dir, { recursive: true });
|
|
1098
|
+
const content = node_fs.default.existsSync(rcFile) ? node_fs.default.readFileSync(rcFile, "utf8") : "";
|
|
1099
|
+
if (!/prun\s+--init/.test(content)) {
|
|
1100
|
+
const prefix = content.length && !content.endsWith("\n") ? "\n" : "";
|
|
1101
|
+
node_fs.default.appendFileSync(rcFile, `${prefix}${initLine}\n`, "utf8");
|
|
1102
|
+
}
|
|
1103
|
+
} catch {}
|
|
1104
|
+
}
|
|
1105
|
+
function shouldAutoInit() {
|
|
1106
|
+
const auto = node_process.default.env.PI_AUTO_INIT || node_process.default.env.PRUN_AUTO_INIT;
|
|
1107
|
+
if (auto != null) return isNoHistory$1(auto);
|
|
1108
|
+
if (isNoHistory$1(node_process.default.env.PI_NO_AUTO_INIT || node_process.default.env.PRUN_NO_AUTO_INIT)) return false;
|
|
1109
|
+
if (node_process.default.env.CI) return false;
|
|
1110
|
+
if (!node_process.default.stdout.isTTY || !node_process.default.stdin.isTTY) return false;
|
|
1111
|
+
return true;
|
|
1112
|
+
}
|
|
1113
|
+
function printPrunInit(args = []) {
|
|
1114
|
+
const shellArg = normalizeShellName(args[0]);
|
|
1115
|
+
const binArg = args[1] || node_process.default.env.PRUN_BIN || "prun";
|
|
1116
|
+
const bin = shellQuote(binArg);
|
|
1117
|
+
const shell = shellArg || detectShell() || "zsh";
|
|
1118
|
+
const historyHintExpr = "${CCOMMAND_HISTORY_HINT:-${XDG_CACHE_HOME:-$HOME/.cache}/ccommand/last-history}";
|
|
1119
|
+
let script = "";
|
|
1120
|
+
if (shell === "zsh") script = [
|
|
1121
|
+
"prun() {",
|
|
1122
|
+
` local bin=${bin}`,
|
|
1123
|
+
" local -a cmd",
|
|
1124
|
+
" cmd=(${=bin})",
|
|
1125
|
+
" command \"${cmd[@]}\" \"$@\"",
|
|
1126
|
+
"}",
|
|
1127
|
+
"__prun_sync_history() {",
|
|
1128
|
+
" local history_disable=${CCOMMAND_NO_HISTORY:-${NO_HISTORY:-\"\"}}",
|
|
1129
|
+
" local history_disable_lower=${history_disable:l}",
|
|
1130
|
+
" if [[ $history_disable_lower == \"1\" || $history_disable_lower == \"true\" || $history_disable_lower == \"yes\" ]]; then",
|
|
1131
|
+
" return",
|
|
1132
|
+
" fi",
|
|
1133
|
+
` local history_hint=${historyHintExpr}`,
|
|
1134
|
+
" if [[ ! -f $history_hint ]]; then",
|
|
1135
|
+
" return",
|
|
1136
|
+
" fi",
|
|
1137
|
+
" local line",
|
|
1138
|
+
" line=$(<\"$history_hint\")",
|
|
1139
|
+
" local hint_ts=${line%%$'\\t'*}",
|
|
1140
|
+
" local hint_cmd=${line#*$'\\t'}",
|
|
1141
|
+
" if [[ -z $hint_ts || $hint_ts == $line ]]; then",
|
|
1142
|
+
" hint_cmd=$line",
|
|
1143
|
+
" hint_ts=\"\"",
|
|
1144
|
+
" fi",
|
|
1145
|
+
" if [[ -n $hint_ts && $hint_ts == ${__PRUN_HISTORY_HINT_TS:-\"\"} ]]; then",
|
|
1146
|
+
" return",
|
|
1147
|
+
" fi",
|
|
1148
|
+
" __PRUN_HISTORY_HINT_TS=$hint_ts",
|
|
1149
|
+
" fc -R",
|
|
1150
|
+
" if [[ $hint_cmd != pfind* && $hint_cmd != prun* ]]; then",
|
|
1151
|
+
" return",
|
|
1152
|
+
" fi",
|
|
1153
|
+
" local last_line",
|
|
1154
|
+
" last_line=$(fc -l -1 2>/dev/null)",
|
|
1155
|
+
" local last_cmd",
|
|
1156
|
+
" last_cmd=$(printf \"%s\" \"$last_line\" | sed -E \"s/^[[:space:]]*[0-9]+[[:space:]]*//\")",
|
|
1157
|
+
" if [[ $last_cmd == \"$hint_cmd\" ]]; then",
|
|
1158
|
+
" return",
|
|
1159
|
+
" fi",
|
|
1160
|
+
" if [[ $last_cmd == prun || $last_cmd == prun\\ * ]]; then",
|
|
1161
|
+
" local last_num",
|
|
1162
|
+
" last_num=$(printf \"%s\" \"$last_line\" | sed -E \"s/^[[:space:]]*([0-9]+).*/\\1/\")",
|
|
1163
|
+
" if [[ -n $last_num ]]; then",
|
|
1164
|
+
" history -d $last_num 2>/dev/null",
|
|
1165
|
+
" fi",
|
|
1166
|
+
" fi",
|
|
1167
|
+
" print -s -- \"$hint_cmd\"",
|
|
1168
|
+
"}",
|
|
1169
|
+
"",
|
|
1170
|
+
"if ! typeset -f __prun_precmd >/dev/null; then",
|
|
1171
|
+
" __prun_precmd() { __prun_sync_history }",
|
|
1172
|
+
" autoload -Uz add-zsh-hook",
|
|
1173
|
+
" add-zsh-hook precmd __prun_precmd",
|
|
1174
|
+
"fi"
|
|
1175
|
+
].join("\n");
|
|
1176
|
+
else if (shell === "bash") script = [
|
|
1177
|
+
"prun() {",
|
|
1178
|
+
` local bin=${bin}`,
|
|
1179
|
+
" local -a cmd",
|
|
1180
|
+
" read -r -a cmd <<< \"$bin\"",
|
|
1181
|
+
" command \"${cmd[@]}\" \"$@\"",
|
|
1182
|
+
"}",
|
|
1183
|
+
"__prun_sync_history() {",
|
|
1184
|
+
" local history_disable=${CCOMMAND_NO_HISTORY:-${NO_HISTORY:-\"\"}}",
|
|
1185
|
+
" local history_disable_lower",
|
|
1186
|
+
" history_disable_lower=$(printf '%s' \"$history_disable\" | tr '[:upper:]' '[:lower:]')",
|
|
1187
|
+
" if [[ $history_disable_lower == \"1\" || $history_disable_lower == \"true\" || $history_disable_lower == \"yes\" ]]; then",
|
|
1188
|
+
" return",
|
|
1189
|
+
" fi",
|
|
1190
|
+
` local history_hint=${historyHintExpr}`,
|
|
1191
|
+
" if [[ ! -f $history_hint ]]; then",
|
|
1192
|
+
" return",
|
|
1193
|
+
" fi",
|
|
1194
|
+
" local line",
|
|
1195
|
+
" line=$(<\"$history_hint\")",
|
|
1196
|
+
" local hint_ts=\"${line%%$'\\t'*}\"",
|
|
1197
|
+
" local hint_cmd=\"${line#*$'\\t'}\"",
|
|
1198
|
+
" if [[ -z $hint_ts || $hint_ts == \"$line\" ]]; then",
|
|
1199
|
+
" hint_cmd=\"$line\"",
|
|
1200
|
+
" hint_ts=\"\"",
|
|
1201
|
+
" fi",
|
|
1202
|
+
" if [[ -n $hint_ts && $hint_ts == \"${__PRUN_HISTORY_HINT_TS:-}\" ]]; then",
|
|
1203
|
+
" return",
|
|
1204
|
+
" fi",
|
|
1205
|
+
" __PRUN_HISTORY_HINT_TS=$hint_ts",
|
|
1206
|
+
" if [[ $hint_cmd != pfind* && $hint_cmd != prun* ]]; then",
|
|
1207
|
+
" return",
|
|
1208
|
+
" fi",
|
|
1209
|
+
" history -n",
|
|
1210
|
+
" local last_line",
|
|
1211
|
+
" last_line=$(history 1)",
|
|
1212
|
+
" local last_cmd",
|
|
1213
|
+
" last_cmd=$(printf \"%s\" \"$last_line\" | sed -E \"s/^[[:space:]]*[0-9]+[[:space:]]*//\")",
|
|
1214
|
+
" if [[ $last_cmd == \"$hint_cmd\" ]]; then",
|
|
1215
|
+
" return",
|
|
1216
|
+
" fi",
|
|
1217
|
+
" if [[ $last_cmd == prun || $last_cmd == prun\\ * ]]; then",
|
|
1218
|
+
" local last_num",
|
|
1219
|
+
" last_num=$(printf \"%s\" \"$last_line\" | sed -E \"s/^[[:space:]]*([0-9]+).*/\\1/\")",
|
|
1220
|
+
" if [[ -n $last_num ]]; then",
|
|
1221
|
+
" history -d \"$last_num\" 2>/dev/null",
|
|
1222
|
+
" fi",
|
|
1223
|
+
" fi",
|
|
1224
|
+
" history -s -- \"$hint_cmd\"",
|
|
1225
|
+
"}",
|
|
1226
|
+
"",
|
|
1227
|
+
"if [[ -z \"${__PRUN_PROMPT_INSTALLED:-}\" ]]; then",
|
|
1228
|
+
" __PRUN_PROMPT_INSTALLED=1",
|
|
1229
|
+
" if [[ -n \"${PROMPT_COMMAND:-}\" ]]; then",
|
|
1230
|
+
" PROMPT_COMMAND=\"__prun_sync_history;${PROMPT_COMMAND}\"",
|
|
1231
|
+
" else",
|
|
1232
|
+
" PROMPT_COMMAND=\"__prun_sync_history\"",
|
|
1233
|
+
" fi",
|
|
1234
|
+
"fi"
|
|
1235
|
+
].join("\n");
|
|
1236
|
+
else if (shell === "fish") script = [
|
|
1237
|
+
"function prun",
|
|
1238
|
+
` set -l bin ${bin}`,
|
|
1239
|
+
" set -l cmd (string split -- \" \" $bin)",
|
|
1240
|
+
" command $cmd $argv",
|
|
1241
|
+
" set -l history_disable $CCOMMAND_NO_HISTORY",
|
|
1242
|
+
" if test -z \"$history_disable\"",
|
|
1243
|
+
" set history_disable $NO_HISTORY",
|
|
1244
|
+
" end",
|
|
1245
|
+
" set history_disable (string lower -- (string trim -- \"$history_disable\"))",
|
|
1246
|
+
" if test \"$history_disable\" != \"1\" -a \"$history_disable\" != \"true\" -a \"$history_disable\" != \"yes\"",
|
|
1247
|
+
" history --merge",
|
|
1248
|
+
" set -l history_hint $CCOMMAND_HISTORY_HINT",
|
|
1249
|
+
" if test -z \"$history_hint\"",
|
|
1250
|
+
" set -l cache_home $XDG_CACHE_HOME",
|
|
1251
|
+
" if test -z \"$cache_home\"",
|
|
1252
|
+
" set cache_home \"$HOME/.cache\"",
|
|
1253
|
+
" end",
|
|
1254
|
+
" set history_hint \"$cache_home/ccommand/last-history\"",
|
|
1255
|
+
" end",
|
|
1256
|
+
" if test -f \"$history_hint\"",
|
|
1257
|
+
" set -l last_cmd (string trim -- (cat \"$history_hint\"))",
|
|
1258
|
+
" set -l last_cmd (string replace -r \"^[0-9]+\\t\" \"\" -- \"$last_cmd\")",
|
|
1259
|
+
" if string match -q \"pfind*\" -- \"$last_cmd\"; or string match -q \"prun*\" -- \"$last_cmd\"",
|
|
1260
|
+
" set -l last_hist (history --max=1)",
|
|
1261
|
+
" if test \"$last_hist\" != \"$last_cmd\"",
|
|
1262
|
+
" history add -- \"$last_cmd\"",
|
|
1263
|
+
" end",
|
|
1264
|
+
" end",
|
|
1265
|
+
" end",
|
|
1266
|
+
" end",
|
|
1267
|
+
"end"
|
|
1268
|
+
].join("\n");
|
|
1269
|
+
else if (shell === "powershell" || shell === "pwsh") script = [
|
|
1270
|
+
`$script:__prun_bin = @(${splitCommand(binArg).map(powerShellQuote).join(", ") || powerShellQuote("prun")})`,
|
|
1271
|
+
"",
|
|
1272
|
+
"function global:prun {",
|
|
1273
|
+
" param([Parameter(ValueFromRemainingArguments = $true)] [string[]] $CliArgs)",
|
|
1274
|
+
" $command = $script:__prun_bin[0]",
|
|
1275
|
+
" if ($command -ieq \"prun\") {",
|
|
1276
|
+
" $resolved = Get-Command -Name $command -CommandType Application,ExternalScript -ErrorAction SilentlyContinue | Select-Object -First 1",
|
|
1277
|
+
" if ($null -ne $resolved) {",
|
|
1278
|
+
" if ($resolved.Path) { $command = $resolved.Path }",
|
|
1279
|
+
" elseif ($resolved.Definition) { $command = $resolved.Definition }",
|
|
1280
|
+
" elseif ($resolved.Source) { $command = $resolved.Source }",
|
|
1281
|
+
" }",
|
|
1282
|
+
" }",
|
|
1283
|
+
" $extra = @()",
|
|
1284
|
+
" if ($script:__prun_bin.Count -gt 1) {",
|
|
1285
|
+
" $extra = $script:__prun_bin[1..($script:__prun_bin.Count - 1)]",
|
|
1286
|
+
" }",
|
|
1287
|
+
" & $command @extra @CliArgs",
|
|
1288
|
+
"}",
|
|
1289
|
+
"",
|
|
1290
|
+
"function global:__prun_sync_history {",
|
|
1291
|
+
" $historyDisable = $env:CCOMMAND_NO_HISTORY",
|
|
1292
|
+
" if ([string]::IsNullOrWhiteSpace($historyDisable)) {",
|
|
1293
|
+
" $historyDisable = $env:NO_HISTORY",
|
|
1294
|
+
" }",
|
|
1295
|
+
" $historyDisable = \"$historyDisable\".Trim().ToLowerInvariant()",
|
|
1296
|
+
" if ($historyDisable -eq \"1\" -or $historyDisable -eq \"true\" -or $historyDisable -eq \"yes\") {",
|
|
1297
|
+
" return",
|
|
1298
|
+
" }",
|
|
1299
|
+
" $historyHint = $env:CCOMMAND_HISTORY_HINT",
|
|
1300
|
+
" if ([string]::IsNullOrWhiteSpace($historyHint)) {",
|
|
1301
|
+
" $cacheHome = $env:XDG_CACHE_HOME",
|
|
1302
|
+
" if ([string]::IsNullOrWhiteSpace($cacheHome)) {",
|
|
1303
|
+
" $cacheHome = Join-Path $HOME \".cache\"",
|
|
1304
|
+
" }",
|
|
1305
|
+
" $historyHint = Join-Path (Join-Path $cacheHome \"ccommand\") \"last-history\"",
|
|
1306
|
+
" }",
|
|
1307
|
+
" if (-not (Test-Path -LiteralPath $historyHint)) {",
|
|
1308
|
+
" return",
|
|
1309
|
+
" }",
|
|
1310
|
+
" $line = (Get-Content -LiteralPath $historyHint -Raw -ErrorAction SilentlyContinue)",
|
|
1311
|
+
" if ([string]::IsNullOrWhiteSpace($line)) {",
|
|
1312
|
+
" return",
|
|
1313
|
+
" }",
|
|
1314
|
+
" $line = $line.Trim()",
|
|
1315
|
+
" $hintTs = \"\"",
|
|
1316
|
+
" $hintCmd = $line",
|
|
1317
|
+
" $parts = $line -split \"`t\", 2",
|
|
1318
|
+
" if ($parts.Count -eq 2 -and $parts[0] -match \"^\\d+$\") {",
|
|
1319
|
+
" $hintTs = $parts[0]",
|
|
1320
|
+
" $hintCmd = $parts[1]",
|
|
1321
|
+
" }",
|
|
1322
|
+
" if (-not $hintCmd.StartsWith(\"prun\") -and -not $hintCmd.StartsWith(\"pfind\")) {",
|
|
1323
|
+
" return",
|
|
1324
|
+
" }",
|
|
1325
|
+
" if ($hintTs -and $script:__PRUN_HISTORY_HINT_TS -eq $hintTs) {",
|
|
1326
|
+
" return",
|
|
1327
|
+
" }",
|
|
1328
|
+
" $script:__PRUN_HISTORY_HINT_TS = $hintTs",
|
|
1329
|
+
" $psReadLineType = \"Microsoft.PowerShell.PSConsoleReadLine\" -as [type]",
|
|
1330
|
+
" if ($null -eq $psReadLineType) {",
|
|
1331
|
+
" return",
|
|
1332
|
+
" }",
|
|
1333
|
+
" $psReadLineType::AddToHistory($hintCmd)",
|
|
1334
|
+
"}",
|
|
1335
|
+
"",
|
|
1336
|
+
"if (-not $script:__PRUN_PROMPT_INSTALLED) {",
|
|
1337
|
+
" $script:__PRUN_PROMPT_INSTALLED = $true",
|
|
1338
|
+
" if (-not $script:__prun_original_prompt) {",
|
|
1339
|
+
" if (Test-Path Function:\\prompt) {",
|
|
1340
|
+
" $script:__prun_original_prompt = $function:prompt",
|
|
1341
|
+
" }",
|
|
1342
|
+
" }",
|
|
1343
|
+
" function global:prompt {",
|
|
1344
|
+
" __prun_sync_history",
|
|
1345
|
+
" if ($script:__prun_original_prompt) {",
|
|
1346
|
+
" & $script:__prun_original_prompt",
|
|
1347
|
+
" return",
|
|
1348
|
+
" }",
|
|
1349
|
+
" \"PS $($executionContext.SessionState.Path.CurrentLocation)> \"",
|
|
1350
|
+
" }",
|
|
1351
|
+
"}"
|
|
1352
|
+
].join("\n");
|
|
1353
|
+
else {
|
|
1354
|
+
console.log(picocolors.default.red(isZh$2 ? `不支持的 shell: ${shell}` : `Unsupported shell: ${shell}`));
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
console.log(script);
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
//#endregion
|
|
1361
|
+
//#region src/pfind.ts
|
|
1362
|
+
function isNoHistory(value) {
|
|
1363
|
+
if (!value) return false;
|
|
1364
|
+
const normalized = value.toLowerCase();
|
|
1365
|
+
return normalized === "1" || normalized === "true" || normalized === "yes";
|
|
1366
|
+
}
|
|
937
1367
|
async function pfind(params) {
|
|
1368
|
+
ensurePrunAutoInit();
|
|
938
1369
|
const hadNoHistoryEnv = node_process.default.env.CCOMMAND_NO_HISTORY != null || node_process.default.env.NO_HISTORY != null;
|
|
939
1370
|
const initialNoHistory = node_process.default.env.CCOMMAND_NO_HISTORY ?? node_process.default.env.NO_HISTORY;
|
|
940
|
-
const shouldWriteHistory = !(hadNoHistoryEnv && isNoHistory
|
|
1371
|
+
const shouldWriteHistory = !(hadNoHistoryEnv && isNoHistory(initialNoHistory));
|
|
941
1372
|
const prevNoHistory = node_process.default.env.CCOMMAND_NO_HISTORY;
|
|
942
1373
|
if (shouldWriteHistory) delete node_process.default.env.CCOMMAND_NO_HISTORY;
|
|
943
1374
|
else node_process.default.env.CCOMMAND_NO_HISTORY = "1";
|
|
@@ -1059,117 +1490,6 @@ async function pix(params) {
|
|
|
1059
1490
|
}
|
|
1060
1491
|
}
|
|
1061
1492
|
|
|
1062
|
-
//#endregion
|
|
1063
|
-
//#region src/prun.ts
|
|
1064
|
-
async function prun(params) {
|
|
1065
|
-
ensurePrunAutoInit();
|
|
1066
|
-
const hadNoHistoryEnv = node_process.default.env.CCOMMAND_NO_HISTORY != null || node_process.default.env.NO_HISTORY != null;
|
|
1067
|
-
const initialNoHistory = node_process.default.env.CCOMMAND_NO_HISTORY ?? node_process.default.env.NO_HISTORY;
|
|
1068
|
-
const prevNoHistory = node_process.default.env.CCOMMAND_NO_HISTORY;
|
|
1069
|
-
if (!(hadNoHistoryEnv && isNoHistory(initialNoHistory))) delete node_process.default.env.CCOMMAND_NO_HISTORY;
|
|
1070
|
-
else node_process.default.env.CCOMMAND_NO_HISTORY = "1";
|
|
1071
|
-
const { ccommand } = getCcommand();
|
|
1072
|
-
try {
|
|
1073
|
-
await ccommand(params);
|
|
1074
|
-
} finally {
|
|
1075
|
-
if (prevNoHistory == null) delete node_process.default.env.CCOMMAND_NO_HISTORY;
|
|
1076
|
-
else node_process.default.env.CCOMMAND_NO_HISTORY = prevNoHistory;
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
const isZh$2 = node_process.default.env.PI_Lang === "zh";
|
|
1080
|
-
const safeShellValue = /^[\w./:@%+=,-]+$/;
|
|
1081
|
-
function isNoHistory(value) {
|
|
1082
|
-
if (!value) return false;
|
|
1083
|
-
const normalized = value.toLowerCase();
|
|
1084
|
-
return normalized === "1" || normalized === "true" || normalized === "yes";
|
|
1085
|
-
}
|
|
1086
|
-
function shellQuote(value) {
|
|
1087
|
-
if (value === "") return "''";
|
|
1088
|
-
if (safeShellValue.test(value)) return value;
|
|
1089
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
1090
|
-
}
|
|
1091
|
-
function detectShell() {
|
|
1092
|
-
const envShell = node_process.default.env.SHELL || "";
|
|
1093
|
-
if (node_process.default.env.FISH_VERSION) return "fish";
|
|
1094
|
-
if (node_process.default.env.ZSH_VERSION) return "zsh";
|
|
1095
|
-
if (node_process.default.env.BASH_VERSION) return "bash";
|
|
1096
|
-
return envShell.split("/").pop() || "zsh";
|
|
1097
|
-
}
|
|
1098
|
-
function ensurePrunAutoInit() {
|
|
1099
|
-
if (!shouldAutoInit()) return;
|
|
1100
|
-
const shell = detectShell();
|
|
1101
|
-
const home = node_process.default.env.HOME || node_os.default.homedir();
|
|
1102
|
-
let rcFile = "";
|
|
1103
|
-
let initLine = "";
|
|
1104
|
-
if (shell === "zsh") {
|
|
1105
|
-
const zdotdir = node_process.default.env.ZDOTDIR || home;
|
|
1106
|
-
rcFile = node_path.default.join(zdotdir, ".zshrc");
|
|
1107
|
-
initLine = "eval \"$(prun --init zsh)\"";
|
|
1108
|
-
} else if (shell === "bash") {
|
|
1109
|
-
rcFile = node_path.default.join(home, ".bashrc");
|
|
1110
|
-
initLine = "eval \"$(prun --init bash)\"";
|
|
1111
|
-
} else if (shell === "fish") {
|
|
1112
|
-
const configHome = node_process.default.env.XDG_CONFIG_HOME || node_path.default.join(home, ".config");
|
|
1113
|
-
rcFile = node_path.default.join(configHome, "fish", "config.fish");
|
|
1114
|
-
initLine = "prun --init fish | source";
|
|
1115
|
-
} else return;
|
|
1116
|
-
try {
|
|
1117
|
-
const dir = node_path.default.dirname(rcFile);
|
|
1118
|
-
if (!node_fs.default.existsSync(dir)) node_fs.default.mkdirSync(dir, { recursive: true });
|
|
1119
|
-
const content = node_fs.default.existsSync(rcFile) ? node_fs.default.readFileSync(rcFile, "utf8") : "";
|
|
1120
|
-
if (!/prun\s+--init/.test(content)) {
|
|
1121
|
-
const prefix = content.length && !content.endsWith("\n") ? "\n" : "";
|
|
1122
|
-
node_fs.default.appendFileSync(rcFile, `${prefix}${initLine}\n`, "utf8");
|
|
1123
|
-
}
|
|
1124
|
-
} catch {}
|
|
1125
|
-
}
|
|
1126
|
-
function shouldAutoInit() {
|
|
1127
|
-
const auto = node_process.default.env.PI_AUTO_INIT || node_process.default.env.PRUN_AUTO_INIT;
|
|
1128
|
-
if (auto != null) return isNoHistory(auto);
|
|
1129
|
-
if (isNoHistory(node_process.default.env.PI_NO_AUTO_INIT || node_process.default.env.PRUN_NO_AUTO_INIT)) return false;
|
|
1130
|
-
if (node_process.default.env.CI) return false;
|
|
1131
|
-
if (!node_process.default.stdout.isTTY || !node_process.default.stdin.isTTY) return false;
|
|
1132
|
-
return true;
|
|
1133
|
-
}
|
|
1134
|
-
function printPrunInit(args = []) {
|
|
1135
|
-
const shellArg = args[0];
|
|
1136
|
-
const binArg = args[1];
|
|
1137
|
-
const bin = shellQuote(binArg || node_process.default.env.PRUN_BIN || "prun");
|
|
1138
|
-
const shell = shellArg || detectShell() || "zsh";
|
|
1139
|
-
let script = "";
|
|
1140
|
-
if (shell === "zsh") script = [
|
|
1141
|
-
"prun() {",
|
|
1142
|
-
` local bin=${bin}`,
|
|
1143
|
-
" local -a cmd",
|
|
1144
|
-
" cmd=(${=bin})",
|
|
1145
|
-
" command \"${cmd[@]}\" \"$@\"",
|
|
1146
|
-
" fc -R",
|
|
1147
|
-
"}"
|
|
1148
|
-
].join("\n");
|
|
1149
|
-
else if (shell === "bash") script = [
|
|
1150
|
-
"prun() {",
|
|
1151
|
-
` local bin=${bin}`,
|
|
1152
|
-
" local -a cmd",
|
|
1153
|
-
" read -r -a cmd <<< \"$bin\"",
|
|
1154
|
-
" command \"${cmd[@]}\" \"$@\"",
|
|
1155
|
-
" history -n",
|
|
1156
|
-
"}"
|
|
1157
|
-
].join("\n");
|
|
1158
|
-
else if (shell === "fish") script = [
|
|
1159
|
-
"function prun",
|
|
1160
|
-
` set -l bin ${bin}`,
|
|
1161
|
-
" set -l cmd (string split -- \" \" $bin)",
|
|
1162
|
-
" command $cmd $argv",
|
|
1163
|
-
" history --merge",
|
|
1164
|
-
"end"
|
|
1165
|
-
].join("\n");
|
|
1166
|
-
else {
|
|
1167
|
-
console.log(picocolors.default.red(isZh$2 ? `不支持的 shell: ${shell}` : `Unsupported shell: ${shell}`));
|
|
1168
|
-
return;
|
|
1169
|
-
}
|
|
1170
|
-
console.log(script);
|
|
1171
|
-
}
|
|
1172
|
-
|
|
1173
1493
|
//#endregion
|
|
1174
1494
|
//#region src/pu.ts
|
|
1175
1495
|
function pu() {
|
package/dist/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import os from "node:os";
|
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
13
13
|
|
|
14
14
|
//#region package.json
|
|
15
|
-
var version = "0.2.
|
|
15
|
+
var version = "0.2.10";
|
|
16
16
|
|
|
17
17
|
//#endregion
|
|
18
18
|
//#region src/tty.ts
|
|
@@ -522,8 +522,30 @@ async function detectNode() {
|
|
|
522
522
|
|
|
523
523
|
//#endregion
|
|
524
524
|
//#region src/pkgManager.ts
|
|
525
|
+
function normalizeDir$1(dir) {
|
|
526
|
+
return path.resolve(dir);
|
|
527
|
+
}
|
|
528
|
+
function findUpSync$1(startDir, predicate) {
|
|
529
|
+
let current = normalizeDir$1(startDir);
|
|
530
|
+
while (true) {
|
|
531
|
+
if (predicate(current)) return current;
|
|
532
|
+
const parent = path.dirname(current);
|
|
533
|
+
if (parent === current) return null;
|
|
534
|
+
current = parent;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
function inferToolFromRepoLayout(cwd) {
|
|
538
|
+
if (findUpSync$1(cwd, (dir) => isFile(path.join(dir, "pnpm-workspace.yaml")) || isFile(path.join(dir, "pnpm-lock.yaml")))) return "pnpm";
|
|
539
|
+
if (findUpSync$1(cwd, (dir) => isFile(path.join(dir, "yarn.lock")) || isFile(path.join(dir, ".yarnrc.yml")))) return "yarn";
|
|
540
|
+
if (findUpSync$1(cwd, (dir) => isFile(path.join(dir, "bun.lockb")))) return "bun";
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
525
543
|
async function resolvePkgTool() {
|
|
526
|
-
|
|
544
|
+
let detected = await getPkgTool() || "npm";
|
|
545
|
+
if (detected === "npm") {
|
|
546
|
+
const inferred = inferToolFromRepoLayout(process.cwd());
|
|
547
|
+
if (inferred) detected = inferred;
|
|
548
|
+
}
|
|
527
549
|
const fallback = process.env.PI_DEFAULT;
|
|
528
550
|
return {
|
|
529
551
|
detected,
|
|
@@ -587,7 +609,13 @@ async function findUpAsync(startDir, predicate) {
|
|
|
587
609
|
async function getParams(params) {
|
|
588
610
|
const cwd = process.cwd();
|
|
589
611
|
try {
|
|
590
|
-
|
|
612
|
+
let tool = await getPkgTool() || "npm";
|
|
613
|
+
if (tool === "npm") {
|
|
614
|
+
if (findUpSync(cwd, (dir) => isFile(path.join(dir, "pnpm-workspace.yaml")) || isFile(path.join(dir, "pnpm-lock.yaml")))) tool = "pnpm";
|
|
615
|
+
else if (findUpSync(cwd, (dir) => isFile(path.join(dir, "yarn.lock")) || isFile(path.join(dir, ".yarnrc.yml")))) tool = "yarn";
|
|
616
|
+
else if (findUpSync(cwd, (dir) => isFile(path.join(dir, "bun.lockb")))) tool = "bun";
|
|
617
|
+
}
|
|
618
|
+
switch (tool) {
|
|
591
619
|
case "pnpm": {
|
|
592
620
|
const pnpmWorkspaceRoot = findUpSync(cwd, (dir) => isFile(path.join(dir, "pnpm-workspace.yaml")));
|
|
593
621
|
const inPnpmWorkspace = Boolean(pnpmWorkspaceRoot);
|
|
@@ -893,16 +921,419 @@ function getCcommand() {
|
|
|
893
921
|
}
|
|
894
922
|
|
|
895
923
|
//#endregion
|
|
896
|
-
//#region src/
|
|
924
|
+
//#region src/prun.ts
|
|
925
|
+
async function prun(params) {
|
|
926
|
+
ensurePrunAutoInit();
|
|
927
|
+
const hadNoHistoryEnv = process.env.CCOMMAND_NO_HISTORY != null || process.env.NO_HISTORY != null;
|
|
928
|
+
const initialNoHistory = process.env.CCOMMAND_NO_HISTORY ?? process.env.NO_HISTORY;
|
|
929
|
+
const prevNoHistory = process.env.CCOMMAND_NO_HISTORY;
|
|
930
|
+
if (!(hadNoHistoryEnv && isNoHistory$1(initialNoHistory))) delete process.env.CCOMMAND_NO_HISTORY;
|
|
931
|
+
else process.env.CCOMMAND_NO_HISTORY = "1";
|
|
932
|
+
const { ccommand } = getCcommand();
|
|
933
|
+
try {
|
|
934
|
+
await ccommand(params);
|
|
935
|
+
} finally {
|
|
936
|
+
if (prevNoHistory == null) delete process.env.CCOMMAND_NO_HISTORY;
|
|
937
|
+
else process.env.CCOMMAND_NO_HISTORY = prevNoHistory;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
const isZh$2 = process.env.PI_Lang === "zh";
|
|
941
|
+
const safeShellValue = /^[\w./:@%+=,-]+$/;
|
|
897
942
|
function isNoHistory$1(value) {
|
|
898
943
|
if (!value) return false;
|
|
899
944
|
const normalized = value.toLowerCase();
|
|
900
945
|
return normalized === "1" || normalized === "true" || normalized === "yes";
|
|
901
946
|
}
|
|
947
|
+
function shellQuote(value) {
|
|
948
|
+
if (value === "") return "''";
|
|
949
|
+
if (safeShellValue.test(value)) return value;
|
|
950
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
951
|
+
}
|
|
952
|
+
function powerShellQuote(value) {
|
|
953
|
+
if (value === "") return "''";
|
|
954
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
955
|
+
}
|
|
956
|
+
function splitCommand(value) {
|
|
957
|
+
const parts = [];
|
|
958
|
+
let current = "";
|
|
959
|
+
let quote = null;
|
|
960
|
+
let hasValue = false;
|
|
961
|
+
const pushCurrent = () => {
|
|
962
|
+
if (!hasValue) return;
|
|
963
|
+
parts.push(current);
|
|
964
|
+
current = "";
|
|
965
|
+
hasValue = false;
|
|
966
|
+
};
|
|
967
|
+
for (let i = 0; i < value.length; i++) {
|
|
968
|
+
const char = value[i];
|
|
969
|
+
if (quote) {
|
|
970
|
+
if (char === quote) {
|
|
971
|
+
quote = null;
|
|
972
|
+
hasValue = true;
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
if (quote === "\"" && char === "\\") {
|
|
976
|
+
const next = value[i + 1];
|
|
977
|
+
if (next) {
|
|
978
|
+
current += next;
|
|
979
|
+
hasValue = true;
|
|
980
|
+
i++;
|
|
981
|
+
continue;
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
current += char;
|
|
985
|
+
hasValue = true;
|
|
986
|
+
continue;
|
|
987
|
+
}
|
|
988
|
+
if (char === "\"" || char === "'") {
|
|
989
|
+
quote = char;
|
|
990
|
+
hasValue = true;
|
|
991
|
+
continue;
|
|
992
|
+
}
|
|
993
|
+
if (/\s/.test(char)) {
|
|
994
|
+
pushCurrent();
|
|
995
|
+
while (i + 1 < value.length && /\s/.test(value[i + 1])) i++;
|
|
996
|
+
continue;
|
|
997
|
+
}
|
|
998
|
+
if (char === "\\") {
|
|
999
|
+
const next = value[i + 1];
|
|
1000
|
+
if (next) {
|
|
1001
|
+
current += next;
|
|
1002
|
+
hasValue = true;
|
|
1003
|
+
i++;
|
|
1004
|
+
continue;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
current += char;
|
|
1008
|
+
hasValue = true;
|
|
1009
|
+
}
|
|
1010
|
+
pushCurrent();
|
|
1011
|
+
return parts;
|
|
1012
|
+
}
|
|
1013
|
+
function normalizeShellName(value) {
|
|
1014
|
+
const shell = (value || "").toLowerCase().replace(/\.exe$/, "");
|
|
1015
|
+
if (shell === "powershell") return "powershell";
|
|
1016
|
+
if (shell === "pwsh") return "pwsh";
|
|
1017
|
+
if (shell === "fish" || shell === "zsh" || shell === "bash") return shell;
|
|
1018
|
+
return shell;
|
|
1019
|
+
}
|
|
1020
|
+
function detectShell() {
|
|
1021
|
+
const envShell = normalizeShellName(path.basename(process.env.SHELL || ""));
|
|
1022
|
+
if (process.env.FISH_VERSION) return "fish";
|
|
1023
|
+
if (process.env.ZSH_VERSION) return "zsh";
|
|
1024
|
+
if (process.env.BASH_VERSION) return "bash";
|
|
1025
|
+
if (process.env.POWERSHELL_DISTRIBUTION_CHANNEL) return "pwsh";
|
|
1026
|
+
if (envShell) return envShell;
|
|
1027
|
+
if (process.platform === "win32") return "powershell";
|
|
1028
|
+
return "zsh";
|
|
1029
|
+
}
|
|
1030
|
+
function getPowerShellProfilePath(shell, home) {
|
|
1031
|
+
if (process.platform === "win32") {
|
|
1032
|
+
const documentsHome = process.env.USERPROFILE || home;
|
|
1033
|
+
const profileDir = shell === "pwsh" ? "PowerShell" : "WindowsPowerShell";
|
|
1034
|
+
return path.join(documentsHome, "Documents", profileDir, "Microsoft.PowerShell_profile.ps1");
|
|
1035
|
+
}
|
|
1036
|
+
const configHome = process.env.XDG_CONFIG_HOME || path.join(home, ".config");
|
|
1037
|
+
return path.join(configHome, "powershell", "Microsoft.PowerShell_profile.ps1");
|
|
1038
|
+
}
|
|
1039
|
+
function ensurePrunAutoInit() {
|
|
1040
|
+
if (!shouldAutoInit()) return;
|
|
1041
|
+
const shell = detectShell();
|
|
1042
|
+
const home = process.env.HOME || os.homedir();
|
|
1043
|
+
let rcFile = "";
|
|
1044
|
+
let initLine = "";
|
|
1045
|
+
if (shell === "zsh") {
|
|
1046
|
+
const zdotdir = process.env.ZDOTDIR || home;
|
|
1047
|
+
rcFile = path.join(zdotdir, ".zshrc");
|
|
1048
|
+
initLine = "eval \"$(prun --init zsh)\"";
|
|
1049
|
+
} else if (shell === "bash") {
|
|
1050
|
+
rcFile = path.join(home, ".bashrc");
|
|
1051
|
+
initLine = "eval \"$(prun --init bash)\"";
|
|
1052
|
+
} else if (shell === "fish") {
|
|
1053
|
+
const configHome = process.env.XDG_CONFIG_HOME || path.join(home, ".config");
|
|
1054
|
+
rcFile = path.join(configHome, "fish", "config.fish");
|
|
1055
|
+
initLine = "prun --init fish | source";
|
|
1056
|
+
} else if (shell === "powershell" || shell === "pwsh") {
|
|
1057
|
+
rcFile = getPowerShellProfilePath(shell, home);
|
|
1058
|
+
initLine = `prun --init ${shell} | Out-String | Invoke-Expression`;
|
|
1059
|
+
} else return;
|
|
1060
|
+
try {
|
|
1061
|
+
const dir = path.dirname(rcFile);
|
|
1062
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
1063
|
+
const content = fs.existsSync(rcFile) ? fs.readFileSync(rcFile, "utf8") : "";
|
|
1064
|
+
if (!/prun\s+--init/.test(content)) {
|
|
1065
|
+
const prefix = content.length && !content.endsWith("\n") ? "\n" : "";
|
|
1066
|
+
fs.appendFileSync(rcFile, `${prefix}${initLine}\n`, "utf8");
|
|
1067
|
+
}
|
|
1068
|
+
} catch {}
|
|
1069
|
+
}
|
|
1070
|
+
function shouldAutoInit() {
|
|
1071
|
+
const auto = process.env.PI_AUTO_INIT || process.env.PRUN_AUTO_INIT;
|
|
1072
|
+
if (auto != null) return isNoHistory$1(auto);
|
|
1073
|
+
if (isNoHistory$1(process.env.PI_NO_AUTO_INIT || process.env.PRUN_NO_AUTO_INIT)) return false;
|
|
1074
|
+
if (process.env.CI) return false;
|
|
1075
|
+
if (!process.stdout.isTTY || !process.stdin.isTTY) return false;
|
|
1076
|
+
return true;
|
|
1077
|
+
}
|
|
1078
|
+
function printPrunInit(args = []) {
|
|
1079
|
+
const shellArg = normalizeShellName(args[0]);
|
|
1080
|
+
const binArg = args[1] || process.env.PRUN_BIN || "prun";
|
|
1081
|
+
const bin = shellQuote(binArg);
|
|
1082
|
+
const shell = shellArg || detectShell() || "zsh";
|
|
1083
|
+
const historyHintExpr = "${CCOMMAND_HISTORY_HINT:-${XDG_CACHE_HOME:-$HOME/.cache}/ccommand/last-history}";
|
|
1084
|
+
let script = "";
|
|
1085
|
+
if (shell === "zsh") script = [
|
|
1086
|
+
"prun() {",
|
|
1087
|
+
` local bin=${bin}`,
|
|
1088
|
+
" local -a cmd",
|
|
1089
|
+
" cmd=(${=bin})",
|
|
1090
|
+
" command \"${cmd[@]}\" \"$@\"",
|
|
1091
|
+
"}",
|
|
1092
|
+
"__prun_sync_history() {",
|
|
1093
|
+
" local history_disable=${CCOMMAND_NO_HISTORY:-${NO_HISTORY:-\"\"}}",
|
|
1094
|
+
" local history_disable_lower=${history_disable:l}",
|
|
1095
|
+
" if [[ $history_disable_lower == \"1\" || $history_disable_lower == \"true\" || $history_disable_lower == \"yes\" ]]; then",
|
|
1096
|
+
" return",
|
|
1097
|
+
" fi",
|
|
1098
|
+
` local history_hint=${historyHintExpr}`,
|
|
1099
|
+
" if [[ ! -f $history_hint ]]; then",
|
|
1100
|
+
" return",
|
|
1101
|
+
" fi",
|
|
1102
|
+
" local line",
|
|
1103
|
+
" line=$(<\"$history_hint\")",
|
|
1104
|
+
" local hint_ts=${line%%$'\\t'*}",
|
|
1105
|
+
" local hint_cmd=${line#*$'\\t'}",
|
|
1106
|
+
" if [[ -z $hint_ts || $hint_ts == $line ]]; then",
|
|
1107
|
+
" hint_cmd=$line",
|
|
1108
|
+
" hint_ts=\"\"",
|
|
1109
|
+
" fi",
|
|
1110
|
+
" if [[ -n $hint_ts && $hint_ts == ${__PRUN_HISTORY_HINT_TS:-\"\"} ]]; then",
|
|
1111
|
+
" return",
|
|
1112
|
+
" fi",
|
|
1113
|
+
" __PRUN_HISTORY_HINT_TS=$hint_ts",
|
|
1114
|
+
" fc -R",
|
|
1115
|
+
" if [[ $hint_cmd != pfind* && $hint_cmd != prun* ]]; then",
|
|
1116
|
+
" return",
|
|
1117
|
+
" fi",
|
|
1118
|
+
" local last_line",
|
|
1119
|
+
" last_line=$(fc -l -1 2>/dev/null)",
|
|
1120
|
+
" local last_cmd",
|
|
1121
|
+
" last_cmd=$(printf \"%s\" \"$last_line\" | sed -E \"s/^[[:space:]]*[0-9]+[[:space:]]*//\")",
|
|
1122
|
+
" if [[ $last_cmd == \"$hint_cmd\" ]]; then",
|
|
1123
|
+
" return",
|
|
1124
|
+
" fi",
|
|
1125
|
+
" if [[ $last_cmd == prun || $last_cmd == prun\\ * ]]; then",
|
|
1126
|
+
" local last_num",
|
|
1127
|
+
" last_num=$(printf \"%s\" \"$last_line\" | sed -E \"s/^[[:space:]]*([0-9]+).*/\\1/\")",
|
|
1128
|
+
" if [[ -n $last_num ]]; then",
|
|
1129
|
+
" history -d $last_num 2>/dev/null",
|
|
1130
|
+
" fi",
|
|
1131
|
+
" fi",
|
|
1132
|
+
" print -s -- \"$hint_cmd\"",
|
|
1133
|
+
"}",
|
|
1134
|
+
"",
|
|
1135
|
+
"if ! typeset -f __prun_precmd >/dev/null; then",
|
|
1136
|
+
" __prun_precmd() { __prun_sync_history }",
|
|
1137
|
+
" autoload -Uz add-zsh-hook",
|
|
1138
|
+
" add-zsh-hook precmd __prun_precmd",
|
|
1139
|
+
"fi"
|
|
1140
|
+
].join("\n");
|
|
1141
|
+
else if (shell === "bash") script = [
|
|
1142
|
+
"prun() {",
|
|
1143
|
+
` local bin=${bin}`,
|
|
1144
|
+
" local -a cmd",
|
|
1145
|
+
" read -r -a cmd <<< \"$bin\"",
|
|
1146
|
+
" command \"${cmd[@]}\" \"$@\"",
|
|
1147
|
+
"}",
|
|
1148
|
+
"__prun_sync_history() {",
|
|
1149
|
+
" local history_disable=${CCOMMAND_NO_HISTORY:-${NO_HISTORY:-\"\"}}",
|
|
1150
|
+
" local history_disable_lower",
|
|
1151
|
+
" history_disable_lower=$(printf '%s' \"$history_disable\" | tr '[:upper:]' '[:lower:]')",
|
|
1152
|
+
" if [[ $history_disable_lower == \"1\" || $history_disable_lower == \"true\" || $history_disable_lower == \"yes\" ]]; then",
|
|
1153
|
+
" return",
|
|
1154
|
+
" fi",
|
|
1155
|
+
` local history_hint=${historyHintExpr}`,
|
|
1156
|
+
" if [[ ! -f $history_hint ]]; then",
|
|
1157
|
+
" return",
|
|
1158
|
+
" fi",
|
|
1159
|
+
" local line",
|
|
1160
|
+
" line=$(<\"$history_hint\")",
|
|
1161
|
+
" local hint_ts=\"${line%%$'\\t'*}\"",
|
|
1162
|
+
" local hint_cmd=\"${line#*$'\\t'}\"",
|
|
1163
|
+
" if [[ -z $hint_ts || $hint_ts == \"$line\" ]]; then",
|
|
1164
|
+
" hint_cmd=\"$line\"",
|
|
1165
|
+
" hint_ts=\"\"",
|
|
1166
|
+
" fi",
|
|
1167
|
+
" if [[ -n $hint_ts && $hint_ts == \"${__PRUN_HISTORY_HINT_TS:-}\" ]]; then",
|
|
1168
|
+
" return",
|
|
1169
|
+
" fi",
|
|
1170
|
+
" __PRUN_HISTORY_HINT_TS=$hint_ts",
|
|
1171
|
+
" if [[ $hint_cmd != pfind* && $hint_cmd != prun* ]]; then",
|
|
1172
|
+
" return",
|
|
1173
|
+
" fi",
|
|
1174
|
+
" history -n",
|
|
1175
|
+
" local last_line",
|
|
1176
|
+
" last_line=$(history 1)",
|
|
1177
|
+
" local last_cmd",
|
|
1178
|
+
" last_cmd=$(printf \"%s\" \"$last_line\" | sed -E \"s/^[[:space:]]*[0-9]+[[:space:]]*//\")",
|
|
1179
|
+
" if [[ $last_cmd == \"$hint_cmd\" ]]; then",
|
|
1180
|
+
" return",
|
|
1181
|
+
" fi",
|
|
1182
|
+
" if [[ $last_cmd == prun || $last_cmd == prun\\ * ]]; then",
|
|
1183
|
+
" local last_num",
|
|
1184
|
+
" last_num=$(printf \"%s\" \"$last_line\" | sed -E \"s/^[[:space:]]*([0-9]+).*/\\1/\")",
|
|
1185
|
+
" if [[ -n $last_num ]]; then",
|
|
1186
|
+
" history -d \"$last_num\" 2>/dev/null",
|
|
1187
|
+
" fi",
|
|
1188
|
+
" fi",
|
|
1189
|
+
" history -s -- \"$hint_cmd\"",
|
|
1190
|
+
"}",
|
|
1191
|
+
"",
|
|
1192
|
+
"if [[ -z \"${__PRUN_PROMPT_INSTALLED:-}\" ]]; then",
|
|
1193
|
+
" __PRUN_PROMPT_INSTALLED=1",
|
|
1194
|
+
" if [[ -n \"${PROMPT_COMMAND:-}\" ]]; then",
|
|
1195
|
+
" PROMPT_COMMAND=\"__prun_sync_history;${PROMPT_COMMAND}\"",
|
|
1196
|
+
" else",
|
|
1197
|
+
" PROMPT_COMMAND=\"__prun_sync_history\"",
|
|
1198
|
+
" fi",
|
|
1199
|
+
"fi"
|
|
1200
|
+
].join("\n");
|
|
1201
|
+
else if (shell === "fish") script = [
|
|
1202
|
+
"function prun",
|
|
1203
|
+
` set -l bin ${bin}`,
|
|
1204
|
+
" set -l cmd (string split -- \" \" $bin)",
|
|
1205
|
+
" command $cmd $argv",
|
|
1206
|
+
" set -l history_disable $CCOMMAND_NO_HISTORY",
|
|
1207
|
+
" if test -z \"$history_disable\"",
|
|
1208
|
+
" set history_disable $NO_HISTORY",
|
|
1209
|
+
" end",
|
|
1210
|
+
" set history_disable (string lower -- (string trim -- \"$history_disable\"))",
|
|
1211
|
+
" if test \"$history_disable\" != \"1\" -a \"$history_disable\" != \"true\" -a \"$history_disable\" != \"yes\"",
|
|
1212
|
+
" history --merge",
|
|
1213
|
+
" set -l history_hint $CCOMMAND_HISTORY_HINT",
|
|
1214
|
+
" if test -z \"$history_hint\"",
|
|
1215
|
+
" set -l cache_home $XDG_CACHE_HOME",
|
|
1216
|
+
" if test -z \"$cache_home\"",
|
|
1217
|
+
" set cache_home \"$HOME/.cache\"",
|
|
1218
|
+
" end",
|
|
1219
|
+
" set history_hint \"$cache_home/ccommand/last-history\"",
|
|
1220
|
+
" end",
|
|
1221
|
+
" if test -f \"$history_hint\"",
|
|
1222
|
+
" set -l last_cmd (string trim -- (cat \"$history_hint\"))",
|
|
1223
|
+
" set -l last_cmd (string replace -r \"^[0-9]+\\t\" \"\" -- \"$last_cmd\")",
|
|
1224
|
+
" if string match -q \"pfind*\" -- \"$last_cmd\"; or string match -q \"prun*\" -- \"$last_cmd\"",
|
|
1225
|
+
" set -l last_hist (history --max=1)",
|
|
1226
|
+
" if test \"$last_hist\" != \"$last_cmd\"",
|
|
1227
|
+
" history add -- \"$last_cmd\"",
|
|
1228
|
+
" end",
|
|
1229
|
+
" end",
|
|
1230
|
+
" end",
|
|
1231
|
+
" end",
|
|
1232
|
+
"end"
|
|
1233
|
+
].join("\n");
|
|
1234
|
+
else if (shell === "powershell" || shell === "pwsh") script = [
|
|
1235
|
+
`$script:__prun_bin = @(${splitCommand(binArg).map(powerShellQuote).join(", ") || powerShellQuote("prun")})`,
|
|
1236
|
+
"",
|
|
1237
|
+
"function global:prun {",
|
|
1238
|
+
" param([Parameter(ValueFromRemainingArguments = $true)] [string[]] $CliArgs)",
|
|
1239
|
+
" $command = $script:__prun_bin[0]",
|
|
1240
|
+
" if ($command -ieq \"prun\") {",
|
|
1241
|
+
" $resolved = Get-Command -Name $command -CommandType Application,ExternalScript -ErrorAction SilentlyContinue | Select-Object -First 1",
|
|
1242
|
+
" if ($null -ne $resolved) {",
|
|
1243
|
+
" if ($resolved.Path) { $command = $resolved.Path }",
|
|
1244
|
+
" elseif ($resolved.Definition) { $command = $resolved.Definition }",
|
|
1245
|
+
" elseif ($resolved.Source) { $command = $resolved.Source }",
|
|
1246
|
+
" }",
|
|
1247
|
+
" }",
|
|
1248
|
+
" $extra = @()",
|
|
1249
|
+
" if ($script:__prun_bin.Count -gt 1) {",
|
|
1250
|
+
" $extra = $script:__prun_bin[1..($script:__prun_bin.Count - 1)]",
|
|
1251
|
+
" }",
|
|
1252
|
+
" & $command @extra @CliArgs",
|
|
1253
|
+
"}",
|
|
1254
|
+
"",
|
|
1255
|
+
"function global:__prun_sync_history {",
|
|
1256
|
+
" $historyDisable = $env:CCOMMAND_NO_HISTORY",
|
|
1257
|
+
" if ([string]::IsNullOrWhiteSpace($historyDisable)) {",
|
|
1258
|
+
" $historyDisable = $env:NO_HISTORY",
|
|
1259
|
+
" }",
|
|
1260
|
+
" $historyDisable = \"$historyDisable\".Trim().ToLowerInvariant()",
|
|
1261
|
+
" if ($historyDisable -eq \"1\" -or $historyDisable -eq \"true\" -or $historyDisable -eq \"yes\") {",
|
|
1262
|
+
" return",
|
|
1263
|
+
" }",
|
|
1264
|
+
" $historyHint = $env:CCOMMAND_HISTORY_HINT",
|
|
1265
|
+
" if ([string]::IsNullOrWhiteSpace($historyHint)) {",
|
|
1266
|
+
" $cacheHome = $env:XDG_CACHE_HOME",
|
|
1267
|
+
" if ([string]::IsNullOrWhiteSpace($cacheHome)) {",
|
|
1268
|
+
" $cacheHome = Join-Path $HOME \".cache\"",
|
|
1269
|
+
" }",
|
|
1270
|
+
" $historyHint = Join-Path (Join-Path $cacheHome \"ccommand\") \"last-history\"",
|
|
1271
|
+
" }",
|
|
1272
|
+
" if (-not (Test-Path -LiteralPath $historyHint)) {",
|
|
1273
|
+
" return",
|
|
1274
|
+
" }",
|
|
1275
|
+
" $line = (Get-Content -LiteralPath $historyHint -Raw -ErrorAction SilentlyContinue)",
|
|
1276
|
+
" if ([string]::IsNullOrWhiteSpace($line)) {",
|
|
1277
|
+
" return",
|
|
1278
|
+
" }",
|
|
1279
|
+
" $line = $line.Trim()",
|
|
1280
|
+
" $hintTs = \"\"",
|
|
1281
|
+
" $hintCmd = $line",
|
|
1282
|
+
" $parts = $line -split \"`t\", 2",
|
|
1283
|
+
" if ($parts.Count -eq 2 -and $parts[0] -match \"^\\d+$\") {",
|
|
1284
|
+
" $hintTs = $parts[0]",
|
|
1285
|
+
" $hintCmd = $parts[1]",
|
|
1286
|
+
" }",
|
|
1287
|
+
" if (-not $hintCmd.StartsWith(\"prun\") -and -not $hintCmd.StartsWith(\"pfind\")) {",
|
|
1288
|
+
" return",
|
|
1289
|
+
" }",
|
|
1290
|
+
" if ($hintTs -and $script:__PRUN_HISTORY_HINT_TS -eq $hintTs) {",
|
|
1291
|
+
" return",
|
|
1292
|
+
" }",
|
|
1293
|
+
" $script:__PRUN_HISTORY_HINT_TS = $hintTs",
|
|
1294
|
+
" $psReadLineType = \"Microsoft.PowerShell.PSConsoleReadLine\" -as [type]",
|
|
1295
|
+
" if ($null -eq $psReadLineType) {",
|
|
1296
|
+
" return",
|
|
1297
|
+
" }",
|
|
1298
|
+
" $psReadLineType::AddToHistory($hintCmd)",
|
|
1299
|
+
"}",
|
|
1300
|
+
"",
|
|
1301
|
+
"if (-not $script:__PRUN_PROMPT_INSTALLED) {",
|
|
1302
|
+
" $script:__PRUN_PROMPT_INSTALLED = $true",
|
|
1303
|
+
" if (-not $script:__prun_original_prompt) {",
|
|
1304
|
+
" if (Test-Path Function:\\prompt) {",
|
|
1305
|
+
" $script:__prun_original_prompt = $function:prompt",
|
|
1306
|
+
" }",
|
|
1307
|
+
" }",
|
|
1308
|
+
" function global:prompt {",
|
|
1309
|
+
" __prun_sync_history",
|
|
1310
|
+
" if ($script:__prun_original_prompt) {",
|
|
1311
|
+
" & $script:__prun_original_prompt",
|
|
1312
|
+
" return",
|
|
1313
|
+
" }",
|
|
1314
|
+
" \"PS $($executionContext.SessionState.Path.CurrentLocation)> \"",
|
|
1315
|
+
" }",
|
|
1316
|
+
"}"
|
|
1317
|
+
].join("\n");
|
|
1318
|
+
else {
|
|
1319
|
+
console.log(color.red(isZh$2 ? `不支持的 shell: ${shell}` : `Unsupported shell: ${shell}`));
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
console.log(script);
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
//#endregion
|
|
1326
|
+
//#region src/pfind.ts
|
|
1327
|
+
function isNoHistory(value) {
|
|
1328
|
+
if (!value) return false;
|
|
1329
|
+
const normalized = value.toLowerCase();
|
|
1330
|
+
return normalized === "1" || normalized === "true" || normalized === "yes";
|
|
1331
|
+
}
|
|
902
1332
|
async function pfind(params) {
|
|
1333
|
+
ensurePrunAutoInit();
|
|
903
1334
|
const hadNoHistoryEnv = process.env.CCOMMAND_NO_HISTORY != null || process.env.NO_HISTORY != null;
|
|
904
1335
|
const initialNoHistory = process.env.CCOMMAND_NO_HISTORY ?? process.env.NO_HISTORY;
|
|
905
|
-
const shouldWriteHistory = !(hadNoHistoryEnv && isNoHistory
|
|
1336
|
+
const shouldWriteHistory = !(hadNoHistoryEnv && isNoHistory(initialNoHistory));
|
|
906
1337
|
const prevNoHistory = process.env.CCOMMAND_NO_HISTORY;
|
|
907
1338
|
if (shouldWriteHistory) delete process.env.CCOMMAND_NO_HISTORY;
|
|
908
1339
|
else process.env.CCOMMAND_NO_HISTORY = "1";
|
|
@@ -1024,117 +1455,6 @@ async function pix(params) {
|
|
|
1024
1455
|
}
|
|
1025
1456
|
}
|
|
1026
1457
|
|
|
1027
|
-
//#endregion
|
|
1028
|
-
//#region src/prun.ts
|
|
1029
|
-
async function prun(params) {
|
|
1030
|
-
ensurePrunAutoInit();
|
|
1031
|
-
const hadNoHistoryEnv = process.env.CCOMMAND_NO_HISTORY != null || process.env.NO_HISTORY != null;
|
|
1032
|
-
const initialNoHistory = process.env.CCOMMAND_NO_HISTORY ?? process.env.NO_HISTORY;
|
|
1033
|
-
const prevNoHistory = process.env.CCOMMAND_NO_HISTORY;
|
|
1034
|
-
if (!(hadNoHistoryEnv && isNoHistory(initialNoHistory))) delete process.env.CCOMMAND_NO_HISTORY;
|
|
1035
|
-
else process.env.CCOMMAND_NO_HISTORY = "1";
|
|
1036
|
-
const { ccommand } = getCcommand();
|
|
1037
|
-
try {
|
|
1038
|
-
await ccommand(params);
|
|
1039
|
-
} finally {
|
|
1040
|
-
if (prevNoHistory == null) delete process.env.CCOMMAND_NO_HISTORY;
|
|
1041
|
-
else process.env.CCOMMAND_NO_HISTORY = prevNoHistory;
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
const isZh$2 = process.env.PI_Lang === "zh";
|
|
1045
|
-
const safeShellValue = /^[\w./:@%+=,-]+$/;
|
|
1046
|
-
function isNoHistory(value) {
|
|
1047
|
-
if (!value) return false;
|
|
1048
|
-
const normalized = value.toLowerCase();
|
|
1049
|
-
return normalized === "1" || normalized === "true" || normalized === "yes";
|
|
1050
|
-
}
|
|
1051
|
-
function shellQuote(value) {
|
|
1052
|
-
if (value === "") return "''";
|
|
1053
|
-
if (safeShellValue.test(value)) return value;
|
|
1054
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
1055
|
-
}
|
|
1056
|
-
function detectShell() {
|
|
1057
|
-
const envShell = process.env.SHELL || "";
|
|
1058
|
-
if (process.env.FISH_VERSION) return "fish";
|
|
1059
|
-
if (process.env.ZSH_VERSION) return "zsh";
|
|
1060
|
-
if (process.env.BASH_VERSION) return "bash";
|
|
1061
|
-
return envShell.split("/").pop() || "zsh";
|
|
1062
|
-
}
|
|
1063
|
-
function ensurePrunAutoInit() {
|
|
1064
|
-
if (!shouldAutoInit()) return;
|
|
1065
|
-
const shell = detectShell();
|
|
1066
|
-
const home = process.env.HOME || os.homedir();
|
|
1067
|
-
let rcFile = "";
|
|
1068
|
-
let initLine = "";
|
|
1069
|
-
if (shell === "zsh") {
|
|
1070
|
-
const zdotdir = process.env.ZDOTDIR || home;
|
|
1071
|
-
rcFile = path.join(zdotdir, ".zshrc");
|
|
1072
|
-
initLine = "eval \"$(prun --init zsh)\"";
|
|
1073
|
-
} else if (shell === "bash") {
|
|
1074
|
-
rcFile = path.join(home, ".bashrc");
|
|
1075
|
-
initLine = "eval \"$(prun --init bash)\"";
|
|
1076
|
-
} else if (shell === "fish") {
|
|
1077
|
-
const configHome = process.env.XDG_CONFIG_HOME || path.join(home, ".config");
|
|
1078
|
-
rcFile = path.join(configHome, "fish", "config.fish");
|
|
1079
|
-
initLine = "prun --init fish | source";
|
|
1080
|
-
} else return;
|
|
1081
|
-
try {
|
|
1082
|
-
const dir = path.dirname(rcFile);
|
|
1083
|
-
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
1084
|
-
const content = fs.existsSync(rcFile) ? fs.readFileSync(rcFile, "utf8") : "";
|
|
1085
|
-
if (!/prun\s+--init/.test(content)) {
|
|
1086
|
-
const prefix = content.length && !content.endsWith("\n") ? "\n" : "";
|
|
1087
|
-
fs.appendFileSync(rcFile, `${prefix}${initLine}\n`, "utf8");
|
|
1088
|
-
}
|
|
1089
|
-
} catch {}
|
|
1090
|
-
}
|
|
1091
|
-
function shouldAutoInit() {
|
|
1092
|
-
const auto = process.env.PI_AUTO_INIT || process.env.PRUN_AUTO_INIT;
|
|
1093
|
-
if (auto != null) return isNoHistory(auto);
|
|
1094
|
-
if (isNoHistory(process.env.PI_NO_AUTO_INIT || process.env.PRUN_NO_AUTO_INIT)) return false;
|
|
1095
|
-
if (process.env.CI) return false;
|
|
1096
|
-
if (!process.stdout.isTTY || !process.stdin.isTTY) return false;
|
|
1097
|
-
return true;
|
|
1098
|
-
}
|
|
1099
|
-
function printPrunInit(args = []) {
|
|
1100
|
-
const shellArg = args[0];
|
|
1101
|
-
const binArg = args[1];
|
|
1102
|
-
const bin = shellQuote(binArg || process.env.PRUN_BIN || "prun");
|
|
1103
|
-
const shell = shellArg || detectShell() || "zsh";
|
|
1104
|
-
let script = "";
|
|
1105
|
-
if (shell === "zsh") script = [
|
|
1106
|
-
"prun() {",
|
|
1107
|
-
` local bin=${bin}`,
|
|
1108
|
-
" local -a cmd",
|
|
1109
|
-
" cmd=(${=bin})",
|
|
1110
|
-
" command \"${cmd[@]}\" \"$@\"",
|
|
1111
|
-
" fc -R",
|
|
1112
|
-
"}"
|
|
1113
|
-
].join("\n");
|
|
1114
|
-
else if (shell === "bash") script = [
|
|
1115
|
-
"prun() {",
|
|
1116
|
-
` local bin=${bin}`,
|
|
1117
|
-
" local -a cmd",
|
|
1118
|
-
" read -r -a cmd <<< \"$bin\"",
|
|
1119
|
-
" command \"${cmd[@]}\" \"$@\"",
|
|
1120
|
-
" history -n",
|
|
1121
|
-
"}"
|
|
1122
|
-
].join("\n");
|
|
1123
|
-
else if (shell === "fish") script = [
|
|
1124
|
-
"function prun",
|
|
1125
|
-
` set -l bin ${bin}`,
|
|
1126
|
-
" set -l cmd (string split -- \" \" $bin)",
|
|
1127
|
-
" command $cmd $argv",
|
|
1128
|
-
" history --merge",
|
|
1129
|
-
"end"
|
|
1130
|
-
].join("\n");
|
|
1131
|
-
else {
|
|
1132
|
-
console.log(color.red(isZh$2 ? `不支持的 shell: ${shell}` : `Unsupported shell: ${shell}`));
|
|
1133
|
-
return;
|
|
1134
|
-
}
|
|
1135
|
-
console.log(script);
|
|
1136
|
-
}
|
|
1137
|
-
|
|
1138
1458
|
//#endregion
|
|
1139
1459
|
//#region src/pu.ts
|
|
1140
1460
|
function pu() {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simon_he/pi",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.10",
|
|
5
5
|
"packageManager": "pnpm@10.29.1",
|
|
6
6
|
"description": "An intelligent cross-platform package manager and CLI tool that autodetects project environments (Node.mjs, Go, Rust, Python) with beautiful loading animations and smart command execution.",
|
|
7
7
|
"author": {
|