ymmv-cli 0.1.5 → 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.md +4 -3
- package/dist/cli.js +108 -47
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
**Share your dev tool-stack from the terminal.**
|
|
4
4
|
|
|
5
|
-
Editor, OS, shell, terminal,
|
|
6
|
-
in about 10 seconds.
|
|
5
|
+
Editor, OS, shell, terminal, browser, font (and more) — published to a clean
|
|
6
|
+
page at `ymmv.fyi/<handle>` in about 10 seconds.
|
|
7
7
|
|
|
8
8
|
```sh
|
|
9
9
|
npx ymmv-cli # detect your stack, confirm, go live at ymmv.fyi/<you>
|
|
@@ -16,7 +16,8 @@ Install once for the short `ymmv` command:
|
|
|
16
16
|
npm i -g ymmv-cli
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
First run includes a one-time GitHub sign-in (the device flow you know from `gh`
|
|
19
|
+
First run includes a one-time GitHub sign-in (the device flow you know from `gh`
|
|
20
|
+
/ `npm login`, ~10s).
|
|
20
21
|
|
|
21
22
|
## Commands
|
|
22
23
|
|
package/dist/cli.js
CHANGED
|
@@ -74,6 +74,101 @@ function isCuratedKey(value) {
|
|
|
74
74
|
return CURATED_KEY_SET.has(value);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
// ../shared/dist/tools.js
|
|
78
|
+
var TOOLS = [
|
|
79
|
+
// ── editor (envTokens mirror EDITOR_NAMES) ────────────────────────────────
|
|
80
|
+
{ key: "editor", canonical: "Neovim", envTokens: ["nvim"], aliases: ["nvim"] },
|
|
81
|
+
{ key: "editor", canonical: "Vim", envTokens: ["vim", "vi"] },
|
|
82
|
+
// `vi` is a detector default only, not a diff alias
|
|
83
|
+
{
|
|
84
|
+
key: "editor",
|
|
85
|
+
canonical: "VS Code",
|
|
86
|
+
envTokens: ["code"],
|
|
87
|
+
// NOT "code": elementary OS ships a distinct editor literally named "Code", so bare "code"
|
|
88
|
+
// is ambiguous as a diff alias (it stays an envToken — detecting $EDITOR=code as VS Code is fine).
|
|
89
|
+
aliases: ["vscode", "vsc", "visual studio code"]
|
|
90
|
+
},
|
|
91
|
+
{ key: "editor", canonical: "VS Code Insiders", envTokens: ["code-insiders"] },
|
|
92
|
+
{ key: "editor", canonical: "VSCodium", envTokens: ["codium"] },
|
|
93
|
+
{ key: "editor", canonical: "Emacs", envTokens: ["emacs"] },
|
|
94
|
+
{ key: "editor", canonical: "Nano", envTokens: ["nano"] },
|
|
95
|
+
{ key: "editor", canonical: "Helix", envTokens: ["hx", "helix"], aliases: ["hx"] },
|
|
96
|
+
{ key: "editor", canonical: "Sublime Text", envTokens: ["subl"], aliases: ["subl", "sublime"] },
|
|
97
|
+
{ key: "editor", canonical: "Micro", envTokens: ["micro"] },
|
|
98
|
+
{ key: "editor", canonical: "IntelliJ IDEA", envTokens: ["idea"], aliases: ["idea", "intellij"] },
|
|
99
|
+
{ key: "editor", canonical: "Zed", envTokens: ["zed"] },
|
|
100
|
+
{ key: "editor", canonical: "Pico", envTokens: ["pico"] },
|
|
101
|
+
// ── shell (envTokens mirror SHELL_NAMES) ──────────────────────────────────
|
|
102
|
+
{ key: "shell", canonical: "zsh", envTokens: ["zsh"] },
|
|
103
|
+
{ key: "shell", canonical: "bash", envTokens: ["bash"] },
|
|
104
|
+
{ key: "shell", canonical: "fish", envTokens: ["fish"] },
|
|
105
|
+
{ key: "shell", canonical: "sh", envTokens: ["sh"] },
|
|
106
|
+
{ key: "shell", canonical: "dash", envTokens: ["dash"] },
|
|
107
|
+
{ key: "shell", canonical: "ksh", envTokens: ["ksh"] },
|
|
108
|
+
{ key: "shell", canonical: "tcsh", envTokens: ["tcsh"] },
|
|
109
|
+
{ key: "shell", canonical: "csh", envTokens: ["csh"] },
|
|
110
|
+
{ key: "shell", canonical: "Nushell", envTokens: ["nu", "nushell"], aliases: ["nu"] },
|
|
111
|
+
{ key: "shell", canonical: "PowerShell", envTokens: ["pwsh", "powershell"], aliases: ["pwsh"] },
|
|
112
|
+
{ key: "shell", canonical: "Elvish", envTokens: ["elvish"] },
|
|
113
|
+
{ key: "shell", canonical: "xonsh", envTokens: ["xonsh"] },
|
|
114
|
+
// ── terminal (envTokens mirror TERM_PROGRAMS) ─────────────────────────────
|
|
115
|
+
{ key: "terminal", canonical: "iTerm2", envTokens: ["iterm.app"], aliases: ["iterm"] },
|
|
116
|
+
{ key: "terminal", canonical: "Terminal", envTokens: ["apple_terminal"] },
|
|
117
|
+
// "terminal" too generic to alias
|
|
118
|
+
{ key: "terminal", canonical: "VS Code", envTokens: ["vscode"] },
|
|
119
|
+
// integrated terminal ($TERM_PROGRAM=vscode)
|
|
120
|
+
{ key: "terminal", canonical: "WezTerm", envTokens: ["wezterm"] },
|
|
121
|
+
{ key: "terminal", canonical: "Ghostty", envTokens: ["ghostty"] },
|
|
122
|
+
{ key: "terminal", canonical: "Hyper", envTokens: ["hyper"] },
|
|
123
|
+
{ key: "terminal", canonical: "Rio", envTokens: ["rio"] },
|
|
124
|
+
{ key: "terminal", canonical: "kitty", envTokens: ["kitty"] },
|
|
125
|
+
{ key: "terminal", canonical: "Tabby", envTokens: ["tabby"] },
|
|
126
|
+
{ key: "terminal", canonical: "Warp", envTokens: ["warpterminal"] },
|
|
127
|
+
// `warpterminal` env id ≠ typed "Warp"
|
|
128
|
+
// ── diff-only synonyms (no detector for these fields) ─────────────────────
|
|
129
|
+
{ key: "browser", canonical: "Firefox", aliases: ["ff"] },
|
|
130
|
+
{ key: "browser", canonical: "Chrome", aliases: ["google chrome"] },
|
|
131
|
+
// NOT Chromium — distinct browser
|
|
132
|
+
{ key: "browser", canonical: "Edge", aliases: ["microsoft edge"] },
|
|
133
|
+
{ key: "os", canonical: "macOS", aliases: ["osx", "os x", "mac"] },
|
|
134
|
+
{ key: "os", canonical: "Windows", aliases: ["win"] },
|
|
135
|
+
{ key: "multiplexer", canonical: "GNU Screen", aliases: ["screen"] }
|
|
136
|
+
// matches detector's "GNU Screen"
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
// ../shared/dist/normalize.js
|
|
140
|
+
var WS = /\s+/g;
|
|
141
|
+
function fold(value) {
|
|
142
|
+
return value.toLowerCase().normalize("NFC").replace(WS, "");
|
|
143
|
+
}
|
|
144
|
+
function buildAliases(tools) {
|
|
145
|
+
const out = {};
|
|
146
|
+
for (const tool of tools) {
|
|
147
|
+
const target = fold(tool.canonical);
|
|
148
|
+
let bucket = out[tool.key];
|
|
149
|
+
if (bucket === void 0) {
|
|
150
|
+
bucket = {};
|
|
151
|
+
out[tool.key] = bucket;
|
|
152
|
+
}
|
|
153
|
+
for (const variant of [tool.canonical, ...tool.aliases ?? []]) {
|
|
154
|
+
const folded = fold(variant);
|
|
155
|
+
if (folded === target)
|
|
156
|
+
continue;
|
|
157
|
+
bucket[folded] = target;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return out;
|
|
161
|
+
}
|
|
162
|
+
var ALIASES = buildAliases(TOOLS);
|
|
163
|
+
var RAW_COMPARE_KEYS = /* @__PURE__ */ new Set(["dotfiles"]);
|
|
164
|
+
function canonical(key, value) {
|
|
165
|
+
if (RAW_COMPARE_KEYS.has(key))
|
|
166
|
+
return value.trim();
|
|
167
|
+
const folded = fold(value);
|
|
168
|
+
const hit = ALIASES[key]?.[folded];
|
|
169
|
+
return typeof hit === "string" ? hit : folded;
|
|
170
|
+
}
|
|
171
|
+
|
|
77
172
|
// ../shared/dist/diff.js
|
|
78
173
|
function toLookup(entries) {
|
|
79
174
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -82,9 +177,9 @@ function toLookup(entries) {
|
|
|
82
177
|
}
|
|
83
178
|
return map;
|
|
84
179
|
}
|
|
85
|
-
function classify(mine, theirs) {
|
|
180
|
+
function classify(key, mine, theirs) {
|
|
86
181
|
if (mine !== null && theirs !== null) {
|
|
87
|
-
return mine
|
|
182
|
+
return canonical(key, mine) === canonical(key, theirs) ? "same" : "changed";
|
|
88
183
|
}
|
|
89
184
|
return mine !== null ? "only_mine" : "only_theirs";
|
|
90
185
|
}
|
|
@@ -100,7 +195,7 @@ function diff(mine, theirs) {
|
|
|
100
195
|
if (mineValue === null && theirsValue === null) {
|
|
101
196
|
continue;
|
|
102
197
|
}
|
|
103
|
-
const status = classify(mineValue, theirsValue);
|
|
198
|
+
const status = classify(key, mineValue, theirsValue);
|
|
104
199
|
if (status === "same") {
|
|
105
200
|
shared += 1;
|
|
106
201
|
} else {
|
|
@@ -429,51 +524,17 @@ function basename(p) {
|
|
|
429
524
|
function firstToken(s) {
|
|
430
525
|
return s.trim().split(/\s+/)[0] ?? "";
|
|
431
526
|
}
|
|
432
|
-
var
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
tcsh: "tcsh",
|
|
440
|
-
csh: "csh",
|
|
441
|
-
nu: "Nushell",
|
|
442
|
-
nushell: "Nushell",
|
|
443
|
-
pwsh: "PowerShell",
|
|
444
|
-
powershell: "PowerShell",
|
|
445
|
-
elvish: "Elvish",
|
|
446
|
-
xonsh: "xonsh"
|
|
447
|
-
};
|
|
448
|
-
var EDITOR_NAMES = {
|
|
449
|
-
nvim: "Neovim",
|
|
450
|
-
vim: "Vim",
|
|
451
|
-
vi: "Vim",
|
|
452
|
-
code: "VS Code",
|
|
453
|
-
"code-insiders": "VS Code Insiders",
|
|
454
|
-
codium: "VSCodium",
|
|
455
|
-
emacs: "Emacs",
|
|
456
|
-
nano: "Nano",
|
|
457
|
-
hx: "Helix",
|
|
458
|
-
helix: "Helix",
|
|
459
|
-
subl: "Sublime Text",
|
|
460
|
-
micro: "Micro",
|
|
461
|
-
idea: "IntelliJ IDEA",
|
|
462
|
-
zed: "Zed",
|
|
463
|
-
pico: "Pico"
|
|
464
|
-
};
|
|
465
|
-
var TERM_PROGRAMS = {
|
|
466
|
-
"iterm.app": "iTerm2",
|
|
467
|
-
apple_terminal: "Terminal",
|
|
468
|
-
vscode: "VS Code",
|
|
469
|
-
wezterm: "WezTerm",
|
|
470
|
-
ghostty: "Ghostty",
|
|
471
|
-
hyper: "Hyper",
|
|
472
|
-
rio: "Rio",
|
|
473
|
-
kitty: "kitty",
|
|
474
|
-
tabby: "Tabby",
|
|
475
|
-
warpterminal: "Warp"
|
|
527
|
+
var namesFor = (key) => {
|
|
528
|
+
const map = {};
|
|
529
|
+
for (const tool of TOOLS) {
|
|
530
|
+
if (tool.key !== key) continue;
|
|
531
|
+
for (const token of tool.envTokens ?? []) map[token] = tool.canonical;
|
|
532
|
+
}
|
|
533
|
+
return map;
|
|
476
534
|
};
|
|
535
|
+
var SHELL_NAMES = namesFor("shell");
|
|
536
|
+
var EDITOR_NAMES = namesFor("editor");
|
|
537
|
+
var TERM_PROGRAMS = namesFor("terminal");
|
|
477
538
|
function detectOS(env, platform) {
|
|
478
539
|
if (env.WSL_DISTRO_NAME) return `${env.WSL_DISTRO_NAME} (WSL)`;
|
|
479
540
|
switch (platform) {
|