mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 12:03:23 +00:00
Add the kill ring and undo features to the Input component (#1373)
* feat(tui): extract KillRing and UndoStack, add to Input Extract kill ring and undo logic from Editor into reusable classes: - KillRing: ring buffer with accumulation for consecutive kills - UndoStack<S>: generic stack with clone-on-push semantics Refactor Editor to use both classes. Add kill ring (kill/yank/ yank-pop), undo with coalescing, and deleteWordForward to Input. * feat(tui): extract handleBackspace() and handleForwardDelete()
This commit is contained in:
parent
da282f9e97
commit
4c2d78f6cb
5 changed files with 765 additions and 79 deletions
46
packages/tui/src/kill-ring.ts
Normal file
46
packages/tui/src/kill-ring.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* Ring buffer for Emacs-style kill/yank operations.
|
||||
*
|
||||
* Tracks killed (deleted) text entries. Consecutive kills can accumulate
|
||||
* into a single entry. Supports yank (paste most recent) and yank-pop
|
||||
* (cycle through older entries).
|
||||
*/
|
||||
export class KillRing {
|
||||
private ring: string[] = [];
|
||||
|
||||
/**
|
||||
* Add text to the kill ring.
|
||||
*
|
||||
* @param text - The killed text to add
|
||||
* @param opts - Push options
|
||||
* @param opts.prepend - If accumulating, prepend (backward deletion) or append (forward deletion)
|
||||
* @param opts.accumulate - Merge with the most recent entry instead of creating a new one
|
||||
*/
|
||||
push(text: string, opts: { prepend: boolean; accumulate?: boolean }): void {
|
||||
if (!text) return;
|
||||
|
||||
if (opts.accumulate && this.ring.length > 0) {
|
||||
const last = this.ring.pop()!;
|
||||
this.ring.push(opts.prepend ? text + last : last + text);
|
||||
} else {
|
||||
this.ring.push(text);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get most recent entry without modifying the ring. */
|
||||
peek(): string | undefined {
|
||||
return this.ring.length > 0 ? this.ring[this.ring.length - 1] : undefined;
|
||||
}
|
||||
|
||||
/** Move last entry to front (for yank-pop cycling). */
|
||||
rotate(): void {
|
||||
if (this.ring.length > 1) {
|
||||
const last = this.ring.pop()!;
|
||||
this.ring.unshift(last);
|
||||
}
|
||||
}
|
||||
|
||||
get length(): number {
|
||||
return this.ring.length;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue