mirror of https://github.com/liamg/aminal.git
Merge pull request #31 from liamg/fix-vim-bug
Fix vim bug and dodgy deletes
This commit is contained in:
commit
9bae0f4aa6
|
@ -19,6 +19,7 @@ type Buffer struct {
|
|||
bottomMargin uint // see DECSTBM docs - this is for scrollable regions
|
||||
replaceMode bool // overwrite character at cursor or insert new
|
||||
autoWrap bool
|
||||
dirty bool
|
||||
}
|
||||
|
||||
// NewBuffer creates a new terminal buffer
|
||||
|
@ -35,6 +36,14 @@ func NewBuffer(viewCols uint16, viewLines uint16, attr CellAttributes) *Buffer {
|
|||
return b
|
||||
}
|
||||
|
||||
func (buffer *Buffer) IsDirty() bool {
|
||||
if !buffer.dirty {
|
||||
return false
|
||||
}
|
||||
buffer.dirty = false
|
||||
return true
|
||||
}
|
||||
|
||||
func (buffer *Buffer) SetAutoWrap(enabled bool) {
|
||||
buffer.autoWrap = enabled
|
||||
}
|
||||
|
@ -132,23 +141,8 @@ func (buffer *Buffer) GetCell(viewCol uint16, viewRow uint16) *Cell {
|
|||
return &line.cells[viewCol]
|
||||
}
|
||||
|
||||
func (buffer *Buffer) AttachDisplayChangeHandler(handler chan bool) {
|
||||
if buffer.displayChangeHandlers == nil {
|
||||
buffer.displayChangeHandlers = []chan bool{}
|
||||
}
|
||||
|
||||
buffer.displayChangeHandlers = append(buffer.displayChangeHandlers, handler)
|
||||
}
|
||||
|
||||
func (buffer *Buffer) emitDisplayChange() {
|
||||
for _, channel := range buffer.displayChangeHandlers {
|
||||
go func(c chan bool) {
|
||||
select {
|
||||
case c <- true:
|
||||
default:
|
||||
}
|
||||
}(channel)
|
||||
}
|
||||
buffer.dirty = true
|
||||
}
|
||||
|
||||
// Column returns cursor column
|
||||
|
@ -219,7 +213,7 @@ func (buffer *Buffer) insertLine() {
|
|||
copy(out[0:], before)
|
||||
|
||||
pos := buffer.RawLine()
|
||||
for i := topIndex; i <= bottomIndex; i++ {
|
||||
for i := topIndex; i < bottomIndex; i++ {
|
||||
if i < pos {
|
||||
out[i] = buffer.lines[i]
|
||||
} else {
|
||||
|
@ -227,7 +221,7 @@ func (buffer *Buffer) insertLine() {
|
|||
}
|
||||
}
|
||||
|
||||
copy(out[bottomIndex:], after)
|
||||
copy(out[bottomIndex+1:], after)
|
||||
|
||||
out[pos] = newLine()
|
||||
buffer.lines = out
|
||||
|
@ -260,17 +254,18 @@ func (buffer *Buffer) Index() {
|
|||
|
||||
if uint(buffer.cursorY) < buffer.bottomMargin {
|
||||
buffer.cursorY++
|
||||
} else {
|
||||
|
||||
topIndex := buffer.convertViewLineToRawLine(uint16(buffer.topMargin))
|
||||
bottomIndex := buffer.convertViewLineToRawLine(uint16(buffer.bottomMargin))
|
||||
|
||||
for i := topIndex; i < bottomIndex; i++ {
|
||||
buffer.lines[i] = buffer.lines[i+1]
|
||||
}
|
||||
|
||||
buffer.lines[bottomIndex] = newLine()
|
||||
}
|
||||
|
||||
topIndex := buffer.convertViewLineToRawLine(uint16(buffer.topMargin))
|
||||
bottomIndex := buffer.convertViewLineToRawLine(uint16(buffer.bottomMargin))
|
||||
|
||||
for i := topIndex; i < bottomIndex; i++ {
|
||||
buffer.lines[i] = buffer.lines[i+1]
|
||||
}
|
||||
|
||||
buffer.lines[buffer.RawLine()] = newLine()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -289,17 +284,17 @@ func (buffer *Buffer) ReverseIndex() {
|
|||
|
||||
if uint(buffer.cursorY) > buffer.topMargin {
|
||||
buffer.cursorY--
|
||||
} else {
|
||||
|
||||
topIndex := buffer.convertViewLineToRawLine(uint16(buffer.topMargin))
|
||||
bottomIndex := buffer.convertViewLineToRawLine(uint16(buffer.bottomMargin))
|
||||
|
||||
for i := bottomIndex; i > topIndex; i-- {
|
||||
buffer.lines[i] = buffer.lines[i-1]
|
||||
}
|
||||
|
||||
buffer.lines[topIndex] = newLine()
|
||||
}
|
||||
|
||||
topIndex := buffer.convertViewLineToRawLine(uint16(buffer.topMargin))
|
||||
bottomIndex := buffer.convertViewLineToRawLine(uint16(buffer.bottomMargin))
|
||||
|
||||
for i := bottomIndex; i > topIndex; i-- {
|
||||
buffer.lines[i] = buffer.lines[i-1]
|
||||
}
|
||||
|
||||
buffer.lines[buffer.RawLine()] = newLine()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -520,10 +515,9 @@ func (buffer *Buffer) EraseLineFromCursor() {
|
|||
|
||||
if len(line.cells) > 0 {
|
||||
cx := buffer.cursorX
|
||||
if int(cx) >= len(line.cells) {
|
||||
return // nothing to delete
|
||||
if int(cx) < len(line.cells) {
|
||||
line.cells = line.cells[:buffer.cursorX]
|
||||
}
|
||||
line.cells = line.cells[:buffer.cursorX]
|
||||
}
|
||||
|
||||
max := int(buffer.ViewWidth()) - len(line.cells)
|
||||
|
@ -545,6 +539,15 @@ func (buffer *Buffer) EraseDisplay() {
|
|||
}
|
||||
}
|
||||
|
||||
func (buffer *Buffer) DeleteChars(n int) {
|
||||
defer buffer.emitDisplayChange()
|
||||
|
||||
line := buffer.getCurrentLine()
|
||||
before := line.cells[:buffer.cursorX]
|
||||
after := line.cells[int(buffer.cursorX)+n:]
|
||||
line.cells = append(before, after...)
|
||||
}
|
||||
|
||||
func (buffer *Buffer) EraseCharacters(n int) {
|
||||
defer buffer.emitDisplayChange()
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package buffer
|
|||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
|
@ -298,29 +297,6 @@ func TestCursorAttr(t *testing.T) {
|
|||
assert.Equal(t, &b.cursorAttr, b.CursorAttr())
|
||||
}
|
||||
|
||||
func TestAttachingHandlers(t *testing.T) {
|
||||
b := NewBuffer(80, 2, CellAttributes{})
|
||||
displayHandler := make(chan bool, 1)
|
||||
b.AttachDisplayChangeHandler(displayHandler)
|
||||
require.Equal(t, 1, len(b.displayChangeHandlers))
|
||||
assert.Equal(t, b.displayChangeHandlers[0], displayHandler)
|
||||
}
|
||||
|
||||
func TestEmitDisplayHandlers(t *testing.T) {
|
||||
b := NewBuffer(80, 2, CellAttributes{})
|
||||
displayHandler := make(chan bool, 1)
|
||||
b.AttachDisplayChangeHandler(displayHandler)
|
||||
b.emitDisplayChange()
|
||||
time.Sleep(time.Millisecond * 50)
|
||||
ok := false
|
||||
select {
|
||||
case <-displayHandler:
|
||||
ok = true
|
||||
default:
|
||||
}
|
||||
assert.True(t, ok)
|
||||
}
|
||||
|
||||
func TestCursorPositionQuerying(t *testing.T) {
|
||||
b := NewBuffer(80, 20, CellAttributes{})
|
||||
b.cursorX = 17
|
||||
|
|
|
@ -158,8 +158,6 @@ func (gui *GUI) key(w *glfw.Window, key glfw.Key, scancode int, action glfw.Acti
|
|||
if gui.terminal.IsApplicationCursorKeysModeEnabled() {
|
||||
gui.terminal.Write([]byte{
|
||||
0x1b,
|
||||
'O',
|
||||
0x1b,
|
||||
})
|
||||
} else {
|
||||
gui.terminal.Write([]byte{
|
||||
|
|
|
@ -28,7 +28,7 @@ var csiSequences = []csiMapping{
|
|||
csiMapping{id: 'l', handler: csiResetModeHandler, expectedParams: &expectedParams{min: 1, max: 1}, description: "Reset Mode (RM)"},
|
||||
csiMapping{id: 'm', handler: sgrSequenceHandler, description: "Character Attributes (SGR)"},
|
||||
csiMapping{id: 'n', handler: csiDeviceStatusReportHandler, description: "Device Status Report (DSR)"},
|
||||
csiMapping{id: 'r', handler: csiSetMarginsHandler, expectedParams: &expectedParams{min: 2, max: 2}, description: "Set Scrolling Region [top;bottom] (default = full size of window) (DECSTBM), VT100"},
|
||||
csiMapping{id: 'r', handler: csiSetMarginsHandler, expectedParams: &expectedParams{min: 0, max: 2}, description: "Set Scrolling Region [top;bottom] (default = full size of window) (DECSTBM), VT100"},
|
||||
csiMapping{id: 't', handler: csiWindowManipulation, description: "Window manipulation"},
|
||||
csiMapping{id: 'A', handler: csiCursorUpHandler, description: "Cursor Up Ps Times (default = 1) (CUU)"},
|
||||
csiMapping{id: 'B', handler: csiCursorDownHandler, description: "Cursor Down Ps Times (default = 1) (CUD)"},
|
||||
|
@ -77,8 +77,9 @@ CSI:
|
|||
if sequence.expectedParams != nil && (uint8(len(params)) < sequence.expectedParams.min || uint8(len(params)) > sequence.expectedParams.max) {
|
||||
continue
|
||||
}
|
||||
terminal.logger.Debugf("CSI 0x%02X (ESC[%s%s%s) %s", final, param, intermediate, string(final), sequence.description)
|
||||
x, y := terminal.ActiveBuffer().CursorColumn(), terminal.ActiveBuffer().CursorLine()
|
||||
err := sequence.handler(params, intermediate, terminal)
|
||||
terminal.logger.Debugf("CSI 0x%02X (ESC[%s%s%s) %s - %d,%d -> %d,%d", final, param, intermediate, string(final), sequence.description, x, y, terminal.ActiveBuffer().CursorColumn(), terminal.ActiveBuffer().CursorLine())
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -377,8 +378,7 @@ func csiDeleteHandler(params []string, intermediate string, terminal *Terminal)
|
|||
}
|
||||
}
|
||||
|
||||
terminal.ActiveBuffer().EraseCharacters(n)
|
||||
|
||||
terminal.ActiveBuffer().DeleteChars(n)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ func (terminal *Terminal) processInput(ctx context.Context, pty chan rune) {
|
|||
} else {
|
||||
//terminal.logger.Debugf("Received character 0x%X: %q", b, string(b))
|
||||
if b >= 0x20 {
|
||||
terminal.logger.Debugf("%c", b)
|
||||
//terminal.logger.Debugf("%c", b)
|
||||
terminal.ActiveBuffer().Write(b)
|
||||
} else {
|
||||
terminal.logger.Error("Non-readable rune received: 0x%X", b)
|
||||
|
|
|
@ -100,7 +100,7 @@ func (terminal *Terminal) SetBracketedPasteMode(enabled bool) {
|
|||
func (terminal *Terminal) CheckDirty() bool {
|
||||
d := terminal.isDirty
|
||||
terminal.isDirty = false
|
||||
return d
|
||||
return d || terminal.ActiveBuffer().IsDirty()
|
||||
}
|
||||
|
||||
func (terminal *Terminal) SetDirty() {
|
||||
|
@ -166,12 +166,6 @@ func (terminal *Terminal) GetCell(col uint16, row uint16) *buffer.Cell {
|
|||
return terminal.ActiveBuffer().GetCell(col, row)
|
||||
}
|
||||
|
||||
func (terminal *Terminal) AttachDisplayChangeHandler(handler chan bool) {
|
||||
for i := range terminal.buffers {
|
||||
terminal.buffers[i].AttachDisplayChangeHandler(handler)
|
||||
}
|
||||
}
|
||||
|
||||
func (terminal *Terminal) AttachTitleChangeHandler(handler chan bool) {
|
||||
terminal.titleHandlers = append(terminal.titleHandlers, handler)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue