diff --git a/codex-cli/src/text-buffer.ts b/codex-cli/src/text-buffer.ts index 43cb6c4e..d7ce1530 100644 --- a/codex-cli/src/text-buffer.ts +++ b/codex-cli/src/text-buffer.ts @@ -443,17 +443,29 @@ export default class TextBuffer { const line = this.line(this.cursorRow); const arr = toCodePoints(line); - // Step 1 – skip over any separators sitting *immediately* to the left of - // the caret so that consecutive deletions wipe runs of whitespace first - // then words. + // If the cursor is just after a space (or several spaces), we only delete the separators + // then, on the next call, the previous word. We should never delete the entire line. let start = this.cursorCol; - while (start > 0 && !isWordChar(arr[start - 1])) { - start--; + let onlySpaces = true; + for (let i = 0; i < start; i++) { + if (isWordChar(arr[i])) { + onlySpaces = false; + break; + } } - // Step 2 – now skip the word characters themselves. - while (start > 0 && isWordChar(arr[start - 1])) { + // If the line contains only spaces up to the cursor, delete just one space + if (onlySpaces && start > 0) { start--; + } else { + // Step 1 – skip over any separators sitting *immediately* to the left of the caret + while (start > 0 && !isWordChar(arr[start - 1])) { + start--; + } + // Step 2 – skip the word characters themselves + while (start > 0 && isWordChar(arr[start - 1])) { + start--; + } } this.lines[this.cursorRow] = diff --git a/codex-cli/tests/text-buffer-word.test.ts b/codex-cli/tests/text-buffer-word.test.ts index 4ea76794..f02ac045 100644 --- a/codex-cli/tests/text-buffer-word.test.ts +++ b/codex-cli/tests/text-buffer-word.test.ts @@ -84,6 +84,15 @@ describe("TextBuffer – word‑wise navigation & deletion", () => { expect(col).toBe(11); }); + test("deleteWordLeft after trailing space only deletes the last word, not the whole line", () => { + const tb = new TextBuffer("I want you to refactor my view "); + tb.move("end"); // Place caret after the space + tb.deleteWordLeft(); + expect(tb.getText()).toBe("I want you to refactor my "); + const [, col] = tb.getCursor(); + expect(col).toBe("I want you to refactor my ".length); + }); + test("deleteWordLeft removes the previous word and positions the caret correctly", () => { const tb = new TextBuffer("hello world");