fix(text-buffer): correct word deletion logic for trailing spaces (Ctrl+Backspace) (#131)
## Description This fix resolves a bug where Ctrl+Backspace (hex 0x17) deletes the entire line when the cursor is positioned after a trailing space. ## Problem When the user has a line like "I want you to refactor my view " (with a space at the end) and the cursor is after that space, Ctrl+Backspace deletes the entire line instead of just removing the word "view". ## Solution - Added a check to detect if the cursor is after spaces - Modified the logic to delete only one space at a time in this case - Added a unit test to verify this behavior ## Tests All tests pass, including the new test that verifies the corrected behavior. --------- Signed-off-by: Alpha Diop <alphakhoss@gmail.com> Co-authored-by: Thibault Sottiaux <tibo@openai.com>
This commit is contained in:
@@ -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] =
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user