From 006e6d53ea9a62d72594aee59c1f21ac1a66e030 Mon Sep 17 00:00:00 2001 From: Liam Galvin Date: Wed, 4 Jul 2018 17:39:50 +0100 Subject: [PATCH] more scape codes --- demo/{position.sh => CGI-A-F.sh} | 0 demo/CSI-J-0.sh | 17 +++++ demo/CSI-J-1.sh | 17 +++++ demo/CSI-J-2.sh | 17 +++++ demo/{clear.sh => CSI-K-0.sh} | 6 +- demo/CSI-K-1.sh | 17 +++++ demo/CSI-K-2.sh | 17 +++++ demo/{colour.sh => CSI-SGR.sh} | 0 terminal/escapes.go | 111 ++++++++++++++++++++----------- terminal/terminal.go | 1 + 10 files changed, 162 insertions(+), 41 deletions(-) rename demo/{position.sh => CGI-A-F.sh} (100%) create mode 100755 demo/CSI-J-0.sh create mode 100755 demo/CSI-J-1.sh create mode 100755 demo/CSI-J-2.sh rename demo/{clear.sh => CSI-K-0.sh} (78%) create mode 100755 demo/CSI-K-1.sh create mode 100755 demo/CSI-K-2.sh rename demo/{colour.sh => CSI-SGR.sh} (100%) diff --git a/demo/position.sh b/demo/CGI-A-F.sh similarity index 100% rename from demo/position.sh rename to demo/CGI-A-F.sh diff --git a/demo/CSI-J-0.sh b/demo/CSI-J-0.sh new file mode 100755 index 0000000..b7e17b1 --- /dev/null +++ b/demo/CSI-J-0.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo -n "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" + +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[0J" diff --git a/demo/CSI-J-1.sh b/demo/CSI-J-1.sh new file mode 100755 index 0000000..21f27a8 --- /dev/null +++ b/demo/CSI-J-1.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo -n "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" + +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[1J" diff --git a/demo/CSI-J-2.sh b/demo/CSI-J-2.sh new file mode 100755 index 0000000..ae7c328 --- /dev/null +++ b/demo/CSI-J-2.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo -n "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" + +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[2J" diff --git a/demo/clear.sh b/demo/CSI-K-0.sh similarity index 78% rename from demo/clear.sh rename to demo/CSI-K-0.sh index 6a691da..fb10fd8 100755 --- a/demo/clear.sh +++ b/demo/CSI-K-0.sh @@ -1,5 +1,7 @@ #!/bin/bash +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" @@ -12,6 +14,4 @@ echo -ne "\x1b[A" # up echo -ne "\x1b[D" # left echo -ne "\x1b[A" # up echo -ne "\x1b[D" # left -sleep 2 -echo -ne "\x1b[J0" - +echo -ne "\x1b[K" diff --git a/demo/CSI-K-1.sh b/demo/CSI-K-1.sh new file mode 100755 index 0000000..ba0f8c8 --- /dev/null +++ b/demo/CSI-K-1.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo -n "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" + +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[1K" diff --git a/demo/CSI-K-2.sh b/demo/CSI-K-2.sh new file mode 100755 index 0000000..453be0e --- /dev/null +++ b/demo/CSI-K-2.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" +echo -n "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" + +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[A" # up +echo -ne "\x1b[D" # left +echo -ne "\x1b[2K" diff --git a/demo/colour.sh b/demo/CSI-SGR.sh similarity index 100% rename from demo/colour.sh rename to demo/CSI-SGR.sh diff --git a/terminal/escapes.go b/terminal/escapes.go index 7cac613..b3fbe65 100644 --- a/terminal/escapes.go +++ b/terminal/escapes.go @@ -5,6 +5,17 @@ import ( "strings" ) +// Wish list here: http://invisible-island.net/xterm/ctlseqs/ctlseqs.html + +type TerminalCharSet int + +const ( + C0 TerminalCharSet = iota + C1 + C2 + C3 +) + func (terminal *Terminal) processInput(buffer chan rune) { // https://en.wikipedia.org/wiki/ANSI_escape_code @@ -136,7 +147,7 @@ func (terminal *Terminal) processInput(buffer chan rune) { if len(params) > 0 { var err error distance, err = strconv.Atoi(params[0]) - if err != nil { + if err != nil || params[0] == "" { distance = 1 } } @@ -149,20 +160,20 @@ func (terminal *Terminal) processInput(buffer chan rune) { if len(params) == 2 { var err error if params[0] != "" { - x, err = strconv.Atoi(string(params[0])) - if err != nil { - x = 1 - } - } - if params[1] != "" { - y, err = strconv.Atoi(string(params[y])) + y, err = strconv.Atoi(string(params[0])) if err != nil { y = 1 } } - terminal.position.Col = x - 1 - terminal.position.Line = y - 1 + if params[1] != "" { + x, err = strconv.Atoi(string(params[1])) + if err != nil { + x = 1 + } + } } + terminal.position.Col = x - 1 + terminal.position.Line = y - 1 case 'J': @@ -173,6 +184,18 @@ func (terminal *Terminal) processInput(buffer chan rune) { switch n { + case "0", "": + line := terminal.getBufferedLine(terminal.position.Line) + if line != nil { + line.Cells = line.Cells[:terminal.position.Col] + } + _, h := terminal.GetSize() + for i := terminal.position.Line + 1; i < h; i++ { + line := terminal.getBufferedLine(i) + if line != nil { + line.Cells = []Cell{} + } + } case "1": line := terminal.getBufferedLine(terminal.position.Line) if line != nil { @@ -189,19 +212,6 @@ func (terminal *Terminal) processInput(buffer chan rune) { } } - case "0", "": - line := terminal.getBufferedLine(terminal.position.Line) - if line != nil { - line.Cells = line.Cells[:terminal.position.Col] - } - _, h := terminal.GetSize() - for i := terminal.position.Line + 1; i < h; i++ { - line := terminal.getBufferedLine(i) - if line != nil { - line.Cells = []Cell{} - } - } - case "2": _, h := terminal.GetSize() for i := 0; i < h; i++ { @@ -210,12 +220,8 @@ func (terminal *Terminal) processInput(buffer chan rune) { line.Cells = []Cell{} } } - terminal.position.Col = 0 - terminal.position.Line = 0 case "3": terminal.lines = []Line{} - terminal.position.Col = 0 - terminal.position.Line = 0 default: terminal.logger.Errorf("Unknown CSI ED sequence: %s", n) @@ -228,6 +234,11 @@ func (terminal *Terminal) processInput(buffer chan rune) { } switch n { + case "0", "": + line := terminal.getBufferedLine(terminal.position.Line) + if line != nil { + line.Cells = line.Cells[:terminal.position.Col] + } case "1": line := terminal.getBufferedLine(terminal.position.Line) if line != nil { @@ -237,11 +248,6 @@ func (terminal *Terminal) processInput(buffer chan rune) { } } } - case "0", "": - line := terminal.getBufferedLine(terminal.position.Line) - if line != nil { - line.Cells = line.Cells[:terminal.position.Col] - } case "2": line := terminal.getBufferedLine(terminal.position.Line) if line != nil { @@ -355,7 +361,7 @@ func (terminal *Terminal) processInput(buffer chan rune) { terminal.logger.Errorf("Unknown SGR control sequence: (ESC[%s%s%s)", param, intermediate, string(final)) } - //terminal.logger.Debugf("SGR control sequence: (ESC[%s%s%s)", param, intermediate, string(final)) + terminal.logger.Debugf("SGR control sequence: (ESC[%s%s%s)", param, intermediate, string(final)) } default: @@ -371,7 +377,9 @@ func (terminal *Terminal) processInput(buffer chan rune) { default: terminal.logger.Errorf("Unknown CSI control sequence: 0x%02X (ESC[%s%s%s)", final, param, intermediate, string(final)) } + } + terminal.logger.Debugf("Received CSI control sequence: 0x%02X (ESC[%s%s%s)", final, param, intermediate, string(final)) case 0x5d: // OSC: Operating System Command b = <-buffer switch b { @@ -381,12 +389,11 @@ func (terminal *Terminal) processInput(buffer chan rune) { title := []rune{} for { b = <-buffer - if b == 0x07 { + if b == 0x07 || b == 0x5c { // 0x07 -> BELL, 0x5c -> ST (\) break } title = append(title, b) } - terminal.logger.Debugf("Terminal title set to: %s", string(title)) terminal.title = string(title) } else { terminal.logger.Errorf("Invalid OSC 0 control sequence: 0x%02X", b) @@ -396,10 +403,38 @@ func (terminal *Terminal) processInput(buffer chan rune) { } case 'c': terminal.logger.Errorf("RIS not yet supported") - case ')', '(': + case '(': b = <-buffer - // todo charset changes - //terminal.logger.Debugf("Ignoring character set control code )%s", string(b)) + switch b { + case 'A': //uk @todo handle these? + terminal.charSet = C0 + case 'B': //us + terminal.charSet = C0 + } + case ')': + b = <-buffer + switch b { + case 'A': //uk @todo handle these? + terminal.charSet = C1 + case 'B': //us + terminal.charSet = C1 + } + case '*': + b = <-buffer + switch b { + case 'A': //uk @todo handle these? + terminal.charSet = C2 + case 'B': //us + terminal.charSet = C2 + } + case '+': + b = <-buffer + switch b { + case 'A': //uk @todo handle these? + terminal.charSet = C3 + case 'B': //us + terminal.charSet = C3 + } case '>': // numeric char selection @todo case '=': diff --git a/terminal/terminal.go b/terminal/terminal.go index 4bf6fa8..a2a6b74 100644 --- a/terminal/terminal.go +++ b/terminal/terminal.go @@ -24,6 +24,7 @@ type Terminal struct { cellAttr CellAttributes defaultCellAttr CellAttributes cursorVisible bool + charSet TerminalCharSet } type Line struct {