fix(tui): show latest shell output

This commit is contained in:
Dax Raad
2026-09-14 13:03:10 -04:00
Unverified
parent 8cf4e6b9b4
commit 60b88daddf
2 changed files with 32 additions and 9 deletions
+4 -9
View File
@@ -77,7 +77,7 @@ import { useConfig } from "../../config"
import { useClipboard } from "../../context/clipboard"
import { nextThinkingMode, reasoningSummary, type ThinkingMode } from "../../context/thinking"
import { getScrollAcceleration } from "../../util/scroll"
import { collapseToolOutput } from "../../util/collapse-tool-output"
import { collapseShellOutput, collapseToolOutput } from "../../util/collapse-tool-output"
import { Keymap, type KeymapCommand } from "../../context/keymap"
import { usePathFormatter } from "../../context/path-format"
import { useLocation } from "../../context/location"
@@ -2968,14 +2968,9 @@ function ShellDisplay(props: {
const maxChars = createMemo(() => maxLines * Math.max(20, ctx.width - 6))
const prefix = createMemo(() => (workdir() && workdir() !== "." ? `cd ${workdir()} && ` : ""))
const input = createMemo(() => (props.command ? `${isRunning() ? "" : "$ "}${prefix()}${props.command}` : ""))
const content = createMemo(() => [input(), output()].filter(Boolean).join("\n\n"))
const collapsed = createMemo(() => collapseToolOutput(content(), maxLines, maxChars()))
const limited = createMemo(() => {
if (expanded() || !collapsed().overflow) return content()
return collapsed().output
})
const limitedInput = createMemo(() => limited().slice(0, input().length))
const limitedOutput = createMemo(() => limited().slice(Math.min(limited().length, input().length + 2)))
const collapsed = createMemo(() => collapseShellOutput(input(), output(), maxLines, maxChars()))
const limitedInput = createMemo(() => (expanded() ? input() : collapsed().input))
const limitedOutput = createMemo(() => (expanded() ? output() : collapsed().output))
const expandable = createMemo(() => Boolean(props.shellID) || collapsed().overflow)
const toggle = () => {
const next = !expanded()
@@ -19,3 +19,31 @@ export function collapseToolOutput(output: string, maxLines: number, maxChars: n
return { output: preview, overflow: true }
}
export function collapseShellOutput(input: string, output: string, maxLines: number, maxChars: number) {
const content = [input, output].filter(Boolean).join("\n\n")
const collapsed = collapseToolOutput(content, maxLines, maxChars)
if (!collapsed.overflow) return { input, output, overflow: false }
if (!input) return { input, output: collapseTail(output, maxLines, maxChars), overflow: true }
if (!output) return { input: collapsed.output, output, overflow: true }
const reserved = Math.max(1, Math.floor(maxChars / maxLines))
const command = collapseToolOutput(
input,
Math.max(1, maxLines - 2),
Math.max(1, maxChars - reserved - 2),
).output
const lines = Math.max(1, maxLines - command.split("\n").length - 1)
const chars = Math.max(1, maxChars - Array.from(command).length - 2)
return { input: command, output: collapseTail(output, lines, chars), overflow: true }
}
function collapseTail(output: string, maxLines: number, maxChars: number) {
const lines = output.split("\n")
if (lines.length <= maxLines && Array.from(output).length <= maxChars) return output
const preview = lines.slice(-maxLines).join("\n")
const visible = Array.from(preview)
if (visible.length < maxChars) return `…${preview}`
return `…${visible.slice(-Math.max(0, maxChars - 1)).join("")}`
}