feat(tui, coding-agent): add configurable code block indent setting (#855)

Add markdown.codeBlockIndent setting to customize indentation prefix for
rendered code blocks. Default remains 2 spaces for visual clarity, but
setting to empty string removes indentation for easier copy/paste of
code snippets to scripts, editors, or other tools.

Changes:
- tui: add optional codeBlockIndent to MarkdownTheme interface
- coding-agent: add MarkdownSettings with codeBlockIndent property
- coding-agent: compose theme with settings at call sites (no global state)
- coding-agent: update message components to accept optional MarkdownTheme

Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
This commit is contained in:
Michael Renner 2026-01-19 22:36:03 +01:00 committed by GitHub
parent 46545276e3
commit 20c7b5fed4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 85 additions and 29 deletions

View file

@ -41,6 +41,8 @@ export interface MarkdownTheme {
strikethrough: (text: string) => string;
underline: (text: string) => string;
highlightCode?: (code: string, lang?: string) => string[];
/** Prefix applied to each rendered code block line (default: " ") */
codeBlockIndent?: string;
}
export class Markdown implements Component {
@ -263,17 +265,18 @@ export class Markdown implements Component {
}
case "code": {
const indent = this.theme.codeBlockIndent ?? " ";
lines.push(this.theme.codeBlockBorder(`\`\`\`${token.lang || ""}`));
if (this.theme.highlightCode) {
const highlightedLines = this.theme.highlightCode(token.text, token.lang);
for (const hlLine of highlightedLines) {
lines.push(` ${hlLine}`);
lines.push(`${indent}${hlLine}`);
}
} else {
// Split code by newlines and style each line
const codeLines = token.text.split("\n");
for (const codeLine of codeLines) {
lines.push(` ${this.theme.codeBlock(codeLine)}`);
lines.push(`${indent}${this.theme.codeBlock(codeLine)}`);
}
}
lines.push(this.theme.codeBlockBorder("```"));
@ -490,16 +493,17 @@ export class Markdown implements Component {
lines.push(text);
} else if (token.type === "code") {
// Code block in list item
const indent = this.theme.codeBlockIndent ?? " ";
lines.push(this.theme.codeBlockBorder(`\`\`\`${token.lang || ""}`));
if (this.theme.highlightCode) {
const highlightedLines = this.theme.highlightCode(token.text, token.lang);
for (const hlLine of highlightedLines) {
lines.push(` ${hlLine}`);
lines.push(`${indent}${hlLine}`);
}
} else {
const codeLines = token.text.split("\n");
for (const codeLine of codeLines) {
lines.push(` ${this.theme.codeBlock(codeLine)}`);
lines.push(`${indent}${this.theme.codeBlock(codeLine)}`);
}
}
lines.push(this.theme.codeBlockBorder("```"));