From baa7d4b6cdb72e86aca84f11a9e466cffc8b7db7 Mon Sep 17 00:00:00 2001 From: Liam Galvin Date: Sat, 4 Aug 2018 21:11:03 +0100 Subject: [PATCH] fix --- gui/gui.go | 5 ++- terminal/ansi.go | 25 ++--------- terminal/csi.go | 3 +- terminal/delete.go | 39 ++++++++++++++++++ terminal/delete_test.go | 91 +++++++++++++++++++++++++++++++++++++++++ terminal/osc.go | 27 ++++++++++++ 6 files changed, 164 insertions(+), 26 deletions(-) create mode 100644 terminal/delete.go create mode 100644 terminal/delete_test.go create mode 100644 terminal/osc.go diff --git a/gui/gui.go b/gui/gui.go index 80375f8..54e1610 100644 --- a/gui/gui.go +++ b/gui/gui.go @@ -265,7 +265,8 @@ func (gui *GUI) Render() error { gui.updateTexts() // Render the string. - gui.window.SetTitle(gui.terminal.GetTitle()) + // @todo uncommentbut dont run all of the time... - perhaps use onTitleChange event from terminal? + //gui.window.SetTitle(gui.terminal.GetTitle()) //gl.ClearColor(0.5, 0.5, 0.5, 1.0) gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) @@ -284,7 +285,7 @@ func (gui *GUI) Render() error { } gui.font.SetColor(1, 0.2, 0.2, 0.5) - gui.font.Printf(50, 50, 2, "Position=%#v", gui.terminal.GetPosition()) + gui.font.Printf(100, 300, 1.5, "%#v %s", gui.terminal.GetPosition(), gui.terminal.GetLineString()) } diff --git a/terminal/ansi.go b/terminal/ansi.go index cc8c3b2..0433363 100644 --- a/terminal/ansi.go +++ b/terminal/ansi.go @@ -1,7 +1,8 @@ package terminal var ansiSequenceMap = map[rune]escapeSequenceHandler{ - '[': csiHandler, + '[': csiHandler, + 0x5d: oscHandler, } func ansiHandler(buffer chan rune, terminal *Terminal) error { @@ -14,27 +15,7 @@ func ansiHandler(buffer chan rune, terminal *Terminal) error { } switch b { - case 0x5d: // OSC: Operating System Command - b = <-buffer - switch b { - case rune('0'): - b = <-buffer - if b == rune(';') { - title := []rune{} - for { - b = <-buffer - if b == 0x07 || b == 0x5c { // 0x07 -> BELL, 0x5c -> ST (\) - break - } - title = append(title, b) - } - terminal.title = string(title) - } else { - terminal.logger.Errorf("Invalid OSC 0 control sequence: 0x%02X", b) - } - default: - terminal.logger.Errorf("Unknown OSC control sequence: 0x%02X", b) - } + case 'c': terminal.logger.Errorf("RIS not yet supported") case '(': diff --git a/terminal/csi.go b/terminal/csi.go index 526edfb..01c3951 100644 --- a/terminal/csi.go +++ b/terminal/csi.go @@ -261,8 +261,7 @@ CSI: } } - // @todo delete n cells at position - _ = n + _ = terminal.delete(n) default: switch param + intermediate + string(final) { diff --git a/terminal/delete.go b/terminal/delete.go new file mode 100644 index 0000000..d46da82 --- /dev/null +++ b/terminal/delete.go @@ -0,0 +1,39 @@ +package terminal + +import ( + "fmt" +) + +func (terminal *Terminal) delete(n int) error { + if len(terminal.lines) <= terminal.position.Line { + return fmt.Errorf("Cannot delete character at current position - line does not exist") + } + line := &terminal.lines[terminal.position.Line] + + if terminal.position.Col >= len(line.Cells) { + return fmt.Errorf("Line not long enough to delete anything") + } + + for terminal.position.Col+n > len(line.Cells) { + n-- + } + after := line.Cells[terminal.position.Col+n:] + before := line.Cells[:terminal.position.Col] + + line.Cells = append(before, after...) + + // @todo rewrap lines here + // so if line overflows and then we delete characters from beginnign of the line + + return nil +} + +// @todo remove this debug func +func (terminal *Terminal) GetLineString() string { + if len(terminal.lines) <= terminal.position.Line { + return "" + } + line := &terminal.lines[terminal.position.Line] + + return line.String() +} diff --git a/terminal/delete_test.go b/terminal/delete_test.go new file mode 100644 index 0000000..250490b --- /dev/null +++ b/terminal/delete_test.go @@ -0,0 +1,91 @@ +package terminal + +import "testing" + +func TestDelete(t *testing.T) { + terminal := &Terminal{ + lines: []Line{ + { + Cells: []Cell{ + { + r: 'a', + }, + { + r: 'b', + }, + { + r: 'c', + }, + { + r: 'd', + }, + { + r: 'e', + }, + }, + }, + { + Cells: []Cell{ + { + r: 'f', + }, + { + r: 'g', + }, + { + r: 'h', + }, + { + r: 'i', + }, + { + r: 'j', + }, + }, + }, + { + Cells: []Cell{ + { + r: 'k', + }, + { + r: 'l', + }, + { + r: 'm', + }, + { + r: 'n', + }, + { + r: 'o', + }, + }, + }, + }, + } + + terminal.position = Position{ + Col: 3, + Line: 1, + } + + if err := terminal.delete(2); err != nil { + t.Errorf("Delete failed: %s", err) + } + + if len(terminal.lines) != 3 { + t.Errorf("No. of lines has changed by deleting characters") + } + + if "fgh" != terminal.lines[1].String() { + t.Errorf("Unexpected string after deletion: %s", terminal.lines[1].String()) + } + if "abcde" != terminal.lines[0].String() { + t.Errorf("Unexpected string after deletion: %s", terminal.lines[0].String()) + } + + if "klmno" != terminal.lines[2].String() { + t.Errorf("Unexpected string after deletion: %s", terminal.lines[2].String()) + } +} diff --git a/terminal/osc.go b/terminal/osc.go new file mode 100644 index 0000000..ca75847 --- /dev/null +++ b/terminal/osc.go @@ -0,0 +1,27 @@ +package terminal + +import "fmt" + +func oscHandler(buffer chan rune, terminal *Terminal) error { + b := <-buffer + switch b { + case rune('0'): + b = <-buffer + if b == rune(';') { + title := []rune{} + for { + b = <-buffer + if b == 0x07 || b == 0x5c { // 0x07 -> BELL, 0x5c -> ST (\) + break + } + title = append(title, b) + } + terminal.title = string(title) + } else { + return fmt.Errorf("Invalid OSC 0 control sequence: 0x%02X", b) + } + default: + return fmt.Errorf("Unknown OSC control sequence: 0x%02X", b) + } + return nil +}