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 line = this.line(this.cursorRow);
|
||||||
const arr = toCodePoints(line);
|
const arr = toCodePoints(line);
|
||||||
|
|
||||||
// Step 1 – skip over any separators sitting *immediately* to the left of
|
// If the cursor is just after a space (or several spaces), we only delete the separators
|
||||||
// the caret so that consecutive deletions wipe runs of whitespace first
|
// then, on the next call, the previous word. We should never delete the entire line.
|
||||||
// then words.
|
|
||||||
let start = this.cursorCol;
|
let start = this.cursorCol;
|
||||||
while (start > 0 && !isWordChar(arr[start - 1])) {
|
let onlySpaces = true;
|
||||||
start--;
|
for (let i = 0; i < start; i++) {
|
||||||
|
if (isWordChar(arr[i])) {
|
||||||
|
onlySpaces = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2 – now skip the word characters themselves.
|
// If the line contains only spaces up to the cursor, delete just one space
|
||||||
while (start > 0 && isWordChar(arr[start - 1])) {
|
if (onlySpaces && start > 0) {
|
||||||
start--;
|
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] =
|
this.lines[this.cursorRow] =
|
||||||
|
|||||||
@@ -84,6 +84,15 @@ describe("TextBuffer – word‑wise navigation & deletion", () => {
|
|||||||
expect(col).toBe(11);
|
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", () => {
|
test("deleteWordLeft removes the previous word and positions the caret correctly", () => {
|
||||||
const tb = new TextBuffer("hello world");
|
const tb = new TextBuffer("hello world");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user