@oxecli/oxe 1.0.21 → 1.0.23

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.js CHANGED
@@ -219,12 +219,13 @@ export class CLI {
219
219
  const label = truncateLabel(rec["label"]);
220
220
  const items = rec["input_items"] ?? [];
221
221
  const toks = estimateTokens(items).toLocaleString();
222
- const content = `\x1b[1m${sid.padStart(4)}\x1b[0m` +
223
- `\x1b[2m ${updated}\x1b[0m ${label}` +
224
- `\x1b[2m ${items.length} items · ${toks} tok\x1b[0m`;
222
+ const selectedRow = idx === selected;
223
+ const content = `${selectedRow ? "\x1b[1m\x1b[37m" : "\x1b[1m"}${sid.padStart(4)}\x1b[0m` +
224
+ `${selectedRow ? "\x1b[2m\x1b[36m" : "\x1b[2m"} ${updated}\x1b[0m` +
225
+ `${selectedRow ? "\x1b[37m" : ""} ${label}\x1b[0m` +
226
+ `${selectedRow ? "\x1b[2m\x1b[34m" : "\x1b[2m"} ${items.length} items · ${toks} tok\x1b[0m`;
225
227
  rows.push({
226
- cells: [idx === selected ? "\x1b[1m\x1b[36m❯\x1b[0m" : "", content],
227
- style: idx === selected ? "\x1b[1m" : undefined,
228
+ cells: [selectedRow ? "\x1b[1m\x1b[36m❯\x1b[0m" : "", content],
228
229
  });
229
230
  }
230
231
  const below = total - hi;
package/dist/ui.js CHANGED
@@ -200,9 +200,9 @@ titleAlign = "center") {
200
200
  contentW = Math.max(contentW, 1);
201
201
  let innerW = contentW + 2;
202
202
  if (title)
203
- innerW = Math.max(innerW, title.length + 2);
203
+ innerW = Math.max(innerW, plainLen(title) + 2);
204
204
  if (subtitle)
205
- innerW = Math.max(innerW, subtitle.length + 2);
205
+ innerW = Math.max(innerW, plainLen(subtitle) + 2);
206
206
  const w = terminalWidth();
207
207
  innerW = expand ? Math.max(w - 4, 10) : Math.min(innerW, w - 4);
208
208
  // Build a border run of `innerW` chars with `text` embedded.
@@ -210,7 +210,7 @@ titleAlign = "center") {
210
210
  if (!text)
211
211
  return "─".repeat(innerW);
212
212
  const inner = ` ${text} `;
213
- const fill = Math.max(innerW - inner.length, 0);
213
+ const fill = Math.max(innerW - plainLen(text) - 2, 0);
214
214
  if (align === "left") {
215
215
  return `${inner}${"─".repeat(fill)}`;
216
216
  }
@@ -690,7 +690,7 @@ export function renderBufferWithCursor(buffer, pasteSpans, prefix, label, cursor
690
690
  }
691
691
  const { rows, caretRow, caretCol } = wrapRuns(runs, innerW);
692
692
  // Top border with the label embedded on the left.
693
- const topPad = Math.max(borderW - label.length - 2, 0);
693
+ const topPad = Math.max(borderW - label.length - 3, 0);
694
694
  const top = `\x1b[90m╭─ ${label} ${"─".repeat(topPad)}╮\x1b[0m`;
695
695
  // Body rows.
696
696
  const body = [];
@@ -728,6 +728,8 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
728
728
  const hist = history.slice();
729
729
  let histIdx = hist.length;
730
730
  let draft = null;
731
+ let bracketedPaste = false;
732
+ let bracketedPasteBuffer = "";
731
733
  readline.emitKeypressEvents(process.stdin);
732
734
  if (process.stdin.isTTY) {
733
735
  process.stdin.setRawMode(true);
@@ -974,8 +976,10 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
974
976
  if (!key)
975
977
  return false;
976
978
  // Bare \n / Ctrl+J = newline.
977
- if (key.name === "enter")
979
+ if (key.ctrl && key.name === "j")
978
980
  return true;
981
+ if (key.name === "enter")
982
+ return !!(key.shift || key.ctrl || key.meta);
979
983
  // Enter with a modifier (Shift/Ctrl/Alt/Meta) = newline.
980
984
  if (key.name === "return")
981
985
  return !!(key.shift || key.ctrl || key.meta);
@@ -998,14 +1002,67 @@ export function askBottomPrompt(label = "You", prefix = "❯", history = []) {
998
1002
  const isSubmitEnterKey = (key) => {
999
1003
  if (!key)
1000
1004
  return false;
1001
- if (key.name === "return" && !(key.shift || key.ctrl || key.meta))
1005
+ if ((key.name === "return" || key.name === "enter") && !(key.shift || key.ctrl || key.meta))
1002
1006
  return true;
1003
1007
  const seq = key.sequence || "";
1004
1008
  if (seq === "\x1b[13u" || /^\x1b\[13;1u$/.test(seq))
1005
1009
  return true;
1006
1010
  return false;
1007
1011
  };
1012
+ const consumeBracketedPaste = (str, key) => {
1013
+ const start = "\x1b[200~";
1014
+ const end = "\x1b[201~";
1015
+ const sequence = key?.sequence || "";
1016
+ const value = str || "";
1017
+ if (!bracketedPaste && (sequence === start || value === start)) {
1018
+ bracketedPaste = true;
1019
+ bracketedPasteBuffer = "";
1020
+ const inline = value === start ? "" : value.startsWith(start) ? value.slice(start.length) : "";
1021
+ if (inline)
1022
+ bracketedPasteBuffer = inline;
1023
+ if (inline.includes(end)) {
1024
+ const endAt = inline.indexOf(end);
1025
+ const pasted = inline.slice(0, endAt).replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1026
+ bracketedPaste = false;
1027
+ bracketedPasteBuffer = "";
1028
+ if (pasted)
1029
+ insert(pasted, true);
1030
+ repaint();
1031
+ }
1032
+ return true;
1033
+ }
1034
+ if (!bracketedPaste)
1035
+ return false;
1036
+ if (sequence === end || value === end) {
1037
+ const pasted = bracketedPasteBuffer.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1038
+ bracketedPaste = false;
1039
+ bracketedPasteBuffer = "";
1040
+ if (pasted)
1041
+ insert(pasted, true);
1042
+ repaint();
1043
+ return true;
1044
+ }
1045
+ const chunk = value || (sequence && !sequence.startsWith("\x1b[") ? sequence : "");
1046
+ if (chunk) {
1047
+ const endAt = chunk.indexOf(end);
1048
+ if (endAt >= 0) {
1049
+ bracketedPasteBuffer += chunk.slice(0, endAt);
1050
+ const pasted = bracketedPasteBuffer.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
1051
+ bracketedPaste = false;
1052
+ bracketedPasteBuffer = "";
1053
+ if (pasted)
1054
+ insert(pasted, true);
1055
+ repaint();
1056
+ }
1057
+ else {
1058
+ bracketedPasteBuffer += chunk;
1059
+ }
1060
+ }
1061
+ return true;
1062
+ };
1008
1063
  const onKeypress = (str, key) => {
1064
+ if (consumeBracketedPaste(str, key))
1065
+ return;
1009
1066
  if (key && key.ctrl && key.name === "c") {
1010
1067
  settle(new Error("interrupt"), true);
1011
1068
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxecli/oxe",
3
- "version": "1.0.21",
3
+ "version": "1.0.23",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },