ymmv-cli 0.11.2 → 0.11.3

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.
Files changed (3) hide show
  1. package/README.md +2 -1
  2. package/dist/cli.js +68 -11
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -46,7 +46,8 @@ via npm Trusted Publishing, with provenance.
46
46
 
47
47
  ## Commands
48
48
 
49
- - `ymmv` detects, confirms, and publishes (re-run any time to update; `ymmv publish` is the same command)
49
+ - `ymmv` detects, confirms, and publishes (re-run any time to update: the preview marks values
50
+ your environment now detects differently and `d` takes them; `ymmv publish` is the same command)
50
51
  - `ymmv <handle>` views a profile, or diffs it against yours when you're logged in
51
52
  - `ymmv set editor Neovim` changes one value
52
53
  - `ymmv set --extra "Keyboard=HHKB"` adds a free-form line of your own (`-e` works too)
package/dist/cli.js CHANGED
@@ -431,6 +431,9 @@ var BIDI_RE = new RegExp("\\p{Bidi_Control}", "gu");
431
431
  function sanitizeValue(value) {
432
432
  return value.replace(ANSI_RE, "").replace(CTRL_RE, "").replace(BIDI_RE, "");
433
433
  }
434
+ function shownValue(value) {
435
+ return sanitizeValue(value).trim();
436
+ }
434
437
  function showsVisibleText(value) {
435
438
  return hasVisibleContent(sanitizeValue(value));
436
439
  }
