fix(tui): leverage Intl.Segmenter for proper Unicode word boundaries (#5022)
This commit is contained in:
@@ -591,6 +591,82 @@ describe("Editor component", () => {
|
||||
editor.handleInput("\x1b[1;5C"); // Ctrl+Right
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 6 }); // after 'foo'
|
||||
});
|
||||
|
||||
it("stops at fullwidth Chinese punctuation (issue #4972)", () => {
|
||||
const editor = new Editor(createTestTUI(), defaultEditorTheme);
|
||||
|
||||
// 你好,世界 = 你好(0-2) ,(2-3) 世界(3-5)
|
||||
editor.setText("你好,世界");
|
||||
// Cursor at end (col 5)
|
||||
|
||||
// Move left over 世界
|
||||
editor.handleInput("\x1b[1;5D"); // Ctrl+Left
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 3 }); // after ,
|
||||
|
||||
// Move left over ,
|
||||
editor.handleInput("\x1b[1;5D"); // Ctrl+Left
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 2 }); // after 你好
|
||||
|
||||
// Move left over 你好
|
||||
editor.handleInput("\x1b[1;5D"); // Ctrl+Left
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 0 }); // start
|
||||
|
||||
// Move right over 你好
|
||||
editor.handleInput("\x1b[1;5C"); // Ctrl+Right
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 2 }); // after 你好
|
||||
|
||||
// Move right over ,
|
||||
editor.handleInput("\x1b[1;5C"); // Ctrl+Right
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 3 }); // after ,
|
||||
|
||||
// Move right over 世界
|
||||
editor.handleInput("\x1b[1;5C"); // Ctrl+Right
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 5 }); // end
|
||||
});
|
||||
|
||||
it("handles mixed CJK and ASCII word movement", () => {
|
||||
const editor = new Editor(createTestTUI(), defaultEditorTheme);
|
||||
|
||||
// "hello你好,world世界" = hello(0-5) 你好(5-7) ,(7-8) world(8-13) 世界(13-15)
|
||||
editor.setText("hello你好,world世界");
|
||||
// Cursor at end (col 15)
|
||||
|
||||
// Move left over 世界
|
||||
editor.handleInput("\x1b[1;5D"); // Ctrl+Left
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 13 }); // after 'world'
|
||||
|
||||
// Move left over world
|
||||
editor.handleInput("\x1b[1;5D"); // Ctrl+Left
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 8 }); // after ,
|
||||
|
||||
// Move left over ,
|
||||
editor.handleInput("\x1b[1;5D"); // Ctrl+Left
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 7 }); // after 你好
|
||||
|
||||
// Move left over 你好
|
||||
editor.handleInput("\x1b[1;5D"); // Ctrl+Left
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 5 }); // after 'hello'
|
||||
|
||||
// Move left over hello
|
||||
editor.handleInput("\x1b[1;5D"); // Ctrl+Left
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 0 }); // start
|
||||
|
||||
// Forward from start
|
||||
editor.handleInput("\x1b[1;5C"); // Ctrl+Right
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 5 }); // after 'hello'
|
||||
|
||||
editor.handleInput("\x1b[1;5C"); // Ctrl+Right
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 7 }); // after 你好
|
||||
|
||||
editor.handleInput("\x1b[1;5C"); // Ctrl+Right
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 8 }); // after ,
|
||||
|
||||
editor.handleInput("\x1b[1;5C"); // Ctrl+Right
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 13 }); // after 'world'
|
||||
|
||||
editor.handleInput("\x1b[1;5C"); // Ctrl+Right
|
||||
assert.deepStrictEqual(editor.getCursor(), { line: 0, col: 15 }); // end
|
||||
});
|
||||
});
|
||||
|
||||
describe("Grapheme-aware text wrapping", () => {
|
||||
|
||||
Reference in New Issue
Block a user