@kaynooo/cli-doctor 0.10.0 → 0.11.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/dist/cli-bin.js CHANGED
@@ -481,7 +481,6 @@ var DASHES = /^-+/;
481
481
  function jsonOption(holds) {
482
482
  return { type: "boolean", description: holds === undefined ? "print JSON" : `print JSON: ${holds}` };
483
483
  }
484
-
485
484
  class Exit extends Error {
486
485
  code;
487
486
  hint;
@@ -1582,9 +1581,20 @@ var KEY_SEQUENCES = /\x1B\[[0-9;]*[A-Z~]|\x1BO[A-Z]|[\s\S]/giu;
1582
1581
  var CONTROL = /^[\x00-\x1F\x7F]/;
1583
1582
  var WORDS = /\s+/;
1584
1583
  var MAX_ROWS = 10;
1585
- var KEYS = { "\x1B[A": "up", "\x1BOA": "up", "\x1B[B": "down", "\x1BOB": "down", "\r": "enter", "\n": "enter", "\x03": "cancel", "\x1B": "cancel", "\x7F": "erase", "\b": "erase" };
1586
- function readKeys(input) {
1587
- return (input.match(KEY_SEQUENCES) ?? []).flatMap((sequence) => KEYS[sequence] ?? (CONTROL.test(sequence) ? [] : [{ text: sequence }]));
1584
+ var PASTE_START = "\x1B[200~";
1585
+ var PASTE_END = "\x1B[201~";
1586
+ var KEYS = { "\x1B[A": "up", "\x1BOA": "up", "\x1B[B": "down", "\x1BOB": "down", "\x1B[5~": "pageup", "\x1B[6~": "pagedown", "\x1B[H": "home", "\x1B[1~": "home", "\x1BOH": "home", "\x1B[F": "end", "\x1B[4~": "end", "\x1BOF": "end", "\r": "enter", "\n": "enter", "\x03": "cancel", "\x1B": "cancel", "\x7F": "erase", "\b": "erase" };
1587
+ function readKeys(input, paste = { active: false }) {
1588
+ return (input.match(KEY_SEQUENCES) ?? []).flatMap((sequence) => {
1589
+ if (sequence === PASTE_START || sequence === PASTE_END) {
1590
+ paste.active = sequence === PASTE_START;
1591
+ return [];
1592
+ }
1593
+ if (paste.active && (sequence === "\r" || sequence === `
1594
+ `))
1595
+ return [];
1596
+ return KEYS[sequence] ?? (CONTROL.test(sequence) ? [] : [{ text: sequence }]);
1597
+ });
1588
1598
  }
1589
1599
  function flip(checked, value) {
1590
1600
  const next = new Set(checked);
@@ -1683,6 +1693,12 @@ class List {
1683
1693
  this.cursor = (this.cursor + (key === "up" ? this.matches.length - 1 : 1)) % this.matches.length;
1684
1694
  return;
1685
1695
  }
1696
+ if (key === "home" || key === "end" || key === "pageup" || key === "pagedown") {
1697
+ const last = this.matches.length - 1;
1698
+ const to = { home: 0, end: last, pageup: this.cursor - MAX_ROWS, pagedown: this.cursor + MAX_ROWS }[key];
1699
+ this.cursor = Math.max(0, Math.min(last, to));
1700
+ return;
1701
+ }
1686
1702
  if (key === "erase")
1687
1703
  this.filter([...this.query].slice(0, -1).join(""));
1688
1704
  else if (typeof key === "object")
@@ -1724,22 +1740,29 @@ async function ask(question, { hint, terminal = process15 }, render, press) {
1724
1740
  if (!isInteractive(terminal))
1725
1741
  fail(`cannot ask "${question}" off a terminal`, 2, hint);
1726
1742
  const colors = paint(stderr);
1727
- let drawn = 0;
1743
+ let drawn = [];
1744
+ let current = "asking";
1728
1745
  let outcome;
1746
+ const columns = () => stderr.columns || 80;
1729
1747
  const draw = (state) => {
1730
- const frame = render(colors, state, { columns: stderr.columns || 80, rows: stderr.rows || 24 });
1731
- stderr.write(`${drawn > 1 ? `\x1B[${drawn - 1}A` : ""}\r\x1B[0J${frame.join(`
1748
+ const frame = render(colors, state, { columns: columns(), rows: stderr.rows || 24 });
1749
+ const rows = drawn.reduce((sum, line) => sum + Math.max(1, Math.ceil(Bun.stringWidth(line) / columns())), 0);
1750
+ stderr.write(`${rows > 1 ? `\x1B[${rows - 1}A` : ""}\r\x1B[0J${frame.join(`
1732
1751
  `)}`);
1733
- drawn = frame.length;
1752
+ drawn = frame;
1753
+ current = state;
1734
1754
  };
1755
+ const redraw = () => draw(current);
1756
+ const paste = { active: false };
1735
1757
  try {
1758
+ stderr.on?.("resize", redraw);
1736
1759
  stdin.setRawMode(true);
1737
1760
  stdin.resume();
1738
- stderr.write("\x1B[?25l");
1761
+ stderr.write("\x1B[?25l\x1B[?2004h");
1739
1762
  draw("asking");
1740
1763
  return await new Promise((resolve) => {
1741
1764
  function onData(data) {
1742
- for (const key of readKeys(data.toString())) {
1765
+ for (const key of readKeys(data.toString(), paste)) {
1743
1766
  const pressed = press(key);
1744
1767
  if (pressed !== undefined) {
1745
1768
  settle(pressed);
@@ -1761,9 +1784,10 @@ async function ask(question, { hint, terminal = process15 }, render, press) {
1761
1784
  stdin.on("end", onEnd);
1762
1785
  });
1763
1786
  } finally {
1787
+ stderr.off?.("resize", redraw);
1764
1788
  draw(outcome ?? "cancel");
1765
1789
  stderr.write(`
1766
- \x1B[?25h`);
1790
+ \x1B[?25h\x1B[?2004l`);
1767
1791
  stdin.setRawMode(false);
1768
1792
  stdin.pause();
1769
1793
  }
@@ -1854,7 +1878,7 @@ async function install(host, options, recheck, choosing = ask2) {
1854
1878
  console.log("everything is installed");
1855
1879
  return 0;
1856
1880
  }
1857
- if (pool.length === 0 && options.names.length > 0) {
1881
+ if (pool.length === 0 && (options.names.length > 0 || !isInteractive())) {
1858
1882
  console.log("everything is installed");
1859
1883
  return 0;
1860
1884
  }
@@ -1917,10 +1941,14 @@ async function install(host, options, recheck, choosing = ask2) {
1917
1941
  return 1;
1918
1942
  }
1919
1943
  }
1920
- if (removing.plugin && host.which("claude") !== null) {
1944
+ if (removing.plugin && host.which("claude") === null) {
1945
+ console.error(`${yellow("not run")} ${PLUGIN_UNINSTALL.join(" ")}: claude is not on PATH`);
1946
+ } else if (removing.plugin) {
1921
1947
  const ran = await host.run(PLUGIN_UNINSTALL);
1922
- if (ran.code !== 0)
1948
+ if (ran.code !== 0) {
1923
1949
  console.error(`${red("failed")} ${PLUGIN_UNINSTALL.join(" ")}: exit ${ran.code}: ${firstLine(ran.stderr || ran.stdout)}`);
1950
+ return 1;
1951
+ }
1924
1952
  }
1925
1953
  console.log(`
1926
1954
  after the install:`);
package/dist/cli.js CHANGED
@@ -481,7 +481,6 @@ var DASHES = /^-+/;
481
481
  function jsonOption(holds) {
482
482
  return { type: "boolean", description: holds === undefined ? "print JSON" : `print JSON: ${holds}` };
483
483
  }
484
-
485
484
  class Exit extends Error {
486
485
  code;
487
486
  hint;
@@ -1580,9 +1579,20 @@ var KEY_SEQUENCES = /\x1B\[[0-9;]*[A-Z~]|\x1BO[A-Z]|[\s\S]/giu;
1580
1579
  var CONTROL = /^[\x00-\x1F\x7F]/;
1581
1580
  var WORDS = /\s+/;
1582
1581
  var MAX_ROWS = 10;
1583
- var KEYS = { "\x1B[A": "up", "\x1BOA": "up", "\x1B[B": "down", "\x1BOB": "down", "\r": "enter", "\n": "enter", "\x03": "cancel", "\x1B": "cancel", "\x7F": "erase", "\b": "erase" };
1584
- function readKeys(input) {
1585
- return (input.match(KEY_SEQUENCES) ?? []).flatMap((sequence) => KEYS[sequence] ?? (CONTROL.test(sequence) ? [] : [{ text: sequence }]));
1582
+ var PASTE_START = "\x1B[200~";
1583
+ var PASTE_END = "\x1B[201~";
1584
+ var KEYS = { "\x1B[A": "up", "\x1BOA": "up", "\x1B[B": "down", "\x1BOB": "down", "\x1B[5~": "pageup", "\x1B[6~": "pagedown", "\x1B[H": "home", "\x1B[1~": "home", "\x1BOH": "home", "\x1B[F": "end", "\x1B[4~": "end", "\x1BOF": "end", "\r": "enter", "\n": "enter", "\x03": "cancel", "\x1B": "cancel", "\x7F": "erase", "\b": "erase" };
1585
+ function readKeys(input, paste = { active: false }) {
1586
+ return (input.match(KEY_SEQUENCES) ?? []).flatMap((sequence) => {
1587
+ if (sequence === PASTE_START || sequence === PASTE_END) {
1588
+ paste.active = sequence === PASTE_START;
1589
+ return [];
1590
+ }
1591
+ if (paste.active && (sequence === "\r" || sequence === `
1592
+ `))
1593
+ return [];
1594
+ return KEYS[sequence] ?? (CONTROL.test(sequence) ? [] : [{ text: sequence }]);
1595
+ });
1586
1596
  }
1587
1597
  function flip(checked, value) {
1588
1598
  const next = new Set(checked);
@@ -1681,6 +1691,12 @@ class List {
1681
1691
  this.cursor = (this.cursor + (key === "up" ? this.matches.length - 1 : 1)) % this.matches.length;
1682
1692
  return;
1683
1693
  }
1694
+ if (key === "home" || key === "end" || key === "pageup" || key === "pagedown") {
1695
+ const last = this.matches.length - 1;
1696
+ const to = { home: 0, end: last, pageup: this.cursor - MAX_ROWS, pagedown: this.cursor + MAX_ROWS }[key];
1697
+ this.cursor = Math.max(0, Math.min(last, to));
1698
+ return;
1699
+ }
1684
1700
  if (key === "erase")
1685
1701
  this.filter([...this.query].slice(0, -1).join(""));
1686
1702
  else if (typeof key === "object")
@@ -1722,22 +1738,29 @@ async function ask(question, { hint, terminal = process15 }, render, press) {
1722
1738
  if (!isInteractive(terminal))
1723
1739
  fail(`cannot ask "${question}" off a terminal`, 2, hint);
1724
1740
  const colors = paint(stderr);
1725
- let drawn = 0;
1741
+ let drawn = [];
1742
+ let current = "asking";
1726
1743
  let outcome;
1744
+ const columns = () => stderr.columns || 80;
1727
1745
  const draw = (state) => {
1728
- const frame = render(colors, state, { columns: stderr.columns || 80, rows: stderr.rows || 24 });
1729
- stderr.write(`${drawn > 1 ? `\x1B[${drawn - 1}A` : ""}\r\x1B[0J${frame.join(`
1746
+ const frame = render(colors, state, { columns: columns(), rows: stderr.rows || 24 });
1747
+ const rows = drawn.reduce((sum, line) => sum + Math.max(1, Math.ceil(Bun.stringWidth(line) / columns())), 0);
1748
+ stderr.write(`${rows > 1 ? `\x1B[${rows - 1}A` : ""}\r\x1B[0J${frame.join(`
1730
1749
  `)}`);
1731
- drawn = frame.length;
1750
+ drawn = frame;
1751
+ current = state;
1732
1752
  };
1753
+ const redraw = () => draw(current);
1754
+ const paste = { active: false };
1733
1755
  try {
1756
+ stderr.on?.("resize", redraw);
1734
1757
  stdin.setRawMode(true);
1735
1758
  stdin.resume();
1736
- stderr.write("\x1B[?25l");
1759
+ stderr.write("\x1B[?25l\x1B[?2004h");
1737
1760
  draw("asking");
1738
1761
  return await new Promise((resolve) => {
1739
1762
  function onData(data) {
1740
- for (const key of readKeys(data.toString())) {
1763
+ for (const key of readKeys(data.toString(), paste)) {
1741
1764
  const pressed = press(key);
1742
1765
  if (pressed !== undefined) {
1743
1766
  settle(pressed);
@@ -1759,9 +1782,10 @@ async function ask(question, { hint, terminal = process15 }, render, press) {
1759
1782
  stdin.on("end", onEnd);
1760
1783
  });
1761
1784
  } finally {
1785
+ stderr.off?.("resize", redraw);
1762
1786
  draw(outcome ?? "cancel");
1763
1787
  stderr.write(`
1764
- \x1B[?25h`);
1788
+ \x1B[?25h\x1B[?2004l`);
1765
1789
  stdin.setRawMode(false);
1766
1790
  stdin.pause();
1767
1791
  }
@@ -1852,7 +1876,7 @@ async function install(host, options, recheck, choosing = ask2) {
1852
1876
  console.log("everything is installed");
1853
1877
  return 0;
1854
1878
  }
1855
- if (pool.length === 0 && options.names.length > 0) {
1879
+ if (pool.length === 0 && (options.names.length > 0 || !isInteractive())) {
1856
1880
  console.log("everything is installed");
1857
1881
  return 0;
1858
1882
  }
@@ -1915,10 +1939,14 @@ async function install(host, options, recheck, choosing = ask2) {
1915
1939
  return 1;
1916
1940
  }
1917
1941
  }
1918
- if (removing.plugin && host.which("claude") !== null) {
1942
+ if (removing.plugin && host.which("claude") === null) {
1943
+ console.error(`${yellow("not run")} ${PLUGIN_UNINSTALL.join(" ")}: claude is not on PATH`);
1944
+ } else if (removing.plugin) {
1919
1945
  const ran = await host.run(PLUGIN_UNINSTALL);
1920
- if (ran.code !== 0)
1946
+ if (ran.code !== 0) {
1921
1947
  console.error(`${red("failed")} ${PLUGIN_UNINSTALL.join(" ")}: exit ${ran.code}: ${firstLine(ran.stderr || ran.stdout)}`);
1948
+ return 1;
1949
+ }
1922
1950
  }
1923
1951
  console.log(`
1924
1952
  after the install:`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kaynooo/cli-doctor",
3
3
  "type": "module",
4
- "version": "0.10.0",
4
+ "version": "0.11.0",
5
5
  "description": "doctor: checks the @kaynooo/cli-* install of a host: each bin's version against the registry, tea's login to Forgejo, the Claude Code hooks and the Bun floor; cli list: every bin in one line, read from its own help.",
6
6
  "author": "Kaynooo <contact@kaynooo.fr>",
7
7
  "license": "MIT",
@@ -37,6 +37,6 @@
37
37
  "doctor": "$npm_execpath src/cli.ts"
38
38
  },
39
39
  "devDependencies": {
40
- "@kaynooo/cli-kit": "0.23.0"
40
+ "@kaynooo/cli-kit": "0.24.0"
41
41
  }
42
42
  }