@@ -482,7 +485,13 @@ function renderProfile(profile, opts) {
482
485
  const rows = CURATED_KEYS.flatMap((key) => {
483
486
  const value = byKey.get(key);
484
487
  if (value === void 0 && !preview) return [];
485
- return [{ label: KEY_LABELS[key], value: value === void 0 ? null : sanitizeValue(value) }];
488
+ return [
489
+ {
490
+ label: KEY_LABELS[key],
491
+ value: value === void 0 ? null : sanitizeValue(value),
492
+ note: preview && value !== void 0 ? opts.disagreements?.get(key) : void 0
493
+ }
494
+ ];
486
495
  });
487
496
  const extras = (profile.extras ?? []).map((x) => ({
488
497
  label: sanitizeValue(x.label),
@@ -501,9 +510,12 @@ function renderProfile(profile, opts) {
501
510
  if (rows.length) {
502
511
  lines.push("");
503
512
  for (const r of rows) {
504
- lines.push(
505
- r.value === null ? ` ${c.faint}${r.label.padEnd(labelW)} ${MISSING}${c.reset}` : ` ${c.faint}${r.label.padEnd(labelW)}${c.reset} ${val(r.value)}`
506
- );
513
+ if (r.value === null) {
514
+ lines.push(` ${c.faint}${r.label.padEnd(labelW)} ${MISSING}${c.reset}`);
515
+ continue;
516
+ }
517
+ const note = r.note ? ` ${c.faint}(detected: ${sanitizeValue(r.note)})${c.reset}` : "";
518
+ lines.push(` ${c.faint}${r.label.padEnd(labelW)}${c.reset} ${val(r.value)}${note}`);
507
519
  }
508
520
  }
509
521
  if (extras.length) {
@@ -1554,6 +1566,17 @@ function buildDefaults(existing, detected) {
1554
1566
  }
1555
1567
  return out;
1556
1568
  }
1569
+ function detectionDisagreements(values, detected, decided = /* @__PURE__ */ new Set()) {
1570
+ const out = /* @__PURE__ */ new Map();
1571
+ for (const key of CURATED_KEYS) {
1572
+ const current = values.get(key);
1573
+ const fresh = detected.get(key);
1574
+ if (current === void 0 || fresh === void 0 || decided.has(key)) continue;
1575
+ const take = shownValue(fresh);
1576
+ if (take && canonical(key, shownValue(current)) !== canonical(key, take)) out.set(key, take);
1577
+ }
1578
+ return out;
1579
+ }
1557
1580
  function entriesFromMap(map) {
1558
1581
  return CURATED_KEYS.flatMap((key) => {
1559
1582
  const value = map.get(key);
@@ -1760,7 +1783,7 @@ async function promptEntries(defaults, saved, prompter) {
1760
1783
  const answer = (await prompter.ask(KEY_LABELS[key], defaults.get(key))).trim();
1761
1784
  const value = answer === "-" ? "" : answer;
1762
1785
  const rawDefault = defaults.get(key) ?? "";
1763
- const isDefault = value === sanitizeValue(rawDefault).trim();
1786
+ const isDefault = value === shownValue(rawDefault);
1764
1787
  const emptiedDefault = answer === "" && rawDefault !== "";
1765
1788
  const problem = emptiedDefault ? "invisible" : value === "" ? void 0 : valueProblem(value);
1766
1789
  if (problem !== void 0) {
@@ -1803,9 +1826,16 @@ async function publish(io) {
1803
1826
  let ifMatch = own?.etag;
1804
1827
  const color = colorEnabled();
1805
1828
  const site = displayUrl(BASE);
1806
- const showCard = (entries) => {
1829
+ let cardShown = false;
1830
+ const showCard = (entries, disagreements) => {
1831
+ cardShown = true;
1807
1832
  console.log(
1808
- renderProfile(newProfile(handle, entries, extras), { color, site, mode: "preview" })
1833
+ renderProfile(newProfile(handle, entries, extras), {
1834
+ color,
1835
+ site,
1836
+ mode: "preview",
1837
+ disagreements
1838
+ })
1809
1839
  );
1810
1840
  const notes = [];
1811
1841
  if (carried.length > 0) {
@@ -1829,14 +1859,29 @@ async function publish(io) {
1829
1859
  let values = defaults;
1830
1860
  const assemble = () => [...entriesFromMap(values), ...carried];
1831
1861
  const edits = /* @__PURE__ */ new Map();
1862
+ const kept = /* @__PURE__ */ new Map();
1832
1863
  let saved = savedKeys(existing);
1864
+ const disagreeing = () => {
1865
+ const out = detectionDisagreements(
1866
+ values,
1867
+ detected,
1868
+ /* @__PURE__ */ new Set([...edits.keys(), ...kept.keys()])
1869
+ );
1870
+ for (const [key, value] of out) if (valueProblem(value) !== void 0) out.delete(key);
1871
+ return out;
1872
+ };
1833
1873
  const prompt = async (prompter) => {
1834
1874
  const before = values;
1875
+ const marked = cardShown ? disagreeing() : /* @__PURE__ */ new Map();
1835
1876
  values = await promptEntries(values, saved, prompter);
1836
1877
  for (const key of CURATED_KEYS) {
1837
1878
  const after = values.get(key);
1838
1879
  if (after !== before.get(key)) edits.set(key, after);
1839
1880
  }
1881
+ for (const key of marked.keys()) {
1882
+ const value = values.get(key);
1883
+ if (!edits.has(key) && value !== void 0) kept.set(key, value);
1884
+ }
1840
1885
  };
1841
1886
  if (!io.interactive || !io.prompter || io.yes) {
1842
1887
  const entries = assemble();
@@ -1846,7 +1891,7 @@ async function publish(io) {
1846
1891
  process.exitCode = 1;
1847
1892
  return;
1848
1893
  }
1849
- showCard(entries);
1894
+ showCard(entries, /* @__PURE__ */ new Map());
1850
1895
  printPublished(
1851
1896
  await publishProfile(newProfile(handle, entries, extras), cred, { ifMatch }),
1852
1897
  color
@@ -1859,12 +1904,14 @@ async function publish(io) {
1859
1904
  for (; ; ) {
1860
1905
  if ([...values].some(failsRule)) await prompt(io.prompter);
1861
1906
  const entries = assemble();
1862
- showCard(entries);
1907
+ const disagreements = disagreeing();
1908
+ showCard(entries, disagreements);
1909
+ const offerD = disagreements.size > 0;
1863
1910
  const ans = await io.prompter.choice(
1864
1911
  `Publish to ${site}/${sanitizeValue(handle)}?`,
1865
- ["y", "n", "e"],
1912
+ offerD ? ["y", "n", "e", "d"] : ["y", "n", "e"],
1866
1913
  "y",
1867
- "Y/n/e=edit"
1914
+ offerD ? "Y/n/e=edit/d=detected" : "Y/n/e=edit"
1868
1915
  );
1869
1916
  if (ans === "y") {
1870
1917
  try {
@@ -1894,6 +1941,8 @@ async function publish(io) {
1894
1941
  else rebased.set(key, value);
1895
1942
  }
1896
1943
  values = rebased;
1944
+ for (const [key, value] of kept) if (rebased.get(key) !== value) kept.delete(key);
1945
+ cardShown = false;
1897
1946
  saved = savedKeys(fresh.profile);
1898
1947
  carried = unknownEntries(fresh.profile);
1899
1948
  extras = fresh.profile.extras;
@@ -1915,6 +1964,14 @@ ${ambiguous ? "The publish may not have completed. Your answers are kept." : "No
1915
1964
  console.log(message("Aborted. Nothing published."));
1916
1965
  return;
1917
1966
  }
1967
+ if (ans === "d") {
1968
+ values = new Map(values);
1969
+ for (const [key, value] of disagreements) {
1970
+ values.set(key, value);
1971
+ edits.set(key, value);
1972
+ }
1973
+ continue;
1974
+ }
1918
1975
  await prompt(io.prompter);
1919
1976
  }
1920
1977
  } catch (e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ymmv-cli",
3
- "version": "0.11.2",
3
+ "version": "0.11.3",
4
4
  "description": "Publish and diff terminal-native developer tool-stack profiles at ymmv.fyi.",
5
5
  "type": "module",
6
6
  "bin": {