Fix Ctrl+W to use standard readline word deletion behavior (#306)

- Skip trailing whitespace before deleting word (readline behavior)
- Make word navigation grapheme-aware using Intl.Segmenter
- Add Ctrl+Left/Right and Alt+Left/Right word navigation to Input
- Accept full Unicode input while rejecting control characters (C0/C1/DEL)
- Extract shared utilities to utils.ts (getSegmenter, isWhitespaceChar, isPunctuationChar)
- Fix unsafe cast in Editor.forceFileAutocomplete with runtime type check
- Add comprehensive tests for word deletion and navigation
This commit is contained in:
Ahmed Kamal 2025-12-25 05:09:47 +02:00 committed by GitHub
parent 65cbc22d7c
commit 0427445242
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 250 additions and 86 deletions

View file

@ -406,8 +406,30 @@ function wrapSingleLine(line: string, width: number): string[] {
return wrapped.length > 0 ? wrapped : [""];
}
// Grapheme segmenter for proper Unicode iteration (handles emojis, etc.)
const segmenter = new Intl.Segmenter();
const segmenter = new Intl.Segmenter(undefined, { granularity: "grapheme" });
/**
* Get the shared grapheme segmenter instance.
*/
export function getSegmenter(): Intl.Segmenter {
return segmenter;
}
const PUNCTUATION_REGEX = /[(){}[\]<>.,;:'"!?+\-=*/\\|&%^$#@~`]/;
/**
* Check if a character is whitespace.
*/
export function isWhitespaceChar(char: string): boolean {
return /\s/.test(char);
}
/**
* Check if a character is punctuation.
*/
export function isPunctuationChar(char: string): boolean {
return PUNCTUATION_REGEX.test(char);
}
function breakLongWord(word: string, width: number, tracker: AnsiCodeTracker): string[] {
const lines: string[] = [];