pi-ask-tool-extension 0.1.5 → 0.2.2
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 +1 -1
- package/src/ask-inline-note.ts +26 -5
- package/src/ask-inline-ui.ts +16 -9
- package/src/ask-tabs-ui.ts +16 -14
package/package.json
CHANGED
package/src/ask-inline-note.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import { wrapTextWithAnsi } from "@mariozechner/pi-tui";
|
|
2
|
+
|
|
1
3
|
const INLINE_NOTE_SEPARATOR = " — note: ";
|
|
2
4
|
const INLINE_EDIT_CURSOR = "▍";
|
|
3
5
|
|
|
6
|
+
export const INLINE_NOTE_WRAP_PADDING = 2;
|
|
7
|
+
|
|
4
8
|
function sanitizeNoteForInlineDisplay(rawNote: string): string {
|
|
5
9
|
return rawNote.replace(/[\r\n\t]/g, " ").replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
|
|
6
10
|
}
|
|
@@ -31,14 +35,31 @@ export function buildOptionLabelWithInlineNote(
|
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
const labelPrefix = `${baseOptionLabel}${INLINE_NOTE_SEPARATOR}`;
|
|
34
|
-
const
|
|
35
|
-
const
|
|
38
|
+
const inlineNote = isEditingNote ? `${sanitizedNote}${INLINE_EDIT_CURSOR}` : sanitizedNote.trim();
|
|
39
|
+
const inlineLabel = `${labelPrefix}${inlineNote}`;
|
|
36
40
|
|
|
37
41
|
if (maxInlineLabelLength == null) {
|
|
38
|
-
return
|
|
42
|
+
return inlineLabel;
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
return isEditingNote
|
|
42
|
-
? truncateTextKeepingTail(
|
|
43
|
-
: truncateTextKeepingHead(
|
|
46
|
+
? truncateTextKeepingTail(inlineLabel, maxInlineLabelLength)
|
|
47
|
+
: truncateTextKeepingHead(inlineLabel, maxInlineLabelLength);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function buildWrappedOptionLabelWithInlineNote(
|
|
51
|
+
baseOptionLabel: string,
|
|
52
|
+
rawNote: string,
|
|
53
|
+
isEditingNote: boolean,
|
|
54
|
+
maxInlineLabelLength: number,
|
|
55
|
+
wrapPadding = INLINE_NOTE_WRAP_PADDING,
|
|
56
|
+
): string[] {
|
|
57
|
+
const inlineLabel = buildOptionLabelWithInlineNote(baseOptionLabel, rawNote, isEditingNote);
|
|
58
|
+
const sanitizedWrapPadding = Number.isFinite(wrapPadding) ? Math.max(0, Math.floor(wrapPadding)) : 0;
|
|
59
|
+
const sanitizedMaxInlineLabelLength = Number.isFinite(maxInlineLabelLength)
|
|
60
|
+
? Math.max(1, Math.floor(maxInlineLabelLength))
|
|
61
|
+
: 1;
|
|
62
|
+
const wrapWidth = Math.max(1, sanitizedMaxInlineLabelLength - sanitizedWrapPadding);
|
|
63
|
+
const wrappedLines = wrapTextWithAnsi(inlineLabel, wrapWidth);
|
|
64
|
+
return wrappedLines.length > 0 ? wrappedLines : [""];
|
|
44
65
|
}
|
package/src/ask-inline-ui.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtensionUIContext } from "@mariozechner/pi-coding-agent";
|
|
2
|
-
import { Editor, type EditorTheme, Key, matchesKey, truncateToWidth } from "@mariozechner/pi-tui";
|
|
2
|
+
import { Editor, type EditorTheme, Key, matchesKey, truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
|
|
3
3
|
import {
|
|
4
4
|
OTHER_OPTION,
|
|
5
5
|
appendRecommendedTagToOptionLabels,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type AskOption,
|
|
8
8
|
type AskSelection,
|
|
9
9
|
} from "./ask-logic";
|
|
10
|
-
import {
|
|
10
|
+
import { INLINE_NOTE_WRAP_PADDING, buildWrappedOptionLabelWithInlineNote } from "./ask-inline-note";
|
|
11
11
|
|
|
12
12
|
interface SingleQuestionInput {
|
|
13
13
|
question: string;
|
|
@@ -115,21 +115,28 @@ export async function askSingleQuestionWithInlineNote(
|
|
|
115
115
|
addLine(theme.fg("text", ` ${questionInput.question}`));
|
|
116
116
|
renderedLines.push("");
|
|
117
117
|
|
|
118
|
-
const maxInlineLabelLength = Math.max(12, width - 6);
|
|
119
118
|
for (let optionIndex = 0; optionIndex < selectableOptionLabels.length; optionIndex++) {
|
|
120
119
|
const optionLabel = selectableOptionLabels[optionIndex];
|
|
121
120
|
const isCursorOption = optionIndex === cursorOptionIndex;
|
|
122
121
|
const isEditingThisOption = isNoteEditorOpen && isCursorOption;
|
|
123
|
-
const
|
|
122
|
+
const cursorPrefixText = isCursorOption ? "→ " : " ";
|
|
123
|
+
const cursorPrefix = isCursorOption ? theme.fg("accent", cursorPrefixText) : cursorPrefixText;
|
|
124
|
+
const bullet = isCursorOption ? "●" : "○";
|
|
125
|
+
const markerText = `${bullet} `;
|
|
126
|
+
const optionColor = isCursorOption ? "accent" : "text";
|
|
127
|
+
const prefixWidth = visibleWidth(cursorPrefixText) + visibleWidth(markerText);
|
|
128
|
+
const wrappedInlineLabelLines = buildWrappedOptionLabelWithInlineNote(
|
|
124
129
|
optionLabel,
|
|
125
130
|
getRawNoteForOption(optionIndex),
|
|
126
131
|
isEditingThisOption,
|
|
127
|
-
|
|
132
|
+
Math.max(1, width - prefixWidth),
|
|
133
|
+
INLINE_NOTE_WRAP_PADDING,
|
|
128
134
|
);
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
const
|
|
132
|
-
|
|
135
|
+
const continuationPrefix = " ".repeat(prefixWidth);
|
|
136
|
+
addLine(`${cursorPrefix}${theme.fg(optionColor, `${markerText}${wrappedInlineLabelLines[0] ?? ""}`)}`);
|
|
137
|
+
for (const wrappedLine of wrappedInlineLabelLines.slice(1)) {
|
|
138
|
+
addLine(`${continuationPrefix}${theme.fg(optionColor, wrappedLine)}`);
|
|
139
|
+
}
|
|
133
140
|
}
|
|
134
141
|
|
|
135
142
|
renderedLines.push("");
|
package/src/ask-tabs-ui.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ExtensionUIContext } from "@mariozechner/pi-coding-agent";
|
|
2
|
-
import { Editor, type EditorTheme, Key, matchesKey, truncateToWidth } from "@mariozechner/pi-tui";
|
|
2
|
+
import { Editor, type EditorTheme, Key, matchesKey, truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
|
|
3
3
|
import {
|
|
4
4
|
OTHER_OPTION,
|
|
5
5
|
appendRecommendedTagToOptionLabels,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
type AskQuestion,
|
|
9
9
|
type AskSelection,
|
|
10
10
|
} from "./ask-logic";
|
|
11
|
-
import {
|
|
11
|
+
import { INLINE_NOTE_WRAP_PADDING, buildWrappedOptionLabelWithInlineNote } from "./ask-inline-note";
|
|
12
12
|
|
|
13
13
|
interface PreparedQuestion {
|
|
14
14
|
id: string;
|
|
@@ -317,27 +317,29 @@ export async function askQuestionsWithTabs(
|
|
|
317
317
|
addLine(theme.fg("text", ` ${preparedQuestion.question}`));
|
|
318
318
|
renderedLines.push("");
|
|
319
319
|
|
|
320
|
-
const maxInlineLabelLength = Math.max(12, width - 8);
|
|
321
320
|
for (let optionIndex = 0; optionIndex < preparedQuestion.options.length; optionIndex++) {
|
|
322
321
|
const optionLabel = preparedQuestion.options[optionIndex];
|
|
323
322
|
const isCursorOption = optionIndex === cursorOptionIndex;
|
|
324
323
|
const isOptionSelected = selectedOptionIndexes.includes(optionIndex);
|
|
325
324
|
const isEditingThisOption = isNoteEditorOpen && isCursorOption;
|
|
326
|
-
const
|
|
325
|
+
const cursorPrefixText = isCursorOption ? "→ " : " ";
|
|
326
|
+
const cursorPrefix = isCursorOption ? theme.fg("accent", cursorPrefixText) : cursorPrefixText;
|
|
327
|
+
const markerText = preparedQuestion.multi
|
|
328
|
+
? `${isOptionSelected ? "[x]" : "[ ]"} `
|
|
329
|
+
: `${isOptionSelected ? "●" : "○"} `;
|
|
330
|
+
const optionColor = isCursorOption ? "accent" : isOptionSelected ? "success" : "text";
|
|
331
|
+
const prefixWidth = visibleWidth(cursorPrefixText) + visibleWidth(markerText);
|
|
332
|
+
const wrappedInlineLabelLines = buildWrappedOptionLabelWithInlineNote(
|
|
327
333
|
optionLabel,
|
|
328
334
|
getQuestionNote(questionIndex, optionIndex),
|
|
329
335
|
isEditingThisOption,
|
|
330
|
-
|
|
336
|
+
Math.max(1, width - prefixWidth),
|
|
337
|
+
INLINE_NOTE_WRAP_PADDING,
|
|
331
338
|
);
|
|
332
|
-
const
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
addLine(`${cursorPrefix}${theme.fg(optionColor, `${checkbox} ${optionLabelWithInlineNote}`)}`);
|
|
337
|
-
} else {
|
|
338
|
-
const bullet = isOptionSelected ? "●" : "○";
|
|
339
|
-
const optionColor = isCursorOption ? "accent" : isOptionSelected ? "success" : "text";
|
|
340
|
-
addLine(`${cursorPrefix}${theme.fg(optionColor, `${bullet} ${optionLabelWithInlineNote}`)}`);
|
|
339
|
+
const continuationPrefix = " ".repeat(prefixWidth);
|
|
340
|
+
addLine(`${cursorPrefix}${theme.fg(optionColor, `${markerText}${wrappedInlineLabelLines[0] ?? ""}`)}`);
|
|
341
|
+
for (const wrappedLine of wrappedInlineLabelLines.slice(1)) {
|
|
342
|
+
addLine(`${continuationPrefix}${theme.fg(optionColor, wrappedLine)}`);
|
|
341
343
|
}
|
|
342
344
|
}
|
|
343
345
|
|