Commit 39d86d850029
Changed files (1)
dots
pi
agent
extensions
dots/pi/agent/extensions/cwd-history.ts
@@ -353,10 +353,6 @@ function getModeBorderColor(ctx: ExtensionContext, pi: ExtensionAPI, mode: strin
return theme.getThinkingBorderColor(pi.getThinkingLevel());
}
-function formatModeLabel(mode: string): string {
- return mode;
-}
-
async function resolveModesPath(cwd: string): Promise<string> {
const projectPath = getProjectModesPath(cwd);
if (await fileExists(projectPath)) return projectPath;
@@ -451,6 +447,17 @@ const runtime: ModeRuntime = {
// Updated by setEditor() when the custom editor is instantiated.
let requestEditorRender: (() => void) | undefined;
+// Update the mode status in the footer via ctx.ui.setStatus
+function updateModeStatus(ctx: ExtensionContext): void {
+ if (!ctx.hasUI) return;
+ const mode = runtime.currentMode;
+ if (mode && mode !== "default") {
+ ctx.ui.setStatus("mode", ctx.ui.theme.fg("dim", `[${mode}]`));
+ } else {
+ ctx.ui.setStatus("mode", undefined);
+ }
+}
+
async function ensureRuntime(pi: ExtensionAPI, ctx: ExtensionContext): Promise<void> {
const filePath = await resolveModesPath(ctx.cwd);
@@ -549,7 +556,10 @@ async function applyMode(pi: ExtensionAPI, ctx: ExtensionContext, mode: string):
if (mode === CUSTOM_MODE_NAME) {
runtime.currentMode = CUSTOM_MODE_NAME;
customOverlay = getCurrentSelectionSpec(pi, ctx);
- if (ctx.hasUI) requestEditorRender?.();
+ if (ctx.hasUI) {
+ updateModeStatus(ctx);
+ requestEditorRender?.();
+ }
return;
}
@@ -602,6 +612,7 @@ async function applyMode(pi: ExtensionAPI, ctx: ExtensionContext, mode: string):
}
if (ctx.hasUI) {
+ updateModeStatus(ctx);
requestEditorRender?.();
}
}
@@ -807,6 +818,7 @@ async function editModeUI(pi: ExtensionAPI, ctx: ExtensionContext, mode: string)
if (runtime.lastRealMode === modeName) {
runtime.lastRealMode = "default";
}
+ updateModeStatus(ctx);
requestEditorRender?.();
ctx.ui.notify(`Deleted mode \"${modeName}\"`, "info");
return;
@@ -851,6 +863,7 @@ async function renameModeUI(pi: ExtensionAPI, ctx: ExtensionContext, oldName: st
if (runtime.currentMode === oldName) runtime.currentMode = newName;
if (runtime.lastRealMode === oldName) runtime.lastRealMode = newName;
+ updateModeStatus(ctx);
requestEditorRender?.();
ctx.ui.notify(`Renamed \"${oldName}\" → \"${newName}\"`, "info");
@@ -927,12 +940,6 @@ interface PromptEntry {
}
class PromptEditor extends CustomEditor {
- public modeLabelProvider?: () => string;
- /**
- * Color function for the mode label. If unset, the label inherits the border color.
- * We use this to keep the label consistent (e.g. same as the footer/status bar).
- */
- public modeLabelColor?: (text: string) => string;
private lockedBorder = false;
private _borderColor?: (text: string) => string;
@@ -958,41 +965,6 @@ class PromptEditor extends CustomEditor {
this.lockedBorder = true;
}
- render(width: number): string[] {
- const lines = super.render(width);
- const mode = this.modeLabelProvider?.();
- if (!mode) return lines;
-
- const stripAnsi = (s: string) => s.replace(/\x1b\[[0-9;]*m/g, "");
- const topPlain = stripAnsi(lines[0] ?? "");
-
- // If the editor is scrolled, the built-in editor renders a scroll indicator on the top border.
- // Preserve it, but still show the mode label.
- const scrollPrefixMatch = topPlain.match(/^(─── ↑ \d+ more )/);
- const prefix = scrollPrefixMatch?.[1] ?? "──";
-
- let label = formatModeLabel(mode);
-
- // Compute how much room we have for the label core (without truncating the prefix).
- const labelLeftSpace = prefix.endsWith(" ") ? "" : " ";
- const labelRightSpace = " ";
- const minRightBorder = 1; // keep at least one border cell on the right
- const maxLabelLen = Math.max(0, width - prefix.length - labelLeftSpace.length - labelRightSpace.length - minRightBorder);
- if (maxLabelLen <= 0) return lines;
- if (label.length > maxLabelLen) label = label.slice(0, maxLabelLen);
-
- const labelChunk = `${labelLeftSpace}${label}${labelRightSpace}`;
-
- const remaining = width - prefix.length - labelChunk.length;
- if (remaining < 0) return lines;
-
- const right = "─".repeat(Math.max(0, remaining));
-
- const labelColor = this.modeLabelColor ?? ((text: string) => this.borderColor(text));
- lines[0] = this.borderColor(prefix) + labelColor(labelChunk) + this.borderColor(right);
- return lines;
- }
-
public requestRenderNow(): void {
this.tui.requestRender();
}
@@ -1146,9 +1118,6 @@ function setEditor(pi: ExtensionAPI, ctx: ExtensionContext, history: PromptEntry
ctx.ui.setEditorComponent((tui, theme, keybindings) => {
const editor = new PromptEditor(tui, theme, keybindings);
requestEditorRender = () => editor.requestRenderNow();
- editor.modeLabelProvider = () => runtime.currentMode;
- // Keep the mode label color stable (match footer/status bar).
- editor.modeLabelColor = (text: string) => ctx.ui.theme.fg("dim", text);
const borderColor = (text: string) => {
const isBashMode = editor.getText().trimStart().startsWith("!");
if (isBashMode) {
@@ -1264,6 +1233,7 @@ export default function (pi: ExtensionAPI) {
customOverlay = getCurrentSelectionSpec(pi, ctx);
}
+ updateModeStatus(ctx);
applyEditor(pi, ctx);
});
@@ -1281,6 +1251,7 @@ export default function (pi: ExtensionAPI) {
customOverlay = getCurrentSelectionSpec(pi, ctx);
}
+ updateModeStatus(ctx);
applyEditor(pi, ctx);
});
@@ -1308,6 +1279,7 @@ export default function (pi: ExtensionAPI) {
// Do not persist/select custom.
if (ctx.hasUI) {
+ updateModeStatus(ctx);
requestEditorRender?.();
}
});