examples: fix navigating unicode text in text_editor (#13286)
							parent
							
								
									01c72d44e8
								
							
						
					
					
						commit
						65a97a9fbe
					
				| 
						 | 
				
			
			@ -7,8 +7,36 @@ import os
 | 
			
		|||
import math
 | 
			
		||||
import term.ui as tui
 | 
			
		||||
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 {
 | 
			
		||||
	up
 | 
			
		||||
| 
						 | 
				
			
			@ -170,6 +198,14 @@ fn (b Buffer) cur_line() string {
 | 
			
		|||
	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 {
 | 
			
		||||
	mut i := 0
 | 
			
		||||
	for y, line in b.lines {
 | 
			
		||||
| 
						 | 
				
			
			@ -501,7 +537,17 @@ fn frame(x voidptr) {
 | 
			
		|||
	view := ed.view(a.viewport, scroll_limit + a.viewport)
 | 
			
		||||
	a.tui.draw_text(0, 0, view.raw)
 | 
			
		||||
	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()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue