Wire up a bunch of callbacks

This commit is contained in:
Kovid Goyal 2022-08-23 20:08:04 +05:30
parent e18b6638bb
commit 526a331f47
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 91 additions and 19 deletions

View File

@ -118,11 +118,12 @@ func do_io(device IOAbstraction, input utils.Reader, no_response bool, response_
response_received := false response_received := false
cmd_prefix := []byte("@kitty-cmd") cmd_prefix := []byte("@kitty-cmd")
handle_dcs := func(b []byte) { handle_dcs := func(b []byte) error {
if bytes.HasPrefix(b, cmd_prefix) { if bytes.HasPrefix(b, cmd_prefix) {
response_received = true response_received = true
} }
serialized_response = b[len(cmd_prefix):] serialized_response = b[len(cmd_prefix):]
return nil
} }
var p utils.EscapeCodeParser = utils.EscapeCodeParser{HandleDCS: handle_dcs} var p utils.EscapeCodeParser = utils.EscapeCodeParser{HandleDCS: handle_dcs}

View File

@ -6,21 +6,56 @@ import (
"kitty/tools/tty" "kitty/tools/tty"
"os" "os"
"time" "time"
"kitty/tools/utils"
) )
type TerminalState struct { type Loop struct {
alternate_screen, grab_mouse bool controlling_term *tty.Term
terminal_options TerminalStateOptions
escape_code_parser utils.EscapeCodeParser
keep_going bool
flush_write_buf bool
write_buf []byte
} }
type Loop struct { func (self *Loop) handle_csi(raw []byte) error {
controlling_term *tty.Term return nil
keep_going bool }
flush_write_buf bool
write_buf []byte func (self *Loop) handle_osc(raw []byte) error {
return nil
}
func (self *Loop) handle_dcs(raw []byte) error {
return nil
}
func (self *Loop) handle_apc(raw []byte) error {
return nil
}
func (self *Loop) handle_sos(raw []byte) error {
return nil
}
func (self *Loop) handle_pm(raw []byte) error {
return nil
}
func (self *Loop) handle_rune(raw rune) error {
return nil
} }
func CreateLoop() (*Loop, error) { func CreateLoop() (*Loop, error) {
l := Loop{controlling_term: nil} l := Loop{controlling_term: nil}
l.escape_code_parser.HandleCSI = l.handle_csi
l.escape_code_parser.HandleOSC = l.handle_osc
l.escape_code_parser.HandleDCS = l.handle_dcs
l.escape_code_parser.HandleAPC = l.handle_apc
l.escape_code_parser.HandleSOS = l.handle_sos
l.escape_code_parser.HandlePM = l.handle_pm
l.escape_code_parser.HandleRune = l.handle_rune
return &l, nil return &l, nil
} }
@ -51,6 +86,7 @@ func (self *Loop) Run() (err error) {
if err != nil { if err != nil {
return err return err
} }
tty_fd := controlling_term.Fd()
self.controlling_term = controlling_term self.controlling_term = controlling_term
defer func() { defer func() {
self.controlling_term.RestoreAndClose() self.controlling_term.RestoreAndClose()
@ -63,18 +99,29 @@ func (self *Loop) Run() (err error) {
var selector Select var selector Select
selector.RegisterRead(int(signal_read_file.Fd())) selector.RegisterRead(int(signal_read_file.Fd()))
selector.RegisterRead(controlling_term.Fd()) selector.RegisterRead(tty_fd)
self.keep_going = true self.keep_going = true
self.flush_write_buf = true self.flush_write_buf = true
self.queue_write_to_tty(self.terminal_options.SetStateEscapeCodes())
defer func() { defer func() {
if self.flush_write_buf { if self.flush_write_buf {
self.flush() self.flush()
} }
self.write_buf = self.write_buf[:]
self.queue_write_to_tty(self.terminal_options.ResetStateEscapeCodes())
self.flush()
}() }()
read_buf := make([]byte, utils.DEFAULT_IO_BUFFER_SIZE)
self.escape_code_parser.Reset()
for self.keep_going { for self.keep_going {
if len(self.write_buf) > 0 {
selector.RegisterWrite(tty_fd)
} else {
selector.UnRegisterWrite(tty_fd)
}
num_ready, err := selector.WaitForever() num_ready, err := selector.WaitForever()
if err != nil { if err != nil {
return fmt.Errorf("Failed to call select() with error: %w", err) return fmt.Errorf("Failed to call select() with error: %w", err)
@ -82,12 +129,36 @@ func (self *Loop) Run() (err error) {
if num_ready == 0 { if num_ready == 0 {
continue continue
} }
if len(self.write_buf) > 0 && selector.IsReadyToWrite(tty_fd) {
err := self.write_to_tty()
if err != nil {
return err
}
}
if selector.IsReadyToRead(tty_fd) {
read_buf = read_buf[:cap(read_buf)]
num_read, err := self.controlling_term.Read(read_buf)
if err != nil {
return err
}
if num_read == 0 {
return io.EOF
}
err = self.escape_code_parser.Parse(read_buf[:num_read])
if err != nil {
return err
}
}
} }
return nil return nil
} }
func (self *Loop) write() error { func (self *Loop) queue_write_to_tty(data []byte) {
self.write_buf = append(self.write_buf, data...)
}
func (self *Loop) write_to_tty() error {
if len(self.write_buf) == 0 || self.controlling_term == nil { if len(self.write_buf) == 0 || self.controlling_term == nil {
return nil return nil
} }
@ -125,7 +196,7 @@ func (self *Loop) flush() error {
return err return err
} }
if num_ready > 0 && selector.IsReadyToWrite(self.controlling_term.Fd()) { if num_ready > 0 && selector.IsReadyToWrite(self.controlling_term.Fd()) {
err = self.write() err = self.write_to_tty()
if err != nil { if err != nil {
return err return err
} }

View File

@ -73,9 +73,9 @@ const (
FULL_MOUSE_TRACKING FULL_MOUSE_TRACKING
) )
type TerminalState struct { type TerminalStateOptions struct {
alternate_screen, kitty_keyboard_mode bool alternate_screen, no_kitty_keyboard_mode bool
mouse_tracking MouseTracking mouse_tracking MouseTracking
} }
func set_modes(sb *strings.Builder, modes ...Mode) { func set_modes(sb *strings.Builder, modes ...Mode) {
@ -90,7 +90,7 @@ func reset_modes(sb *strings.Builder, modes ...Mode) {
} }
} }
func (self *TerminalState) SetStateEscapeCodes() []byte { func (self *TerminalStateOptions) SetStateEscapeCodes() []byte {
var sb strings.Builder var sb strings.Builder
sb.Grow(256) sb.Grow(256)
sb.WriteString(S7C1T) sb.WriteString(S7C1T)
@ -107,10 +107,10 @@ func (self *TerminalState) SetStateEscapeCodes() []byte {
set_modes(&sb, ALTERNATE_SCREEN) set_modes(&sb, ALTERNATE_SCREEN)
sb.WriteString(CLEAR_SCREEN) sb.WriteString(CLEAR_SCREEN)
} }
if self.kitty_keyboard_mode { if self.no_kitty_keyboard_mode {
sb.WriteString("\033[>31u")
} else {
sb.WriteString("\033[>u") sb.WriteString("\033[>u")
} else {
sb.WriteString("\033[>31u")
} }
if self.mouse_tracking != NO_MOUSE_TRACKING { if self.mouse_tracking != NO_MOUSE_TRACKING {
sb.WriteString(MOUSE_SGR_PIXEL_MODE.EscapeCodeToSet()) sb.WriteString(MOUSE_SGR_PIXEL_MODE.EscapeCodeToSet())
@ -126,7 +126,7 @@ func (self *TerminalState) SetStateEscapeCodes() []byte {
return []byte(sb.String()) return []byte(sb.String())
} }
func (self *TerminalState) ResetStateData() []byte { func (self *TerminalStateOptions) ResetStateEscapeCodes() []byte {
var sb strings.Builder var sb strings.Builder
sb.Grow(64) sb.Grow(64)
sb.WriteString("\033[<u") sb.WriteString("\033[<u")