term.ui: add support for multi byte/UTF-8 events (#13274)
							parent
							
								
									ca1f675dba
								
							
						
					
					
						commit
						28ddd8440a
					
				| 
						 | 
					@ -6,6 +6,9 @@ module ui
 | 
				
			||||||
struct ExtraContext {
 | 
					struct ExtraContext {
 | 
				
			||||||
mut:
 | 
					mut:
 | 
				
			||||||
	read_buf []byte
 | 
						read_buf []byte
 | 
				
			||||||
 | 
						// read_all_bytes causes all the raw bytes to be read as one event unit.
 | 
				
			||||||
 | 
						// This is cruicial for UTF-8 support since Unicode codepoints can span several bytes.
 | 
				
			||||||
 | 
						read_all_bytes bool = true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ctx_ptr = &Context(0)
 | 
					const ctx_ptr = &Context(0)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -257,10 +257,16 @@ fn (mut ctx Context) parse_events() {
 | 
				
			||||||
			e, len := escape_sequence(ctx.read_buf.bytestr())
 | 
								e, len := escape_sequence(ctx.read_buf.bytestr())
 | 
				
			||||||
			event = e
 | 
								event = e
 | 
				
			||||||
			ctx.shift(len)
 | 
								ctx.shift(len)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if ctx.read_all_bytes {
 | 
				
			||||||
 | 
									e, len := multi_char(ctx.read_buf.bytestr())
 | 
				
			||||||
 | 
									event = e
 | 
				
			||||||
 | 
									ctx.shift(len)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				event = single_char(ctx.read_buf.bytestr())
 | 
									event = single_char(ctx.read_buf.bytestr())
 | 
				
			||||||
				ctx.shift(1)
 | 
									ctx.shift(1)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if event != 0 {
 | 
							if event != 0 {
 | 
				
			||||||
			ctx.event(event)
 | 
								ctx.event(event)
 | 
				
			||||||
			nr_iters = 0
 | 
								nr_iters = 0
 | 
				
			||||||
| 
						 | 
					@ -271,6 +277,47 @@ fn (mut ctx Context) parse_events() {
 | 
				
			||||||
fn single_char(buf string) &Event {
 | 
					fn single_char(buf string) &Event {
 | 
				
			||||||
	ch := buf[0]
 | 
						ch := buf[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mut event := &Event{
 | 
				
			||||||
 | 
							typ: .key_down
 | 
				
			||||||
 | 
							ascii: ch
 | 
				
			||||||
 | 
							code: KeyCode(ch)
 | 
				
			||||||
 | 
							utf8: ch.ascii_str()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						match ch {
 | 
				
			||||||
 | 
							// special handling for `ctrl + letter`
 | 
				
			||||||
 | 
							// TODO: Fix assoc in V and remove this workaround :/
 | 
				
			||||||
 | 
							// 1  ... 26 { event = Event{ ...event, code: KeyCode(96 | ch), modifiers: .ctrl  } }
 | 
				
			||||||
 | 
							// 65 ... 90 { event = Event{ ...event, code: KeyCode(32 | ch), modifiers: .shift } }
 | 
				
			||||||
 | 
							// The bit `or`s here are really just `+`'s, just written in this way for a tiny performance improvement
 | 
				
			||||||
 | 
							// don't treat tab, enter as ctrl+i, ctrl+j
 | 
				
			||||||
 | 
							1...8, 11...26 {
 | 
				
			||||||
 | 
								event = &Event{
 | 
				
			||||||
 | 
									typ: event.typ
 | 
				
			||||||
 | 
									ascii: event.ascii
 | 
				
			||||||
 | 
									utf8: event.utf8
 | 
				
			||||||
 | 
									code: KeyCode(96 | ch)
 | 
				
			||||||
 | 
									modifiers: .ctrl
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							65...90 {
 | 
				
			||||||
 | 
								event = &Event{
 | 
				
			||||||
 | 
									typ: event.typ
 | 
				
			||||||
 | 
									ascii: event.ascii
 | 
				
			||||||
 | 
									utf8: event.utf8
 | 
				
			||||||
 | 
									code: KeyCode(32 | ch)
 | 
				
			||||||
 | 
									modifiers: .shift
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return event
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn multi_char(buf string) (&Event, int) {
 | 
				
			||||||
 | 
						ch := buf[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mut event := &Event{
 | 
						mut event := &Event{
 | 
				
			||||||
		typ: .key_down
 | 
							typ: .key_down
 | 
				
			||||||
		ascii: ch
 | 
							ascii: ch
 | 
				
			||||||
| 
						 | 
					@ -306,7 +353,7 @@ fn single_char(buf string) &Event {
 | 
				
			||||||
		else {}
 | 
							else {}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return event
 | 
						return event, buf.len
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Gets an entire, independent escape sequence from the buffer
 | 
					// Gets an entire, independent escape sequence from the buffer
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue