@fadhelhaidar/pi-ask-user 1.0.4 → 1.1.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 CHANGED
@@ -50,14 +50,16 @@ For GitSync and new machines, use the unpinned Pi package source `npm:@fadhelhai
50
50
  - Drafts and checkbox state survive tab changes.
51
51
  - Single-select behavior remains unchanged.
52
52
 
53
- Use arrow keys to move, Tab to switch questions, Enter to choose/toggle, and Esc to cancel. The custom-answer row is appended automatically; models must not author it. Previews are available for single-select questions. Ctrl+] collapses the overlay, Shift+Enter adds a line, and Ctrl+G opens the external editor.
53
+ Use arrow keys to move, Tab to switch questions, Enter to choose/toggle, and Esc to cancel. The custom-answer row is appended automatically; models must not author it. Previews are available for single-select questions. Digits `1`–`9` act on the row with that number, Ctrl+] collapses the dialog, Shift+Enter adds a line, and Ctrl+G opens the external editor. The dialog opens inline in Pi's editor area and takes at most 70% of the terminal height.
54
+
55
+ Inline presentation, digit shortcuts, transcript receipts, `unanswered` reporting for skipped questions and the `rpiv:ask-user:answer` inbound event are ported from upstream. Upstream's Space-to-toggle, automatic custom-text checking and draft-clearing behaviors are deliberately not adopted: this fork keeps Enter-only toggling and explicit custom checkboxes.
54
56
 
55
57
  ## Compatibility and configuration
56
58
 
57
59
  The tool remains named `ask_user_question`. Event names and the localization namespace are preserved for compatibility. Existing configuration remains at `~/.config/rpiv-ask-user-question/config.json`, honoring `XDG_CONFIG_HOME` with legacy fallback.
58
60
 
59
61
  ```json
