@dreki-gg/pi-questionnaire 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/CHANGELOG.md +6 -0
- package/extensions/questionnaire/ui.ts +55 -21
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { ExtensionContext } from '@earendil-works/pi-coding-agent';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
Editor,
|
|
4
|
+
type EditorTheme,
|
|
5
|
+
Key,
|
|
6
|
+
matchesKey,
|
|
7
|
+
truncateToWidth,
|
|
8
|
+
visibleWidth,
|
|
9
|
+
wrapTextWithAnsi,
|
|
10
|
+
} from '@earendil-works/pi-tui';
|
|
3
11
|
import {
|
|
4
12
|
areAllAnswersValid,
|
|
5
13
|
createInitialQuestionStateById,
|
|
@@ -50,6 +58,35 @@ function getRenderOptions(question: NormalizedQuestion): RenderOption[] {
|
|
|
50
58
|
return listed;
|
|
51
59
|
}
|
|
52
60
|
|
|
61
|
+
function pushWrappedText(lines: string[], text: string, width: number) {
|
|
62
|
+
lines.push(...wrapTextWithAnsi(text, Math.max(1, width)));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function pushWrappedWithPrefix(
|
|
66
|
+
lines: string[],
|
|
67
|
+
prefix: string,
|
|
68
|
+
text: string,
|
|
69
|
+
width: number,
|
|
70
|
+
continuationPrefix = ' '.repeat(visibleWidth(prefix)),
|
|
71
|
+
) {
|
|
72
|
+
const availableWidth = Math.max(1, width - visibleWidth(prefix));
|
|
73
|
+
const wrapped = wrapTextWithAnsi(text, availableWidth);
|
|
74
|
+
|
|
75
|
+
if (wrapped.length === 0) {
|
|
76
|
+
lines.push(truncateToWidth(prefix, width));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
lines.push(truncateToWidth(`${prefix}${wrapped[0]}`, width));
|
|
81
|
+
|
|
82
|
+
for (const line of wrapped.slice(1)) {
|
|
83
|
+
const continuationWidth = Math.max(1, width - visibleWidth(continuationPrefix));
|
|
84
|
+
for (const continuationLine of wrapTextWithAnsi(line, continuationWidth)) {
|
|
85
|
+
lines.push(truncateToWidth(`${continuationPrefix}${continuationLine}`, width));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
53
90
|
function ensureQuestionState(
|
|
54
91
|
stateById: Record<string, QuestionSelectionState>,
|
|
55
92
|
questionId: string,
|
|
@@ -357,7 +394,7 @@ export async function runQuestionnaireUI(
|
|
|
357
394
|
options.length - 1,
|
|
358
395
|
);
|
|
359
396
|
|
|
360
|
-
lines
|
|
397
|
+
pushWrappedText(lines, theme.fg('text', question.prompt), width);
|
|
361
398
|
lines.push('');
|
|
362
399
|
|
|
363
400
|
for (const [index, option] of options.entries()) {
|
|
@@ -373,19 +410,17 @@ export async function runQuestionnaireUI(
|
|
|
373
410
|
: 'Other';
|
|
374
411
|
const marker = selection.wasOtherSelected ? '[x]' : '[ ]';
|
|
375
412
|
const color = selection.wasOtherSelected ? 'accent' : 'text';
|
|
376
|
-
lines
|
|
413
|
+
pushWrappedWithPrefix(lines, prefix, theme.fg(color, `${marker} ${label}`), width);
|
|
377
414
|
continue;
|
|
378
415
|
}
|
|
379
416
|
|
|
380
417
|
const selected = selection.listedSelectedValues.includes(option.value);
|
|
381
418
|
const marker = selected ? '[x]' : '[ ]';
|
|
382
419
|
const color = selected ? 'accent' : 'text';
|
|
383
|
-
lines.
|
|
384
|
-
truncateToWidth(`${prefix}${theme.fg(color, `${marker} ${option.label}`)}`, width),
|
|
385
|
-
);
|
|
420
|
+
pushWrappedWithPrefix(lines, prefix, theme.fg(color, `${marker} ${option.label}`), width);
|
|
386
421
|
|
|
387
422
|
if (option.description) {
|
|
388
|
-
lines
|
|
423
|
+
pushWrappedWithPrefix(lines, ' ', theme.fg('muted', option.description), width);
|
|
389
424
|
}
|
|
390
425
|
}
|
|
391
426
|
|
|
@@ -402,7 +437,7 @@ export async function runQuestionnaireUI(
|
|
|
402
437
|
const ready = areAllAnswersValid(questions, uiState.questionStateById);
|
|
403
438
|
const normalizedAnswers = normalizeAnswers(questions, uiState.questionStateById);
|
|
404
439
|
|
|
405
|
-
lines
|
|
440
|
+
pushWrappedText(lines, theme.fg('accent', theme.bold('Review answers')), width);
|
|
406
441
|
lines.push('');
|
|
407
442
|
|
|
408
443
|
for (const [index, question] of questions.entries()) {
|
|
@@ -415,22 +450,21 @@ export async function runQuestionnaireUI(
|
|
|
415
450
|
const marker = valid ? theme.fg('success', '■') : theme.fg('warning', '□');
|
|
416
451
|
const value = formatAnswerValue(answer);
|
|
417
452
|
const color = valid ? 'text' : 'muted';
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
453
|
+
pushWrappedWithPrefix(
|
|
454
|
+
lines,
|
|
455
|
+
cursor,
|
|
456
|
+
`${marker} ${theme.fg('accent', `${question.label}:`)} ${theme.fg(color, value)}`,
|
|
457
|
+
width,
|
|
423
458
|
);
|
|
424
459
|
}
|
|
425
460
|
|
|
426
461
|
lines.push('');
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
),
|
|
462
|
+
pushWrappedText(
|
|
463
|
+
lines,
|
|
464
|
+
ready
|
|
465
|
+
? theme.fg('success', 'Press Enter to submit')
|
|
466
|
+
: theme.fg('warning', 'Complete all questions before submitting.'),
|
|
467
|
+
width,
|
|
434
468
|
);
|
|
435
469
|
}
|
|
436
470
|
|
|
@@ -448,7 +482,7 @@ export async function runQuestionnaireUI(
|
|
|
448
482
|
}
|
|
449
483
|
|
|
450
484
|
lines.push('');
|
|
451
|
-
lines
|
|
485
|
+
pushWrappedText(lines, theme.fg('dim', hint), width);
|
|
452
486
|
}
|
|
453
487
|
|
|
454
488
|
function render(width: number): string[] {
|