examples: fix navigating unicode text in text_editor (#13286)
parent
01c72d44e8
commit
65a97a9fbe
|
@ -7,8 +7,36 @@ import os
|
||||||
import math
|
import math
|
||||||
import term.ui as tui
|
import term.ui as tui
|
||||||
import encoding.utf8
|
import encoding.utf8
|
||||||
|
import encoding.utf8.east_asian
|
||||||
|
|
||||||
const rune_digits = [`0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`]
|
const (
|
||||||
|
rune_digits = [`0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`]
|
||||||
|
|
||||||
|
zero_width_unicode = [
|
||||||
|
`\u034f`, // U+034F COMBINING GRAPHEME JOINER
|
||||||
|
`\u061c`, // U+061C ARABIC LETTER MARK
|
||||||
|
`\u17b4`, // U+17B4 KHMER VOWEL INHERENT AQ
|
||||||
|
`\u17b5`, // U+17B5 KHMER VOWEL INHERENT AA
|
||||||
|
`\u200a`, // U+200A HAIR SPACE
|
||||||
|
`\u200b`, // U+200B ZERO WIDTH SPACE
|
||||||
|
`\u200c`, // U+200C ZERO WIDTH NON-JOINER
|
||||||
|
`\u200d`, // U+200D ZERO WIDTH JOINER
|
||||||
|
`\u200e`, // U+200E LEFT-TO-RIGHT MARK
|
||||||
|
`\u200f`, // U+200F RIGHT-TO-LEFT MARK
|
||||||
|
`\u2060`, // U+2060 WORD JOINER
|
||||||
|
`\u2061`, // U+2061 FUNCTION APPLICATION
|
||||||
|
`\u2062`, // U+2062 INVISIBLE TIMES
|
||||||
|
`\u2063`, // U+2063 INVISIBLE SEPARATOR
|
||||||
|
`\u2064`, // U+2064 INVISIBLE PLUS
|
||||||
|
`\u206a`, // U+206A INHIBIT SYMMETRIC SWAPPING
|
||||||
|
`\u206b`, // U+206B ACTIVATE SYMMETRIC SWAPPING
|
||||||
|
`\u206c`, // U+206C INHIBIT ARABIC FORM SHAPING
|
||||||
|
`\u206d`, // U+206D ACTIVATE ARABIC FORM SHAPING
|
||||||
|
`\u206e`, // U+206E NATIONAL DIGIT SHAPES
|
||||||
|
`\u206f`, // U+206F NOMINAL DIGIT SHAPES
|
||||||
|
`\ufeff`, // U+FEFF ZERO WIDTH NO-BREAK SPACE
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
enum Movement {
|
enum Movement {
|
||||||
up
|
up
|
||||||
|
@ -170,6 +198,14 @@ fn (b Buffer) cur_line() string {
|
||||||
return b.line(b.cursor.pos_y)
|
return b.line(b.cursor.pos_y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (b Buffer) cur_slice() string {
|
||||||
|
line := b.line(b.cursor.pos_y).runes()
|
||||||
|
if b.cursor.pos_x == 0 || b.cursor.pos_x > line.len {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return line[..b.cursor.pos_x].string()
|
||||||
|
}
|
||||||
|
|
||||||
fn (b Buffer) cursor_index() int {
|
fn (b Buffer) cursor_index() int {
|
||||||
mut i := 0
|
mut i := 0
|
||||||
for y, line in b.lines {
|
for y, line in b.lines {
|
||||||
|
@ -501,7 +537,17 @@ fn frame(x voidptr) {
|
||||||
view := ed.view(a.viewport, scroll_limit + a.viewport)
|
view := ed.view(a.viewport, scroll_limit + a.viewport)
|
||||||
a.tui.draw_text(0, 0, view.raw)
|
a.tui.draw_text(0, 0, view.raw)
|
||||||
a.footer()
|
a.footer()
|
||||||
a.tui.set_cursor_position(view.cursor.pos_x + 1, ed.cursor.pos_y + 1 - a.viewport)
|
|
||||||
|
// Unicode: Handle correct mapping of cursor X position in terminal.
|
||||||
|
mut ch_x := view.cursor.pos_x
|
||||||
|
mut sl := ed.cur_slice().replace('\t', ' '.repeat(ed.tab_width))
|
||||||
|
if sl.len > 0 {
|
||||||
|
// Strip out any zero-width codepoints.
|
||||||
|
sl = sl.runes().filter(it !in zero_width_unicode).string()
|
||||||
|
ch_x = east_asian.display_width(sl, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.tui.set_cursor_position(ch_x + 1, ed.cursor.pos_y + 1 - a.viewport)
|
||||||
a.tui.flush()
|
a.tui.flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue