mirror of
https://github.com/earendil-works/pi.git
synced 2026-06-18 15:54:04 +08:00
Merge pull request #5585 from haoqixu/fix-editor-cjk-wrap
fix(tui): wrap CJK text at character boundaries in editor
This commit is contained in:
@@ -4,7 +4,14 @@ import { decodePrintableKey, matchesKey } from "../keys.ts";
|
||||
import { KillRing } from "../kill-ring.ts";
|
||||
import { type Component, CURSOR_MARKER, type Focusable, type TUI } from "../tui.ts";
|
||||
import { UndoStack } from "../undo-stack.ts";
|
||||
import { getGraphemeSegmenter, getWordSegmenter, isWhitespaceChar, truncateToWidth, visibleWidth } from "../utils.ts";
|
||||
import {
|
||||
cjkBreakRegex,
|
||||
getGraphemeSegmenter,
|
||||
getWordSegmenter,
|
||||
isWhitespaceChar,
|
||||
truncateToWidth,
|
||||
visibleWidth,
|
||||
} from "../utils.ts";
|
||||
import { findWordBackward, findWordForward } from "../word-navigation.ts";
|
||||
import { SelectList, type SelectListLayoutOptions, type SelectListTheme } from "./select-list.ts";
|
||||
|
||||
@@ -174,13 +181,21 @@ export function wordWrapLine(line: string, maxWidth: number, preSegmented?: Intl
|
||||
// Advance.
|
||||
currentWidth += gWidth;
|
||||
|
||||
// Record wrap opportunity: whitespace followed by non-whitespace.
|
||||
// Multiple spaces join (no break between them); the break point is
|
||||
// after the last space before the next word.
|
||||
// Record wrap opportunity: whitespace followed by non-whitespace
|
||||
// (multiple spaces join; the break point is after the last space),
|
||||
// or at a boundary where either side is CJK (CJK allows breaking
|
||||
// between any adjacent characters).
|
||||
const next = segments[i + 1];
|
||||
if (isWs && next && (isPasteMarker(next.segment) || !isWhitespaceChar(next.segment))) {
|
||||
wrapOppIndex = next.index;
|
||||
wrapOppWidth = currentWidth;
|
||||
} else if (!isWs && next && !isWhitespaceChar(next.segment)) {
|
||||
const isCjk = !isPasteMarker(grapheme) && cjkBreakRegex.test(grapheme);
|
||||
const nextIsCjk = !isPasteMarker(next.segment) && cjkBreakRegex.test(next.segment);
|
||||
if (isCjk || nextIsCjk) {
|
||||
wrapOppIndex = next.index;
|
||||
wrapOppWidth = currentWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ const rgiEmojiRegex = /^\p{RGI_Emoji}$/v;
|
||||
const WIDTH_CACHE_SIZE = 512;
|
||||
const widthCache = new Map<string, number>();
|
||||
|
||||
const cjkBreakRegex =
|
||||
export const cjkBreakRegex =
|
||||
/[\p{Script_Extensions=Han}\p{Script_Extensions=Hiragana}\p{Script_Extensions=Katakana}\p{Script_Extensions=Hangul}\p{Script_Extensions=Bopomofo}]/u;
|
||||
|
||||
function isPrintableAscii(str: string): boolean {
|
||||
|
||||
Reference in New Issue
Block a user