feat(examples): Wrap question extension text instead of truncating (#5708)
This commit is contained in:
@@ -5,7 +5,15 @@
|
||||
*/
|
||||
|
||||
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
||||
import { Editor, type EditorTheme, Key, matchesKey, Text, truncateToWidth } from "@earendil-works/pi-tui";
|
||||
import {
|
||||
Editor,
|
||||
type EditorTheme,
|
||||
Key,
|
||||
matchesKey,
|
||||
Text,
|
||||
visibleWidth,
|
||||
wrapTextWithAnsi,
|
||||
} from "@earendil-works/pi-tui";
|
||||
import { Type } from "typebox";
|
||||
|
||||
interface OptionWithDesc {
|
||||
@@ -139,10 +147,27 @@ export default function question(pi: ExtensionAPI) {
|
||||
if (cachedLines) return cachedLines;
|
||||
|
||||
const lines: string[] = [];
|
||||
const add = (s: string) => lines.push(truncateToWidth(s, width));
|
||||
const renderWidth = Math.max(1, width);
|
||||
|
||||
add(theme.fg("accent", "─".repeat(width)));
|
||||
add(theme.fg("text", ` ${params.question}`));
|
||||
function addWrapped(text: string) {
|
||||
lines.push(...wrapTextWithAnsi(text, renderWidth));
|
||||
}
|
||||
|
||||
function addWrappedWithPrefix(prefix: string, text: string) {
|
||||
const prefixWidth = visibleWidth(prefix);
|
||||
if (prefixWidth >= renderWidth) {
|
||||
addWrapped(prefix + text);
|
||||
return;
|
||||
}
|
||||
const wrapped = wrapTextWithAnsi(text, renderWidth - prefixWidth);
|
||||
const continuationPrefix = " ".repeat(prefixWidth);
|
||||
for (let i = 0; i < wrapped.length; i++) {
|
||||
lines.push(`${i === 0 ? prefix : continuationPrefix}${wrapped[i]}`);
|
||||
}
|
||||
}
|
||||
|
||||
lines.push(theme.fg("accent", "─".repeat(renderWidth)));
|
||||
addWrappedWithPrefix(" ", theme.fg("text", params.question));
|
||||
lines.push("");
|
||||
|
||||
for (let i = 0; i < allOptions.length; i++) {
|
||||
@@ -150,36 +175,32 @@ export default function question(pi: ExtensionAPI) {
|
||||
const selected = i === optionIndex;
|
||||
const isOther = opt.isOther === true;
|
||||
const prefix = selected ? theme.fg("accent", "> ") : " ";
|
||||
const label = `${i + 1}. ${opt.label}${isOther && editMode ? " ✎" : ""}`;
|
||||
const color = selected || (isOther && editMode) ? "accent" : "text";
|
||||
|
||||
if (isOther && editMode) {
|
||||
add(prefix + theme.fg("accent", `${i + 1}. ${opt.label} ✎`));
|
||||
} else if (selected) {
|
||||
add(prefix + theme.fg("accent", `${i + 1}. ${opt.label}`));
|
||||
} else {
|
||||
add(` ${theme.fg("text", `${i + 1}. ${opt.label}`)}`);
|
||||
}
|
||||
addWrappedWithPrefix(prefix, theme.fg(color, label));
|
||||
|
||||
// Show description if present
|
||||
if (opt.description) {
|
||||
add(` ${theme.fg("muted", opt.description)}`);
|
||||
addWrappedWithPrefix(" ", theme.fg("muted", opt.description));
|
||||
}
|
||||
}
|
||||
|
||||
if (editMode) {
|
||||
lines.push("");
|
||||
add(theme.fg("muted", " Your answer:"));
|
||||
for (const line of editor.render(width - 2)) {
|
||||
add(` ${line}`);
|
||||
addWrappedWithPrefix(" ", theme.fg("muted", "Your answer:"));
|
||||
for (const line of editor.render(Math.max(1, renderWidth - 2))) {
|
||||
lines.push(` ${line}`);
|
||||
}
|
||||
}
|
||||
|
||||
lines.push("");
|
||||
if (editMode) {
|
||||
add(theme.fg("dim", " Enter to submit • Esc to go back"));
|
||||
addWrappedWithPrefix(" ", theme.fg("dim", "Enter to submit • Esc to go back"));
|
||||
} else {
|
||||
add(theme.fg("dim", " ↑↓ navigate • Enter to select • Esc to cancel"));
|
||||
addWrappedWithPrefix(" ", theme.fg("dim", "↑↓ navigate • Enter to select • Esc to cancel"));
|
||||
}
|
||||
add(theme.fg("accent", "─".repeat(width)));
|
||||
lines.push(theme.fg("accent", "─".repeat(renderWidth)));
|
||||
|
||||
cachedLines = lines;
|
||||
return lines;
|
||||
|
||||
Reference in New Issue
Block a user