mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-17 07:03:25 +00:00
Fix tab rendering in TUI components
Replace tabs with 3 spaces for consistent rendering and width calculation: - Updated visibleWidth() to normalize tabs before measuring - Updated Text and Markdown components to replace tabs when rendering - Updated tool-execution display for read/write tools to replace tabs This fixes background color rendering issues when displaying files with tab indentation.
This commit is contained in:
parent
7beb354337
commit
001beff394
5 changed files with 49 additions and 5 deletions
|
|
@ -13,6 +13,13 @@ function shortenPath(path: string): string {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace tabs with spaces for consistent rendering
|
||||||
|
*/
|
||||||
|
function replaceTabs(text: string): string {
|
||||||
|
return text.replace(/\t/g, " ");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a unified diff between old and new strings with line numbers
|
* Generate a unified diff between old and new strings with line numbers
|
||||||
*/
|
*/
|
||||||
|
|
@ -120,7 +127,7 @@ export class ToolExecutionComponent extends Container {
|
||||||
const displayLines = lines.slice(0, maxLines);
|
const displayLines = lines.slice(0, maxLines);
|
||||||
const remaining = lines.length - maxLines;
|
const remaining = lines.length - maxLines;
|
||||||
|
|
||||||
text += "\n\n" + displayLines.map((line: string) => chalk.dim(line)).join("\n");
|
text += "\n\n" + displayLines.map((line: string) => chalk.dim(replaceTabs(line))).join("\n");
|
||||||
if (remaining > 0) {
|
if (remaining > 0) {
|
||||||
text += chalk.dim(`\n... (${remaining} more lines)`);
|
text += chalk.dim(`\n... (${remaining} more lines)`);
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +149,7 @@ export class ToolExecutionComponent extends Container {
|
||||||
const displayLines = lines.slice(0, maxLines);
|
const displayLines = lines.slice(0, maxLines);
|
||||||
const remaining = lines.length - maxLines;
|
const remaining = lines.length - maxLines;
|
||||||
|
|
||||||
text += "\n\n" + displayLines.map((line: string) => chalk.dim(line)).join("\n");
|
text += "\n\n" + displayLines.map((line: string) => chalk.dim(replaceTabs(line))).join("\n");
|
||||||
if (remaining > 0) {
|
if (remaining > 0) {
|
||||||
text += chalk.dim(`\n... (${remaining} more lines)`);
|
text += chalk.dim(`\n... (${remaining} more lines)`);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
28
packages/coding-agent/test.json
Normal file
28
packages/coding-agent/test.json
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "test-file",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "A test JSON file with tab indentation",
|
||||||
|
"author": "coding-agent",
|
||||||
|
"data": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "First item",
|
||||||
|
"active": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "Second item",
|
||||||
|
"active": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"created": "2024-11-11",
|
||||||
|
"tags": [
|
||||||
|
"test",
|
||||||
|
"example",
|
||||||
|
"json"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -103,8 +103,11 @@ export class Markdown implements Component {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace tabs with 3 spaces for consistent rendering
|
||||||
|
const normalizedText = this.text.replace(/\t/g, " ");
|
||||||
|
|
||||||
// Parse markdown to HTML-like tokens
|
// Parse markdown to HTML-like tokens
|
||||||
const tokens = marked.lexer(this.text);
|
const tokens = marked.lexer(normalizedText);
|
||||||
|
|
||||||
// Convert tokens to styled terminal output
|
// Convert tokens to styled terminal output
|
||||||
const renderedLines: string[] = [];
|
const renderedLines: string[] = [];
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,11 @@ export class Text implements Component {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace tabs with 3 spaces for consistent rendering
|
||||||
|
const normalizedText = this.text.replace(/\t/g, " ");
|
||||||
|
|
||||||
const lines: string[] = [];
|
const lines: string[] = [];
|
||||||
const textLines = this.text.split("\n");
|
const textLines = normalizedText.split("\n");
|
||||||
|
|
||||||
for (const line of textLines) {
|
for (const line of textLines) {
|
||||||
// Measure visible length (strip ANSI codes)
|
// Measure visible length (strip ANSI codes)
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,10 @@ import stringWidth from "string-width";
|
||||||
* - ANSI escape codes (ignored)
|
* - ANSI escape codes (ignored)
|
||||||
* - Emojis and wide characters (counted as 2 columns)
|
* - Emojis and wide characters (counted as 2 columns)
|
||||||
* - Combining characters (counted correctly)
|
* - Combining characters (counted correctly)
|
||||||
|
* - Tabs (replaced with 3 spaces for consistent width)
|
||||||
*/
|
*/
|
||||||
export function visibleWidth(str: string): number {
|
export function visibleWidth(str: string): number {
|
||||||
return stringWidth(str);
|
// Replace tabs with 3 spaces before measuring
|
||||||
|
const normalized = str.replace(/\t/g, " ");
|
||||||
|
return stringWidth(normalized);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue