pi-ask-tool-extension 0.2.5 → 0.2.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ask-tool-extension",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "Ask tool extension for pi with tabbed questioning and inline note editing",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,4 +1,4 @@
1
- import { wrapTextWithAnsi } from "@mariozechner/pi-tui";
1
+ import { CURSOR_MARKER, wrapTextWithAnsi } from "@mariozechner/pi-tui";
2
2
 
3
3
  const INLINE_NOTE_SEPARATOR = " — note: ";
4
4
  const INLINE_EDIT_CURSOR_INVERT_ON = "\u001b[7m";
@@ -17,14 +17,19 @@ function clampCursorIndex(index: number, rawTextLength: number): number {
17
17
  return Math.floor(index);
18
18
  }
19
19
 
20
- function buildEditingInlineNote(rawNote: string, editingCursorIndex?: number): string {
20
+ function buildEditingInlineNote(
21
+ rawNote: string,
22
+ editingCursorIndex?: number,
23
+ includeHardwareCursorMarker = false,
24
+ ): string {
21
25
  const cursorIndex = clampCursorIndex(editingCursorIndex ?? rawNote.length, rawNote.length);
22
26
  const beforeCursor = sanitizeNoteForInlineDisplay(rawNote.slice(0, cursorIndex));
23
27
  const rawCharAtCursor = rawNote.slice(cursorIndex, cursorIndex + 1);
24
28
  const charAtCursor = sanitizeNoteForInlineDisplay(rawCharAtCursor) || " ";
25
29
  const afterCursorStartIndex = rawCharAtCursor.length > 0 ? cursorIndex + 1 : cursorIndex;
26
30
  const afterCursor = sanitizeNoteForInlineDisplay(rawNote.slice(afterCursorStartIndex));
27
- const cursorCell = `${INLINE_EDIT_CURSOR_INVERT_ON}${charAtCursor}${INLINE_EDIT_CURSOR_INVERT_OFF}`;
31
+ const cursorMarker = includeHardwareCursorMarker ? CURSOR_MARKER : "";
32
+ const cursorCell = `${cursorMarker}${INLINE_EDIT_CURSOR_INVERT_ON}${charAtCursor}${INLINE_EDIT_CURSOR_INVERT_OFF}`;
28
33
  return `${beforeCursor}${cursorCell}${afterCursor}`;
29
34
  }
30
35
 
@@ -48,6 +53,7 @@ export function buildOptionLabelWithInlineNote(
48
53
  isEditingNote: boolean,
49
54
  maxInlineLabelLength?: number,
50
55
  editingCursorIndex?: number,
56
+ includeHardwareCursorMarker = false,
51
57
  ): string {
52
58
  const sanitizedNote = sanitizeNoteForInlineDisplay(rawNote);
53
59
  if (!isEditingNote && sanitizedNote.trim().length === 0) {
@@ -55,7 +61,9 @@ export function buildOptionLabelWithInlineNote(
55
61
  }
56
62
 
57
63
  const labelPrefix = `${baseOptionLabel}${INLINE_NOTE_SEPARATOR}`;
58
- const inlineNote = isEditingNote ? buildEditingInlineNote(rawNote, editingCursorIndex) : sanitizedNote.trim();
64
+ const inlineNote = isEditingNote
65
+ ? buildEditingInlineNote(rawNote, editingCursorIndex, includeHardwareCursorMarker)
66
+ : sanitizedNote.trim();
59
67
  const inlineLabel = `${labelPrefix}${inlineNote}`;
60
68
 
61
69
  if (maxInlineLabelLength == null) {
@@ -74,6 +82,7 @@ export function buildWrappedOptionLabelWithInlineNote(
74
82
  maxInlineLabelLength: number,
75
83
  wrapPadding = INLINE_NOTE_WRAP_PADDING,
76
84
  editingCursorIndex?: number,
85
+ includeHardwareCursorMarker = false,
77
86
  ): string[] {
78
87
  const inlineLabel = buildOptionLabelWithInlineNote(
79
88
  baseOptionLabel,
@@ -81,6 +90,7 @@ export function buildWrappedOptionLabelWithInlineNote(
81
90
  isEditingNote,
82
91
  undefined,
83
92
  editingCursorIndex,
93
+ includeHardwareCursorMarker,
84
94
  );
85
95
  const sanitizedWrapPadding = Number.isFinite(wrapPadding) ? Math.max(0, Math.floor(wrapPadding)) : 0;
86
96
  const sanitizedMaxInlineLabelLength = Number.isFinite(maxInlineLabelLength)
@@ -187,6 +187,7 @@ export async function askSingleQuestionWithInlineNote(
187
187
  Math.max(1, width - prefixWidth),
188
188
  INLINE_NOTE_WRAP_PADDING,
189
189
  isEditingThisOption ? activeEditingCursorIndex : undefined,
190
+ isEditingThisOption,
190
191
  );
191
192
  const continuationPrefix = " ".repeat(prefixWidth);
192
193
  addLine(`${cursorPrefix}${theme.fg(optionColor, `${markerText}${wrappedInlineLabelLines[0] ?? ""}`)}`);
@@ -288,6 +289,7 @@ export async function askSingleQuestionWithInlineNote(
288
289
  };
289
290
 
290
291
  return {
292
+ focused: true,
291
293
  render,
292
294
  invalidate: () => {
293
295
  cachedRenderedLines = undefined;
@@ -388,6 +388,7 @@ export async function askQuestionsWithTabs(
388
388
  Math.max(1, width - prefixWidth),
389
389
  INLINE_NOTE_WRAP_PADDING,
390
390
  isEditingThisOption ? activeEditingCursorIndex : undefined,
391
+ isEditingThisOption,
391
392
  );
392
393
  const continuationPrefix = " ".repeat(prefixWidth);
393
394
  addLine(`${cursorPrefix}${theme.fg(optionColor, `${markerText}${wrappedInlineLabelLines[0] ?? ""}`)}`);
@@ -404,12 +405,12 @@ export async function askQuestionsWithTabs(
404
405
  addLine(
405
406
  theme.fg(
406
407
  "dim",
407
- " ↑↓ move • Enter toggle/select • Tab add note • ←/→ switch tabs • Esc cancel",
408
+ " ↑↓ move • Space toggle/select • Enter next • Tab add note • ←/→ switch tabs • Esc cancel",
408
409
  ),
409
410
  );
410
411
  } else {
411
412
  addLine(
412
- theme.fg("dim", " ↑↓ move • Enter select • Tab add note • ←/→ switch tabs • Esc cancel"),
413
+ theme.fg("dim", " ↑↓ move • Space/Enter select • Tab add note • ←/→ switch tabs • Esc cancel"),
413
414
  );
414
415
  }
415
416
  }
@@ -533,7 +534,7 @@ export async function askQuestionsWithTabs(
533
534
  return;
534
535
  }
535
536
 
536
- if (matchesKey(data, Key.enter)) {
537
+ if (matchesKey(data, Key.space)) {
537
538
  const cursorOptionIndex = cursorOptionIndexByQuestion[questionIndex];
538
539
 
539
540
  if (preparedQuestion.multi) {
@@ -566,6 +567,37 @@ export async function askQuestionsWithTabs(
566
567
  return;
567
568
  }
568
569
 
570
+ requestUiRerender();
571
+ return;
572
+ }
573
+
574
+ if (matchesKey(data, Key.enter)) {
575
+ const cursorOptionIndex = cursorOptionIndexByQuestion[questionIndex];
576
+
577
+ if (preparedQuestion.multi) {
578
+ if (
579
+ cursorOptionIndex === preparedQuestion.otherOptionIndex &&
580
+ selectedOptionIndexesByQuestion[questionIndex].includes(cursorOptionIndex) &&
581
+ getTrimmedQuestionNote(questionIndex, cursorOptionIndex).length === 0
582
+ ) {
583
+ openNoteEditorForActiveOption();
584
+ return;
585
+ }
586
+
587
+ advanceToNextTabOrSubmit();
588
+ requestUiRerender();
589
+ return;
590
+ }
591
+
592
+ selectedOptionIndexesByQuestion[questionIndex] = [cursorOptionIndex];
593
+ if (
594
+ cursorOptionIndex === preparedQuestion.otherOptionIndex &&
595
+ getTrimmedQuestionNote(questionIndex, cursorOptionIndex).length === 0
596
+ ) {
597
+ openNoteEditorForActiveOption();
598
+ return;
599
+ }
600
+
569
601
  advanceToNextTabOrSubmit();
570
602
  requestUiRerender();
571
603
  return;
@@ -585,6 +617,7 @@ export async function askQuestionsWithTabs(
585
617
  };
586
618
 
587
619
  return {
620
+ focused: true,
588
621
  render,
589
622
  invalidate: () => {
590
623
  cachedRenderedLines = undefined;