60
- { "collapseKey": "alt+o" }
62
+ { "collapseKey": "alt+o", "notesKey": "т" }
61
63
  ```
62
64
 
63
65
  The optional `@juicesharp/rpiv-i18n` integration is retained. Without it, the UI uses English. Runtime config helpers are included locally; no rpiv-config dependency is required.
@@ -75,6 +75,8 @@ function readEnvVar(key, fallback) {
75
75
  // config.ts
76
76
  var DEFAULT_COLLAPSE_KEY = "ctrl+]";
77
77
  var COLLAPSE_KEY_OFF = "off";
78
+ var DEFAULT_NOTES_KEY = "n";
79
+ var KEY_PLACEHOLDER = "{key}";
78
80
  var SPECIAL_KEYS = new Set([
79
81
  "escape",
80
82
  "esc",
@@ -119,6 +121,32 @@ function resolveCollapseKey(config) {
119
121
  return COLLAPSE_KEY_OFF;
120
122
  return isValidCollapseKeySpec(raw) ? raw : DEFAULT_COLLAPSE_KEY;
121
123
  }
124
+ var NOTES_KEY_RESERVED = new Set([
125
+ "space",
126
+ "enter",
127
+ "return",
128
+ "tab",
129
+ "escape",
130
+ "esc",
131
+ "up",
132
+ "down",
133
+ "left",
134
+ "right"
135
+ ]);
136
+ function resolveNotesKey(config) {
137
+ const raw = typeof config.notesKey === "string" ? config.notesKey.trim() : "";
138
+ if (!raw)
139
+ return DEFAULT_NOTES_KEY;
140
+ if ([...raw].length === 1)
141
+ return raw;
142
+ const spec = raw.toLowerCase();
143
+ return isValidCollapseKeySpec(spec) && !NOTES_KEY_RESERVED.has(spec) ? spec : DEFAULT_NOTES_KEY;
144
+ }
145
+ function formatNotesKeyForDisplay(notesKey) {
146
+ if (typeof notesKey !== "string" || notesKey.length === 0)
147
+ return formatNotesKeyForDisplay(DEFAULT_NOTES_KEY);
148
+ return [...notesKey].length === 1 ? notesKey : formatKeySpecForDisplay(notesKey);
149
+ }
122
150
  var COMPOUND_KEY_DISPLAY = {
123
151
  pageup: "PageUp",
124
152
  pagedown: "PageDown"
@@ -223,4 +251,52 @@ function formatAnswerScalar(a, _variant) {
223
251
  }
224
252
  }
225
253
 
226
- export { validateGuidanceFields, DEFAULT_COLLAPSE_KEY, COLLAPSE_KEY_OFF, resolveCollapseKey, formatKeySpecForDisplay, loadConfig, ROW_INTENT_META, sentinelsToAppend, I18N_NAMESPACE, t, displayLabel, formatAnswerScalar };
254
+ // view/components/preview/preview-box-renderer.ts
255
+ import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
256
+ var ANSI_SGR_RE = /\x1b\[[0-9;]*m/g;
257
+ var ANSI_OSC8_RE = /\x1b\]8;[^\x07\x1b]*(?:\x07|\x1b\\)/g;
258
+ var FENCE_MARKER_RE = /^`{3}/;
259
+ var BORDER_VERTICAL_OVERHEAD = 2;
260
+ var BORDER_HORIZONTAL_OVERHEAD = 2;
261
+ var BORDER_INNER_PADDING_HORIZONTAL = 1;
262
+ var BOX_MIN_CONTENT_WIDTH = 40;
263
+ function stripFenceMarkers(lines) {
264
+ return lines.filter((line) => {
265
+ const clean = line.replace(ANSI_SGR_RE, "").replace(ANSI_OSC8_RE, "");
266
+ return !FENCE_MARKER_RE.test(clean);
267
+ });
268
+ }
269
+ function renderBorderedBox(lines, width, colorFn, hidden = 0) {
270
+ const dashSpan = Math.max(1, width - BORDER_HORIZONTAL_OVERHEAD);
271
+ const contentInner = Math.max(1, dashSpan - 2 * BORDER_INNER_PADDING_HORIZONTAL);
272
+ const pad = " ".repeat(BORDER_INNER_PADDING_HORIZONTAL);
273
+ const top = colorFn(`┌${"─".repeat(dashSpan)}┐`);
274
+ const out = [top];
275
+ for (const line of lines) {
276
+ const padded = truncateToWidth(line, contentInner, "", true);
277
+ out.push(`${colorFn("│")}${pad}${padded}${pad}${colorFn("│")}`);
278
+ }
279
+ if (hidden > 0) {
280
+ const indicator = ` ✂ ── ${hidden} lines hidden ── `;
281
+ const space = dashSpan - indicator.length;
282
+ const leftFill = "─".repeat(Math.max(0, Math.floor(space / 2)));
283
+ const rightFill = "─".repeat(Math.max(0, dashSpan - leftFill.length - indicator.length));
284
+ out.push(colorFn(`└${leftFill}${indicator}${rightFill}┘`));
285
+ } else {
286
+ out.push(colorFn(`└${"─".repeat(dashSpan)}┘`));
287
+ }
288
+ return out;
289
+ }
290
+ function computeBoxDimensions(contentLines, maxInnerWidth) {
291
+ let widest = Math.min(BOX_MIN_CONTENT_WIDTH, maxInnerWidth);
292
+ for (const line of contentLines) {
293
+ const w = visibleWidth(line.replace(/\s+$/, ""));
294
+ if (w > widest)
295
+ widest = w;
296
+ }
297
+ const innerWidth = Math.min(widest, maxInnerWidth);
298
+ const boxWidth = innerWidth + BORDER_HORIZONTAL_OVERHEAD + 2 * BORDER_INNER_PADDING_HORIZONTAL;
299
+ return { innerWidth, boxWidth };
300
+ }
301
+
302
+ export { validateGuidanceFields, DEFAULT_COLLAPSE_KEY, COLLAPSE_KEY_OFF, DEFAULT_NOTES_KEY, KEY_PLACEHOLDER, resolveCollapseKey, resolveNotesKey, formatNotesKeyForDisplay, formatKeySpecForDisplay, loadConfig, ROW_INTENT_META, sentinelsToAppend, I18N_NAMESPACE, t, displayLabel, NO_INPUT_PLACEHOLDER, formatAnswerScalar, BORDER_VERTICAL_OVERHEAD, BORDER_HORIZONTAL_OVERHEAD, BORDER_INNER_PADDING_HORIZONTAL, stripFenceMarkers, renderBorderedBox, computeBoxDimensions };
@@ -0,0 +1,7 @@
1
+ // events.ts
2
+ var ASK_USER_PROMPT_EVENT2 = "rpiv:ask-user:prompt";
3
+ var ASK_USER_BLOCKED_EVENT2 = "rpiv:ask-user:blocked";
4
+ var ASK_USER_ANSWER_EVENT2 = "rpiv:ask-user:answer";
5
+ var ASK_USER_ANSWER_RESULT_EVENT2 = "rpiv:ask-user:answer-result";
6
+
7
+ export { ASK_USER_PROMPT_EVENT2, ASK_USER_BLOCKED_EVENT2, ASK_USER_ANSWER_EVENT2, ASK_USER_ANSWER_RESULT_EVENT2 };