mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-17 05:00:16 +00:00
Release v0.7.28
- Add message queuing with configurable modes (one-at-a-time/all) (#15) - Add /queue command to select queue mode - Add TruncatedText component for proper viewport-aware text truncation - Queue mode setting persists in ~/.pi/agent/settings.json - Visual feedback for queued messages with proper ANSI handling - Press Escape to abort and restore queued messages to editor
This commit is contained in:
parent
e694d435fd
commit
d44073b140
18 changed files with 477 additions and 108 deletions
78
packages/tui/src/components/truncated-text.ts
Normal file
78
packages/tui/src/components/truncated-text.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import type { Component } from "../tui.js";
|
||||
import { visibleWidth } from "../utils.js";
|
||||
|
||||
/**
|
||||
* Text component that truncates to fit viewport width
|
||||
*/
|
||||
export class TruncatedText implements Component {
|
||||
private text: string;
|
||||
private paddingX: number;
|
||||
private paddingY: number;
|
||||
|
||||
constructor(text: string, paddingX: number = 0, paddingY: number = 0) {
|
||||
this.text = text;
|
||||
this.paddingX = paddingX;
|
||||
this.paddingY = paddingY;
|
||||
}
|
||||
|
||||
render(width: number): string[] {
|
||||
const result: string[] = [];
|
||||
|
||||
// Add vertical padding above
|
||||
for (let i = 0; i < this.paddingY; i++) {
|
||||
result.push("");
|
||||
}
|
||||
|
||||
// Calculate available width after horizontal padding
|
||||
const availableWidth = Math.max(1, width - this.paddingX * 2);
|
||||
|
||||
// Truncate text if needed (accounting for ANSI codes)
|
||||
let displayText = this.text;
|
||||
const textVisibleWidth = visibleWidth(this.text);
|
||||
|
||||
if (textVisibleWidth > availableWidth) {
|
||||
// Need to truncate - walk through the string character by character
|
||||
let currentWidth = 0;
|
||||
let truncateAt = 0;
|
||||
let i = 0;
|
||||
const ellipsisWidth = 3;
|
||||
const targetWidth = availableWidth - ellipsisWidth;
|
||||
|
||||
while (i < this.text.length && currentWidth < targetWidth) {
|
||||
// Skip ANSI escape sequences
|
||||
if (this.text[i] === "\x1b" && this.text[i + 1] === "[") {
|
||||
let j = i + 2;
|
||||
while (j < this.text.length && !/[a-zA-Z]/.test(this.text[j])) {
|
||||
j++;
|
||||
}
|
||||
i = j + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
const char = this.text[i];
|
||||
const charWidth = visibleWidth(char);
|
||||
|
||||
if (currentWidth + charWidth > targetWidth) {
|
||||
break;
|
||||
}
|
||||
|
||||
currentWidth += charWidth;
|
||||
truncateAt = i + 1;
|
||||
i++;
|
||||
}
|
||||
|
||||
displayText = this.text.substring(0, truncateAt) + "...";
|
||||
}
|
||||
|
||||
// Add horizontal padding
|
||||
const paddingStr = " ".repeat(this.paddingX);
|
||||
result.push(paddingStr + displayText);
|
||||
|
||||
// Add vertical padding below
|
||||
for (let i = 0; i < this.paddingY; i++) {
|
||||
result.push("");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue