Skip to content

Commit

Permalink
Complete handling of cursor movement
Browse files Browse the repository at this point in the history
  • Loading branch information
andydotxyz committed Mar 14, 2020
1 parent 9fc8904 commit 9da205a
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 14 deletions.
51 changes: 39 additions & 12 deletions escape.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ var currentFG, currentBG color.Color

func (t *Terminal) handleEscape(code string) {
switch code { // exact matches
case "H", ";H":
t.cursorCol = 0
t.cursorRow = 0
t.cursorMoved()
case "H", "f":
t.moveCursor(0, 0)
case "J":
t.clearScreenFromCursor()
case "2J":
t.clearScreen()
case "K":
Expand All @@ -28,18 +28,24 @@ func (t *Terminal) handleEscape(code string) {
default: // check mode (last letter) then match
message := code[:len(code)-1]
switch code[len(code)-1:] {
case "H":
case "A":
rows, _ := strconv.Atoi(message)
t.moveCursor(t.cursorRow-rows, t.cursorCol)
case "B":
rows, _ := strconv.Atoi(message)
t.moveCursor(t.cursorRow+rows, t.cursorCol)
case "C":
cols, _ := strconv.Atoi(message)
t.moveCursor(t.cursorRow, t.cursorCol-cols)
case "D":
cols, _ := strconv.Atoi(message)
t.moveCursor(t.cursorRow, t.cursorCol+cols)
case "H", "f":
parts := strings.Split(message, ";")
row, _ := strconv.Atoi(parts[0])
col, _ := strconv.Atoi(parts[1])

if row < len(t.content.Content) {
t.cursorRow = row
}
line := t.content.Row(t.cursorRow)
if col < len(line) {
t.cursorCol = col
}
t.moveCursor(row, col)
case "m":
if message == "" || message == "0" {
currentBG = nil
Expand Down Expand Up @@ -154,3 +160,24 @@ func (t *Terminal) clearScreen() {
func (t *Terminal) handleVT100(code string) {
log.Println("Unhandled VT100:", code)
}

func (t *Terminal) moveCursor(row, col int) {
if col < 0 {
col = 0
} else if col >= int(t.config.Columns) {
col = int(t.config.Columns) - 1
}

if row < 0 {
row = 0
} else if row >= int(t.config.Rows) {
row = int(t.config.Rows) - 1
}

t.cursorCol = col
t.cursorRow = row

if t.cursorMoved != nil {
t.cursorMoved()
}
}
47 changes: 45 additions & 2 deletions escape_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,54 @@ func TestEraseLine(t *testing.T) {

func TestCursorMove(t *testing.T) {
term := NewTerminal()
term.config.Columns = 5
term.config.Rows = 2
term.handleOutput([]byte("Hello"))
assert.Equal(t, 0, term.cursorRow)
assert.Equal(t, 5, term.cursorCol)

term.handleEscape("0;2H")
term.handleEscape("0;3H")
assert.Equal(t, 0, term.cursorRow)
assert.Equal(t, 2, term.cursorCol)
assert.Equal(t, 3, term.cursorCol)

term.handleEscape("2C")
assert.Equal(t, 0, term.cursorRow)
assert.Equal(t, 1, term.cursorCol)

term.handleEscape("2D")
assert.Equal(t, 0, term.cursorRow)
assert.Equal(t, 3, term.cursorCol)

term.handleEscape("1B")
assert.Equal(t, 1, term.cursorRow)
assert.Equal(t, 3, term.cursorCol)

term.handleEscape("1A")
assert.Equal(t, 0, term.cursorRow)
assert.Equal(t, 3, term.cursorCol)
}

func TestCursorMove_Overflow(t *testing.T) {
term := NewTerminal()
term.config.Columns = 2
term.config.Rows = 2
term.handleEscape("2;2H")
assert.Equal(t, 1, term.cursorRow)
assert.Equal(t, 1, term.cursorCol)

term.handleEscape("2C")
assert.Equal(t, 1, term.cursorRow)
assert.Equal(t, 0, term.cursorCol)

term.handleEscape("5D")
assert.Equal(t, 1, term.cursorRow)
assert.Equal(t, 1, term.cursorCol)

term.handleEscape("5A")
assert.Equal(t, 0, term.cursorRow)
assert.Equal(t, 1, term.cursorCol)

term.handleEscape("4B")
assert.Equal(t, 1, term.cursorRow)
assert.Equal(t, 1, term.cursorCol)
}

0 comments on commit 9da205a

Please sign in to comment.