mirror of https://github.com/liamg/aminal.git
alt buffer
This commit is contained in:
parent
3ac0d62d72
commit
6d10ffd17c
|
@ -86,15 +86,15 @@ func (buffer *Buffer) CursorAttr() *CellAttributes {
|
||||||
return &buffer.cursorAttr
|
return &buffer.cursorAttr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (buffer *Buffer) GetCell(viewCol int, viewRow int) *Cell {
|
func (buffer *Buffer) GetCell(viewCol uint16, viewRow uint16) *Cell {
|
||||||
|
|
||||||
rawLine := buffer.convertViewLineToRawLine(uint16(viewRow))
|
rawLine := buffer.convertViewLineToRawLine(viewRow)
|
||||||
|
|
||||||
if viewCol < 0 || rawLine < 0 || int(rawLine) >= len(buffer.lines) {
|
if viewCol < 0 || rawLine < 0 || int(rawLine) >= len(buffer.lines) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
line := &buffer.lines[rawLine]
|
line := &buffer.lines[rawLine]
|
||||||
if viewCol >= len(line.cells) {
|
if int(viewCol) >= len(line.cells) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &line.cells[viewCol]
|
return &line.cells[viewCol]
|
||||||
|
@ -245,6 +245,23 @@ func (buffer *Buffer) Backspace() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (buffer *Buffer) BackspaceDelete() {
|
||||||
|
|
||||||
|
if buffer.cursorX == 0 {
|
||||||
|
line := buffer.getCurrentLine()
|
||||||
|
if line.wrapped {
|
||||||
|
buffer.MovePosition(int16(buffer.Width()-1), -1)
|
||||||
|
buffer.GetCell(buffer.cursorX, buffer.cursorY).erase()
|
||||||
|
} else {
|
||||||
|
//@todo ring bell or whatever
|
||||||
|
fmt.Println("BELL?")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer.MovePosition(-1, 0)
|
||||||
|
buffer.GetCell(buffer.cursorX, buffer.cursorY).erase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (buffer *Buffer) CarriageReturn() {
|
func (buffer *Buffer) CarriageReturn() {
|
||||||
defer buffer.emitDisplayChange()
|
defer buffer.emitDisplayChange()
|
||||||
buffer.cursorX = 0
|
buffer.cursorX = 0
|
||||||
|
@ -425,6 +442,7 @@ func (buffer *Buffer) EraseDisplayToCursor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (buffer *Buffer) ResizeView(width uint16, height uint16) {
|
func (buffer *Buffer) ResizeView(width uint16, height uint16) {
|
||||||
|
|
||||||
defer buffer.emitDisplayChange()
|
defer buffer.emitDisplayChange()
|
||||||
|
|
||||||
if buffer.viewHeight == 0 {
|
if buffer.viewHeight == 0 {
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
mode: set
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:17.59,25.2 3 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:28.45,30.2 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:33.43,35.2 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:38.40,40.40 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:43.2,43.75 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:40.40,42.3 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:47.38,49.2 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:51.42,53.2 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:55.36,57.2 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:59.43,61.2 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:63.53,64.49 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:64.49,66.3 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:70.44,71.26 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:71.26,73.16 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:77.3,78.53 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:81.3,84.35 4 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:73.16,75.12 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:78.53,80.4 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:88.49,90.46 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:90.46,92.3 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:92.8,93.44 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:93.44,98.4 4 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:98.9,100.50 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:100.50,105.5 4 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:105.10,106.58 1 0
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:107.5,108.26 2 0
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:114.33,116.25 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:124.2,124.43 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:116.25,118.19 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:118.19,121.4 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:124.43,127.3 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:127.8,130.3 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:133.54,135.33 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:139.2,139.33 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:143.2,143.86 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:135.33,137.3 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:139.33,141.3 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:146.60,147.31 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:151.2,151.33 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:155.2,156.23 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:147.31,150.3 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:151.33,154.3 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:159.48,161.80 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:166.2,166.14 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:161.80,162.38 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:162.38,164.4 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:171.31,172.48 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:175.2,175.26 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:172.48,174.3 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/buffer.go:178.63,183.2 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/cell.go:20.21,22.2 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/cell.go:24.35,27.2 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/line.go:8.21,13.2 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/line.go:15.44,17.2 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/line.go:19.35,21.34 2 1
|
|
||||||
gitlab.com/liamg/raft/buffer/line.go:24.2,24.22 1 1
|
|
||||||
gitlab.com/liamg/raft/buffer/line.go:21.34,23.3 1 1
|
|
10
gui/gui.go
10
gui/gui.go
|
@ -75,7 +75,7 @@ func (gui *GUI) glfwScrollCallback(w *glfw.Window, xoff float64, yoff float64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gui *GUI) getTermSize() (int, int) {
|
func (gui *GUI) getTermSize() (uint, uint) {
|
||||||
if gui.renderer == nil {
|
if gui.renderer == nil {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
@ -201,14 +201,14 @@ func (gui *GUI) Render() error {
|
||||||
lines := gui.terminal.GetVisibleLines()
|
lines := gui.terminal.GetVisibleLines()
|
||||||
for y := 0; y < len(lines); y++ {
|
for y := 0; y < len(lines); y++ {
|
||||||
for x, cell := range lines[y].Cells() {
|
for x, cell := range lines[y].Cells() {
|
||||||
gui.renderer.DrawCell(cell, x, y)
|
gui.renderer.DrawCell(cell, uint(x), uint(y))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if gui.terminal.Modes().ShowCursor {
|
if gui.terminal.Modes().ShowCursor {
|
||||||
cx := int(gui.terminal.GetLogicalCursorX())
|
cx := uint(gui.terminal.GetLogicalCursorX())
|
||||||
cy := int(gui.terminal.GetLogicalCursorY())
|
cy := uint(gui.terminal.GetLogicalCursorY())
|
||||||
cy = int(cy) + int(gui.terminal.GetScrollOffset())
|
cy = cy + uint(gui.terminal.GetScrollOffset())
|
||||||
gui.renderer.DrawCursor(cx, cy, gui.config.ColourScheme.Cursor)
|
gui.renderer.DrawCursor(cx, cy, gui.config.ColourScheme.Cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ import (
|
||||||
|
|
||||||
type Renderer interface {
|
type Renderer interface {
|
||||||
SetArea(areaX int, areaY int, areaWidth int, areaHeight int)
|
SetArea(areaX int, areaY int, areaWidth int, areaHeight int)
|
||||||
DrawCell(cell buffer.Cell, col int, row int)
|
DrawCell(cell buffer.Cell, col uint, row uint)
|
||||||
DrawCursor(col int, row int, colour config.Colour)
|
DrawCursor(col uint, row uint, colour config.Colour)
|
||||||
GetTermSize() (int, int)
|
GetTermSize() (uint, uint)
|
||||||
}
|
}
|
||||||
|
|
||||||
type OpenGLRenderer struct {
|
type OpenGLRenderer struct {
|
||||||
|
@ -27,10 +27,10 @@ type OpenGLRenderer struct {
|
||||||
cellWidth float32
|
cellWidth float32
|
||||||
cellHeight float32
|
cellHeight float32
|
||||||
verticalCellPadding float32
|
verticalCellPadding float32
|
||||||
termCols int
|
termCols uint
|
||||||
termRows int
|
termRows uint
|
||||||
cellPositions map[[2]int][2]float32
|
cellPositions map[[2]uint][2]float32
|
||||||
rectangles map[[2]int]*rectangle
|
rectangles map[[2]uint]*rectangle
|
||||||
config config.Config
|
config config.Config
|
||||||
colourAttr uint32
|
colourAttr uint32
|
||||||
program uint32
|
program uint32
|
||||||
|
@ -124,8 +124,8 @@ func NewOpenGLRenderer(config config.Config, font *glfont.Font, fontScale int32,
|
||||||
areaX: areaX,
|
areaX: areaX,
|
||||||
areaY: areaY,
|
areaY: areaY,
|
||||||
fontScale: fontScale,
|
fontScale: fontScale,
|
||||||
cellPositions: map[[2]int][2]float32{},
|
cellPositions: map[[2]uint][2]float32{},
|
||||||
rectangles: map[[2]int]*rectangle{},
|
rectangles: map[[2]uint]*rectangle{},
|
||||||
config: config,
|
config: config,
|
||||||
colourAttr: colourAttr,
|
colourAttr: colourAttr,
|
||||||
program: program,
|
program: program,
|
||||||
|
@ -134,7 +134,7 @@ func NewOpenGLRenderer(config config.Config, font *glfont.Font, fontScale int32,
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *OpenGLRenderer) GetTermSize() (int, int) {
|
func (r *OpenGLRenderer) GetTermSize() (uint, uint) {
|
||||||
return r.termCols, r.termRows
|
return r.termCols, r.termRows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,31 +156,31 @@ func (r *OpenGLRenderer) SetFont(font *glfont.Font) { // @todo check for monospa
|
||||||
r.verticalCellPadding = (0.25 * float32(r.fontScale))
|
r.verticalCellPadding = (0.25 * float32(r.fontScale))
|
||||||
r.cellWidth = font.Width(1, "X")
|
r.cellWidth = font.Width(1, "X")
|
||||||
r.cellHeight = font.Height(1, "X") + (r.verticalCellPadding * 2) // vertical padding
|
r.cellHeight = font.Height(1, "X") + (r.verticalCellPadding * 2) // vertical padding
|
||||||
r.termCols = int(math.Floor(float64(float32(r.areaWidth) / r.cellWidth)))
|
r.termCols = uint(math.Floor(float64(float32(r.areaWidth) / r.cellWidth)))
|
||||||
r.termRows = int(math.Floor(float64(float32(r.areaHeight) / r.cellHeight)))
|
r.termRows = uint(math.Floor(float64(float32(r.areaHeight) / r.cellHeight)))
|
||||||
r.calculatePositions()
|
r.calculatePositions()
|
||||||
r.generateRectangles()
|
r.generateRectangles()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *OpenGLRenderer) calculatePositions() {
|
func (r *OpenGLRenderer) calculatePositions() {
|
||||||
for line := 0; line < r.termRows; line++ {
|
for line := uint(0); line < r.termRows; line++ {
|
||||||
for col := 0; col < r.termCols; col++ {
|
for col := uint(0); col < r.termCols; col++ {
|
||||||
// rounding to whole pixels makes everything nice
|
// rounding to whole pixels makes everything nice
|
||||||
x := float32(math.Round(float64((float32(col) * r.cellWidth))))
|
x := float32(math.Round(float64((float32(col) * r.cellWidth))))
|
||||||
y := float32(math.Round(float64(
|
y := float32(math.Round(float64(
|
||||||
(float32(line) * r.cellHeight) + (r.cellHeight / 2) + r.verticalCellPadding,
|
(float32(line) * r.cellHeight) + (r.cellHeight / 2) + r.verticalCellPadding,
|
||||||
)))
|
)))
|
||||||
r.cellPositions[[2]int{col, line}] = [2]float32{x, y}
|
r.cellPositions[[2]uint{col, line}] = [2]float32{x, y}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *OpenGLRenderer) generateRectangles() {
|
func (r *OpenGLRenderer) generateRectangles() {
|
||||||
gl.UseProgram(r.program)
|
gl.UseProgram(r.program)
|
||||||
for line := 0; line < r.termRows; line++ {
|
for line := uint(0); line < r.termRows; line++ {
|
||||||
for col := 0; col < r.termCols; col++ {
|
for col := uint(0); col < r.termCols; col++ {
|
||||||
|
|
||||||
rect, ok := r.rectangles[[2]int{col, line}]
|
rect, ok := r.rectangles[[2]uint{col, line}]
|
||||||
if ok {
|
if ok {
|
||||||
rect.Free()
|
rect.Free()
|
||||||
}
|
}
|
||||||
|
@ -188,14 +188,14 @@ func (r *OpenGLRenderer) generateRectangles() {
|
||||||
// rounding to whole pixels makes everything nice
|
// rounding to whole pixels makes everything nice
|
||||||
x := float32(float64((float32(col) * r.cellWidth)))
|
x := float32(float64((float32(col) * r.cellWidth)))
|
||||||
y := float32(float64((float32(line) * r.cellHeight) + (r.cellHeight)))
|
y := float32(float64((float32(line) * r.cellHeight) + (r.cellHeight)))
|
||||||
r.rectangles[[2]int{col, line}] = r.newRectangle(x, y, r.colourAttr)
|
r.rectangles[[2]uint{col, line}] = r.newRectangle(x, y, r.colourAttr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *OpenGLRenderer) DrawCursor(col int, row int, colour config.Colour) {
|
func (r *OpenGLRenderer) DrawCursor(col uint, row uint, colour config.Colour) {
|
||||||
|
|
||||||
rect, ok := r.rectangles[[2]int{col, row}]
|
rect, ok := r.rectangles[[2]uint{col, row}]
|
||||||
if !ok { // probably trying to draw during resize - perhaps add a mutex?
|
if !ok { // probably trying to draw during resize - perhaps add a mutex?
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,7 @@ func (r *OpenGLRenderer) DrawCursor(col int, row int, colour config.Colour) {
|
||||||
//gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
|
//gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *OpenGLRenderer) DrawCell(cell buffer.Cell, col int, row int) {
|
func (r *OpenGLRenderer) DrawCell(cell buffer.Cell, col uint, row uint) {
|
||||||
|
|
||||||
if cell.Attr().Hidden || (cell.Rune() == 0x00) {
|
if cell.Attr().Hidden || (cell.Rune() == 0x00) {
|
||||||
return
|
return
|
||||||
|
@ -235,7 +235,7 @@ func (r *OpenGLRenderer) DrawCell(cell buffer.Cell, col int, row int) {
|
||||||
bg = cell.Bg()
|
bg = cell.Bg()
|
||||||
}
|
}
|
||||||
|
|
||||||
pos, ok := r.cellPositions[[2]int{col, row}]
|
pos, ok := r.cellPositions[[2]uint{col, row}]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Missing position data for cell at %d,%d", col, row))
|
panic(fmt.Sprintf("Missing position data for cell at %d,%d", col, row))
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ func (r *OpenGLRenderer) DrawCell(cell buffer.Cell, col int, row int) {
|
||||||
// don't bother rendering rectangles that are the same colour as the background
|
// don't bother rendering rectangles that are the same colour as the background
|
||||||
if bg != r.config.ColourScheme.Background {
|
if bg != r.config.ColourScheme.Background {
|
||||||
|
|
||||||
rect, ok := r.rectangles[[2]int{col, row}]
|
rect, ok := r.rectangles[[2]uint{col, row}]
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(fmt.Sprintf("Missing rectangle data for cell at %d,%d", col, row))
|
panic(fmt.Sprintf("Missing rectangle data for cell at %d,%d", col, row))
|
||||||
}
|
}
|
||||||
|
|
2
main.go
2
main.go
|
@ -84,6 +84,8 @@ func main() {
|
||||||
// parse this
|
// parse this
|
||||||
conf := getConfig()
|
conf := getConfig()
|
||||||
|
|
||||||
|
os.Setenv("TERM", "xterm-256color")
|
||||||
|
|
||||||
logger, err := getLogger(conf)
|
logger, err := getLogger(conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to create logger: %s\n", err)
|
fmt.Printf("Failed to create logger: %s\n", err)
|
||||||
|
|
|
@ -15,36 +15,36 @@ var ansiSequenceMap = map[rune]escapeSequenceHandler{
|
||||||
func indexHandler(buffer chan rune, terminal *Terminal) error {
|
func indexHandler(buffer chan rune, terminal *Terminal) error {
|
||||||
// @todo is thus right?
|
// @todo is thus right?
|
||||||
// "This sequence causes the active position to move downward one line without changing the column position. If the active position is at the bottom margin, a scroll up is performed."
|
// "This sequence causes the active position to move downward one line without changing the column position. If the active position is at the bottom margin, a scroll up is performed."
|
||||||
if terminal.buffer.CursorLine() == terminal.buffer.ViewHeight()-1 {
|
if terminal.ActiveBuffer().CursorLine() == terminal.ActiveBuffer().ViewHeight()-1 {
|
||||||
terminal.buffer.NewLine()
|
terminal.ActiveBuffer().NewLine()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
terminal.buffer.MovePosition(0, 1)
|
terminal.ActiveBuffer().MovePosition(0, 1)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func reverseIndexHandler(buffer chan rune, terminal *Terminal) error {
|
func reverseIndexHandler(buffer chan rune, terminal *Terminal) error {
|
||||||
terminal.buffer.MovePosition(0, -1)
|
terminal.ActiveBuffer().MovePosition(0, -1)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveCursorHandler(buffer chan rune, terminal *Terminal) error {
|
func saveCursorHandler(buffer chan rune, terminal *Terminal) error {
|
||||||
terminal.buffer.SaveCursor()
|
terminal.ActiveBuffer().SaveCursor()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func restoreCursorHandler(buffer chan rune, terminal *Terminal) error {
|
func restoreCursorHandler(buffer chan rune, terminal *Terminal) error {
|
||||||
terminal.buffer.RestoreCursor()
|
terminal.ActiveBuffer().RestoreCursor()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ansiHandler(buffer chan rune, terminal *Terminal) error {
|
func ansiHandler(pty chan rune, terminal *Terminal) error {
|
||||||
// if the byte is an escape character, read the next byte to determine which one
|
// if the byte is an escape character, read the next byte to determine which one
|
||||||
b := <-buffer
|
b := <-pty
|
||||||
|
|
||||||
handler, ok := ansiSequenceMap[b]
|
handler, ok := ansiSequenceMap[b]
|
||||||
if ok {
|
if ok {
|
||||||
return handler(buffer, terminal)
|
return handler(pty, terminal)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch b {
|
switch b {
|
||||||
|
@ -52,7 +52,7 @@ func ansiHandler(buffer chan rune, terminal *Terminal) error {
|
||||||
case 'c':
|
case 'c':
|
||||||
terminal.logger.Errorf("RIS not yet supported")
|
terminal.logger.Errorf("RIS not yet supported")
|
||||||
case '(':
|
case '(':
|
||||||
b = <-buffer
|
b = <-pty
|
||||||
switch b {
|
switch b {
|
||||||
case 'A': //uk @todo handle these?
|
case 'A': //uk @todo handle these?
|
||||||
//terminal.charSet = C0
|
//terminal.charSet = C0
|
||||||
|
@ -60,7 +60,7 @@ func ansiHandler(buffer chan rune, terminal *Terminal) error {
|
||||||
//terminal.charSet = C0
|
//terminal.charSet = C0
|
||||||
}
|
}
|
||||||
case ')':
|
case ')':
|
||||||
b = <-buffer
|
b = <-pty
|
||||||
switch b {
|
switch b {
|
||||||
case 'A': //uk @todo handle these?
|
case 'A': //uk @todo handle these?
|
||||||
//terminal.charSet = C1
|
//terminal.charSet = C1
|
||||||
|
@ -68,7 +68,7 @@ func ansiHandler(buffer chan rune, terminal *Terminal) error {
|
||||||
//terminal.charSet = C1
|
//terminal.charSet = C1
|
||||||
}
|
}
|
||||||
case '*':
|
case '*':
|
||||||
b = <-buffer
|
b = <-pty
|
||||||
switch b {
|
switch b {
|
||||||
case 'A': //uk @todo handle these?
|
case 'A': //uk @todo handle these?
|
||||||
//terminal.charSet = C2
|
//terminal.charSet = C2
|
||||||
|
@ -76,7 +76,7 @@ func ansiHandler(buffer chan rune, terminal *Terminal) error {
|
||||||
//terminal.charSet = C2
|
//terminal.charSet = C2
|
||||||
}
|
}
|
||||||
case '+':
|
case '+':
|
||||||
b = <-buffer
|
b = <-pty
|
||||||
switch b {
|
switch b {
|
||||||
case 'A': //uk @todo handle these?
|
case 'A': //uk @todo handle these?
|
||||||
//terminal.charSet = C3
|
//terminal.charSet = C3
|
||||||
|
@ -90,7 +90,7 @@ func ansiHandler(buffer chan rune, terminal *Terminal) error {
|
||||||
case '?':
|
case '?':
|
||||||
pm := ""
|
pm := ""
|
||||||
for {
|
for {
|
||||||
b = <-buffer
|
b = <-pty
|
||||||
switch b {
|
switch b {
|
||||||
case 'h':
|
case 'h':
|
||||||
switch pm {
|
switch pm {
|
||||||
|
|
|
@ -22,10 +22,28 @@ func csiSetMode(modeStr string, enabled bool, terminal *Terminal) error {
|
||||||
switch modeStr {
|
switch modeStr {
|
||||||
case "?1":
|
case "?1":
|
||||||
terminal.modes.ApplicationCursorKeys = enabled
|
terminal.modes.ApplicationCursorKeys = enabled
|
||||||
case "?12":
|
case "?12", "?13":
|
||||||
terminal.modes.BlinkingCursor = enabled
|
terminal.modes.BlinkingCursor = enabled
|
||||||
case "?25":
|
case "?25":
|
||||||
terminal.modes.ShowCursor = enabled
|
terminal.modes.ShowCursor = enabled
|
||||||
|
case "?47", "?1047":
|
||||||
|
if enabled {
|
||||||
|
terminal.UseAltBuffer()
|
||||||
|
} else {
|
||||||
|
terminal.UseMainBuffer()
|
||||||
|
}
|
||||||
|
case "?1048":
|
||||||
|
if enabled {
|
||||||
|
terminal.ActiveBuffer().SaveCursor()
|
||||||
|
} else {
|
||||||
|
terminal.ActiveBuffer().RestoreCursor()
|
||||||
|
}
|
||||||
|
case "?1049":
|
||||||
|
if enabled {
|
||||||
|
terminal.UseAltBuffer()
|
||||||
|
} else {
|
||||||
|
terminal.UseMainBuffer()
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unsupported CSI %sl code", modeStr)
|
return fmt.Errorf("Unsupported CSI %sl code", modeStr)
|
||||||
}
|
}
|
||||||
|
@ -43,7 +61,7 @@ func csiEraseCharactersHandler(params []string, intermediate string, terminal *T
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal.buffer.EraseCharacters(count)
|
terminal.ActiveBuffer().EraseCharacters(count)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -71,7 +89,7 @@ func csiLinePositionAbsolute(params []string, intermediate string, terminal *Ter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal.buffer.SetPosition(uint16(col), terminal.buffer.CursorLine())
|
terminal.ActiveBuffer().SetPosition(uint16(col), terminal.ActiveBuffer().CursorLine())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -79,7 +97,7 @@ func csiLinePositionAbsolute(params []string, intermediate string, terminal *Ter
|
||||||
type csiSequenceHandler func(params []string, intermediate string, terminal *Terminal) error
|
type csiSequenceHandler func(params []string, intermediate string, terminal *Terminal) error
|
||||||
|
|
||||||
// CSI: Control Sequence Introducer [
|
// CSI: Control Sequence Introducer [
|
||||||
func csiHandler(buffer chan rune, terminal *Terminal) error {
|
func csiHandler(pty chan rune, terminal *Terminal) error {
|
||||||
var final rune
|
var final rune
|
||||||
var b rune
|
var b rune
|
||||||
var err error
|
var err error
|
||||||
|
@ -87,7 +105,7 @@ func csiHandler(buffer chan rune, terminal *Terminal) error {
|
||||||
intermediate := ""
|
intermediate := ""
|
||||||
CSI:
|
CSI:
|
||||||
for {
|
for {
|
||||||
b = <-buffer
|
b = <-pty
|
||||||
switch true {
|
switch true {
|
||||||
case b >= 0x30 && b <= 0x3F:
|
case b >= 0x30 && b <= 0x3F:
|
||||||
param = param + string(b)
|
param = param + string(b)
|
||||||
|
@ -117,7 +135,7 @@ CSI:
|
||||||
distance = 1
|
distance = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
terminal.buffer.MovePosition(0, -int16(distance))
|
terminal.ActiveBuffer().MovePosition(0, -int16(distance))
|
||||||
case 'B':
|
case 'B':
|
||||||
distance := 1
|
distance := 1
|
||||||
if len(params) > 0 {
|
if len(params) > 0 {
|
||||||
|
@ -128,7 +146,7 @@ CSI:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal.buffer.MovePosition(0, int16(distance))
|
terminal.ActiveBuffer().MovePosition(0, int16(distance))
|
||||||
case 'C':
|
case 'C':
|
||||||
|
|
||||||
distance := 1
|
distance := 1
|
||||||
|
@ -140,7 +158,7 @@ CSI:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal.buffer.MovePosition(int16(distance), 0)
|
terminal.ActiveBuffer().MovePosition(int16(distance), 0)
|
||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
|
|
||||||
|
@ -153,7 +171,7 @@ CSI:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal.buffer.MovePosition(-int16(distance), 0)
|
terminal.ActiveBuffer().MovePosition(-int16(distance), 0)
|
||||||
|
|
||||||
case 'E':
|
case 'E':
|
||||||
distance := 1
|
distance := 1
|
||||||
|
@ -165,8 +183,8 @@ CSI:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal.buffer.MovePosition(0, int16(distance))
|
terminal.ActiveBuffer().MovePosition(0, int16(distance))
|
||||||
terminal.buffer.SetPosition(0, terminal.buffer.CursorLine())
|
terminal.ActiveBuffer().SetPosition(0, terminal.ActiveBuffer().CursorLine())
|
||||||
|
|
||||||
case 'F':
|
case 'F':
|
||||||
|
|
||||||
|
@ -178,8 +196,8 @@ CSI:
|
||||||
distance = 1
|
distance = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
terminal.buffer.MovePosition(0, -int16(distance))
|
terminal.ActiveBuffer().MovePosition(0, -int16(distance))
|
||||||
terminal.buffer.SetPosition(0, terminal.buffer.CursorLine())
|
terminal.ActiveBuffer().SetPosition(0, terminal.ActiveBuffer().CursorLine())
|
||||||
|
|
||||||
case 'G':
|
case 'G':
|
||||||
|
|
||||||
|
@ -192,7 +210,7 @@ CSI:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal.buffer.SetPosition(uint16(distance-1), terminal.buffer.CursorLine())
|
terminal.ActiveBuffer().SetPosition(uint16(distance-1), terminal.ActiveBuffer().CursorLine())
|
||||||
|
|
||||||
case 'H', 'f':
|
case 'H', 'f':
|
||||||
|
|
||||||
|
@ -213,7 +231,7 @@ CSI:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal.buffer.SetPosition(uint16(x-1), uint16(y-1))
|
terminal.ActiveBuffer().SetPosition(uint16(x-1), uint16(y-1))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err = fmt.Errorf("Unknown CSI control sequence: 0x%02X (ESC[%s%s%s)", final, param, intermediate, string(final))
|
err = fmt.Errorf("Unknown CSI control sequence: 0x%02X (ESC[%s%s%s)", final, param, intermediate, string(final))
|
||||||
|
@ -232,7 +250,9 @@ func csiDeleteHandler(params []string, intermediate string, terminal *Terminal)
|
||||||
n = 1
|
n = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = n
|
|
||||||
|
terminal.ActiveBuffer().EraseCharacters(n)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,11 +266,11 @@ func csiEraseInDisplayHandler(params []string, intermediate string, terminal *Te
|
||||||
switch n {
|
switch n {
|
||||||
|
|
||||||
case "0", "":
|
case "0", "":
|
||||||
terminal.buffer.EraseDisplayFromCursor()
|
terminal.ActiveBuffer().EraseDisplayFromCursor()
|
||||||
case "1":
|
case "1":
|
||||||
terminal.buffer.EraseDisplayToCursor()
|
terminal.ActiveBuffer().EraseDisplayToCursor()
|
||||||
case "2":
|
case "2":
|
||||||
terminal.buffer.EraseDisplay()
|
terminal.ActiveBuffer().EraseDisplay()
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unsupported ED: CSI %s J", n)
|
return fmt.Errorf("Unsupported ED: CSI %s J", n)
|
||||||
}
|
}
|
||||||
|
@ -268,11 +288,11 @@ func csiEraseInLineHandler(params []string, intermediate string, terminal *Termi
|
||||||
|
|
||||||
switch n {
|
switch n {
|
||||||
case "0", "": //erase adter cursor
|
case "0", "": //erase adter cursor
|
||||||
terminal.buffer.EraseLineFromCursor()
|
terminal.ActiveBuffer().EraseLineFromCursor()
|
||||||
case "1": // erase to cursor inclusive
|
case "1": // erase to cursor inclusive
|
||||||
terminal.buffer.EraseLineToCursor()
|
terminal.ActiveBuffer().EraseLineToCursor()
|
||||||
case "2": // erase entire
|
case "2": // erase entire
|
||||||
terminal.buffer.EraseLine()
|
terminal.ActiveBuffer().EraseLine()
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unsupported EL: CSI %s K", n)
|
return fmt.Errorf("Unsupported EL: CSI %s K", n)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
type TerminalCharSet int
|
type TerminalCharSet int
|
||||||
|
|
||||||
type escapeSequenceHandler func(buffer chan rune, terminal *Terminal) error
|
type escapeSequenceHandler func(pty chan rune, terminal *Terminal) error
|
||||||
|
|
||||||
var escapeSequenceMap = map[rune]escapeSequenceHandler{
|
var escapeSequenceMap = map[rune]escapeSequenceHandler{
|
||||||
0x1b: ansiHandler,
|
0x1b: ansiHandler,
|
||||||
|
@ -28,7 +28,7 @@ func (terminal *Terminal) Resume() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) processInput(ctx context.Context, buffer chan rune) {
|
func (terminal *Terminal) processInput(ctx context.Context, pty chan rune) {
|
||||||
|
|
||||||
// https://en.wikipedia.org/wiki/ANSI_escape_code
|
// https://en.wikipedia.org/wiki/ANSI_escape_code
|
||||||
|
|
||||||
|
@ -47,12 +47,12 @@ func (terminal *Terminal) processInput(ctx context.Context, buffer chan rune) {
|
||||||
//if terminal.config.slomo
|
//if terminal.config.slomo
|
||||||
//time.Sleep(time.Millisecond * 100)
|
//time.Sleep(time.Millisecond * 100)
|
||||||
|
|
||||||
b := <-buffer
|
b := <-pty
|
||||||
|
|
||||||
handler, ok := escapeSequenceMap[b]
|
handler, ok := escapeSequenceMap[b]
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
if err := handler(buffer, terminal); err != nil {
|
if err := handler(pty, terminal); err != nil {
|
||||||
terminal.logger.Errorf("Error handling escape sequence 0x%X: %s", b, err)
|
terminal.logger.Errorf("Error handling escape sequence 0x%X: %s", b, err)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
@ -62,19 +62,19 @@ func (terminal *Terminal) processInput(ctx context.Context, buffer chan rune) {
|
||||||
|
|
||||||
switch b {
|
switch b {
|
||||||
case 0x0a:
|
case 0x0a:
|
||||||
terminal.buffer.NewLine()
|
terminal.ActiveBuffer().NewLine()
|
||||||
case 0x0d:
|
case 0x0d:
|
||||||
terminal.buffer.CarriageReturn()
|
terminal.ActiveBuffer().CarriageReturn()
|
||||||
case 0x08:
|
case 0x08:
|
||||||
// backspace
|
// backspace
|
||||||
terminal.buffer.Backspace()
|
terminal.ActiveBuffer().Backspace()
|
||||||
case 0x07:
|
case 0x07:
|
||||||
// @todo ring bell - flash red or some shit?
|
// @todo ring bell - flash red or some shit?
|
||||||
default:
|
default:
|
||||||
// render character at current location
|
// render character at current location
|
||||||
// fmt.Printf("%s\n", string([]byte{b}))
|
// fmt.Printf("%s\n", string([]byte{b}))
|
||||||
if b >= 0x20 {
|
if b >= 0x20 {
|
||||||
terminal.buffer.Write(b)
|
terminal.ActiveBuffer().Write(b)
|
||||||
} else {
|
} else {
|
||||||
terminal.logger.Error("Non-readable rune received: 0x%X", b)
|
terminal.logger.Error("Non-readable rune received: 0x%X", b)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,103 +12,103 @@ func sgrSequenceHandler(params []string, intermediate string, terminal *Terminal
|
||||||
param := params[i]
|
param := params[i]
|
||||||
switch param {
|
switch param {
|
||||||
case "00", "0", "":
|
case "00", "0", "":
|
||||||
attr := terminal.buffer.CursorAttr()
|
attr := terminal.ActiveBuffer().CursorAttr()
|
||||||
*attr = buffer.CellAttributes{
|
*attr = buffer.CellAttributes{
|
||||||
FgColour: terminal.config.ColourScheme.Foreground,
|
FgColour: terminal.config.ColourScheme.Foreground,
|
||||||
BgColour: terminal.config.ColourScheme.Background,
|
BgColour: terminal.config.ColourScheme.Background,
|
||||||
}
|
}
|
||||||
case "1", "01":
|
case "1", "01":
|
||||||
terminal.buffer.CursorAttr().Bold = true
|
terminal.ActiveBuffer().CursorAttr().Bold = true
|
||||||
case "2", "02":
|
case "2", "02":
|
||||||
terminal.buffer.CursorAttr().Dim = true
|
terminal.ActiveBuffer().CursorAttr().Dim = true
|
||||||
case "4", "04":
|
case "4", "04":
|
||||||
terminal.buffer.CursorAttr().Underline = true
|
terminal.ActiveBuffer().CursorAttr().Underline = true
|
||||||
case "5", "05":
|
case "5", "05":
|
||||||
terminal.buffer.CursorAttr().Blink = true
|
terminal.ActiveBuffer().CursorAttr().Blink = true
|
||||||
case "7", "07":
|
case "7", "07":
|
||||||
terminal.buffer.CursorAttr().Reverse = true
|
terminal.ActiveBuffer().CursorAttr().Reverse = true
|
||||||
case "8", "08":
|
case "8", "08":
|
||||||
terminal.buffer.CursorAttr().Hidden = true
|
terminal.ActiveBuffer().CursorAttr().Hidden = true
|
||||||
case "21":
|
case "21":
|
||||||
terminal.buffer.CursorAttr().Bold = false
|
terminal.ActiveBuffer().CursorAttr().Bold = false
|
||||||
case "22":
|
case "22":
|
||||||
terminal.buffer.CursorAttr().Dim = false
|
terminal.ActiveBuffer().CursorAttr().Dim = false
|
||||||
case "24":
|
case "24":
|
||||||
terminal.buffer.CursorAttr().Underline = false
|
terminal.ActiveBuffer().CursorAttr().Underline = false
|
||||||
case "25":
|
case "25":
|
||||||
terminal.buffer.CursorAttr().Blink = false
|
terminal.ActiveBuffer().CursorAttr().Blink = false
|
||||||
case "27":
|
case "27":
|
||||||
terminal.buffer.CursorAttr().Reverse = false
|
terminal.ActiveBuffer().CursorAttr().Reverse = false
|
||||||
case "28":
|
case "28":
|
||||||
terminal.buffer.CursorAttr().Hidden = false
|
terminal.ActiveBuffer().CursorAttr().Hidden = false
|
||||||
case "39":
|
case "39":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.Foreground
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.Foreground
|
||||||
case "30":
|
case "30":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.Black
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.Black
|
||||||
case "31":
|
case "31":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.Red
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.Red
|
||||||
case "32":
|
case "32":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.Green
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.Green
|
||||||
case "33":
|
case "33":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.Yellow
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.Yellow
|
||||||
case "34":
|
case "34":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.Blue
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.Blue
|
||||||
case "35":
|
case "35":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.Magenta
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.Magenta
|
||||||
case "36":
|
case "36":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.Cyan
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.Cyan
|
||||||
case "37":
|
case "37":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.White
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.White
|
||||||
case "90":
|
case "90":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.DarkGrey
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.DarkGrey
|
||||||
case "91":
|
case "91":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.LightRed
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.LightRed
|
||||||
case "92":
|
case "92":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.LightGreen
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.LightGreen
|
||||||
case "93":
|
case "93":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.LightYellow
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.LightYellow
|
||||||
case "94":
|
case "94":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.LightBlue
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.LightBlue
|
||||||
case "95":
|
case "95":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.LightMagenta
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.LightMagenta
|
||||||
case "96":
|
case "96":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.LightCyan
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.LightCyan
|
||||||
case "97":
|
case "97":
|
||||||
terminal.buffer.CursorAttr().FgColour = terminal.config.ColourScheme.White
|
terminal.ActiveBuffer().CursorAttr().FgColour = terminal.config.ColourScheme.White
|
||||||
case "49":
|
case "49":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.Background
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.Background
|
||||||
case "40":
|
case "40":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.Black
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.Black
|
||||||
case "41":
|
case "41":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.Red
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.Red
|
||||||
case "42":
|
case "42":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.Green
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.Green
|
||||||
case "43":
|
case "43":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.Yellow
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.Yellow
|
||||||
case "44":
|
case "44":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.Blue
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.Blue
|
||||||
case "45":
|
case "45":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.Magenta
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.Magenta
|
||||||
case "46":
|
case "46":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.Cyan
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.Cyan
|
||||||
case "47":
|
case "47":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.White
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.White
|
||||||
case "100":
|
case "100":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.DarkGrey
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.DarkGrey
|
||||||
case "101":
|
case "101":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.LightRed
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.LightRed
|
||||||
case "102":
|
case "102":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.LightGreen
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.LightGreen
|
||||||
case "103":
|
case "103":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.LightYellow
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.LightYellow
|
||||||
case "104":
|
case "104":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.LightBlue
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.LightBlue
|
||||||
case "105":
|
case "105":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.LightMagenta
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.LightMagenta
|
||||||
case "106":
|
case "106":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.LightCyan
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.LightCyan
|
||||||
case "107":
|
case "107":
|
||||||
terminal.buffer.CursorAttr().BgColour = terminal.config.ColourScheme.White
|
terminal.ActiveBuffer().CursorAttr().BgColour = terminal.config.ColourScheme.White
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("Unknown SGR control sequence: (ESC[%s%sm)", param, intermediate)
|
return fmt.Errorf("Unknown SGR control sequence: (ESC[%s%sm)", param, intermediate)
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,18 +15,24 @@ import (
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
MainBuffer uint8 = 0
|
||||||
|
AltBuffer uint8 = 1
|
||||||
|
)
|
||||||
|
|
||||||
type Terminal struct {
|
type Terminal struct {
|
||||||
buffer *buffer.Buffer
|
buffers []*buffer.Buffer
|
||||||
lock sync.Mutex
|
activeBufferIndex uint8
|
||||||
pty *os.File
|
lock sync.Mutex
|
||||||
logger *zap.SugaredLogger
|
pty *os.File
|
||||||
title string
|
logger *zap.SugaredLogger
|
||||||
size Winsize
|
title string
|
||||||
config config.Config
|
size Winsize
|
||||||
titleHandlers []chan bool
|
config config.Config
|
||||||
pauseChan chan bool
|
titleHandlers []chan bool
|
||||||
resumeChan chan bool
|
pauseChan chan bool
|
||||||
modes Modes
|
resumeChan chan bool
|
||||||
|
modes Modes
|
||||||
}
|
}
|
||||||
|
|
||||||
type Modes struct {
|
type Modes struct {
|
||||||
|
@ -50,10 +56,16 @@ type Position struct {
|
||||||
func New(pty *os.File, logger *zap.SugaredLogger, config config.Config) *Terminal {
|
func New(pty *os.File, logger *zap.SugaredLogger, config config.Config) *Terminal {
|
||||||
|
|
||||||
return &Terminal{
|
return &Terminal{
|
||||||
buffer: buffer.NewBuffer(0, 0, buffer.CellAttributes{
|
buffers: []*buffer.Buffer{
|
||||||
FgColour: config.ColourScheme.Foreground,
|
buffer.NewBuffer(1, 1, buffer.CellAttributes{
|
||||||
BgColour: config.ColourScheme.Background,
|
FgColour: config.ColourScheme.Foreground,
|
||||||
}),
|
BgColour: config.ColourScheme.Background,
|
||||||
|
}),
|
||||||
|
buffer.NewBuffer(1, 1, buffer.CellAttributes{
|
||||||
|
FgColour: config.ColourScheme.Foreground,
|
||||||
|
BgColour: config.ColourScheme.Background,
|
||||||
|
}),
|
||||||
|
},
|
||||||
pty: pty,
|
pty: pty,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
config: config,
|
config: config,
|
||||||
|
@ -66,38 +78,54 @@ func New(pty *os.File, logger *zap.SugaredLogger, config config.Config) *Termina
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (terminal *Terminal) UseMainBuffer() {
|
||||||
|
terminal.activeBufferIndex = MainBuffer
|
||||||
|
terminal.SetSize(uint(terminal.size.Width), uint(terminal.size.Height))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (terminal *Terminal) UseAltBuffer() {
|
||||||
|
terminal.activeBufferIndex = AltBuffer
|
||||||
|
terminal.SetSize(uint(terminal.size.Width), uint(terminal.size.Height))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (terminal *Terminal) ActiveBuffer() *buffer.Buffer {
|
||||||
|
return terminal.buffers[terminal.activeBufferIndex]
|
||||||
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) GetScrollOffset() uint {
|
func (terminal *Terminal) GetScrollOffset() uint {
|
||||||
return terminal.buffer.GetScrollOffset()
|
return terminal.ActiveBuffer().GetScrollOffset()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) ScrollDown(lines uint16) {
|
func (terminal *Terminal) ScrollDown(lines uint16) {
|
||||||
terminal.buffer.ScrollDown(lines)
|
terminal.ActiveBuffer().ScrollDown(lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) ScrollUp(lines uint16) {
|
func (terminal *Terminal) ScrollUp(lines uint16) {
|
||||||
terminal.buffer.ScrollUp(lines)
|
terminal.ActiveBuffer().ScrollUp(lines)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) ScrollPageDown() {
|
func (terminal *Terminal) ScrollPageDown() {
|
||||||
terminal.buffer.ScrollPageDown()
|
terminal.ActiveBuffer().ScrollPageDown()
|
||||||
}
|
}
|
||||||
func (terminal *Terminal) ScrollPageUp() {
|
func (terminal *Terminal) ScrollPageUp() {
|
||||||
terminal.buffer.ScrollPageUp()
|
terminal.ActiveBuffer().ScrollPageUp()
|
||||||
}
|
}
|
||||||
func (terminal *Terminal) ScrollToEnd() {
|
func (terminal *Terminal) ScrollToEnd() {
|
||||||
terminal.buffer.ScrollToEnd()
|
terminal.ActiveBuffer().ScrollToEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) GetVisibleLines() []buffer.Line {
|
func (terminal *Terminal) GetVisibleLines() []buffer.Line {
|
||||||
return terminal.buffer.GetVisibleLines()
|
return terminal.ActiveBuffer().GetVisibleLines()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) GetCell(col int, row int) *buffer.Cell {
|
func (terminal *Terminal) GetCell(col uint16, row uint16) *buffer.Cell {
|
||||||
return terminal.buffer.GetCell(col, row)
|
return terminal.ActiveBuffer().GetCell(col, row)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) AttachDisplayChangeHandler(handler chan bool) {
|
func (terminal *Terminal) AttachDisplayChangeHandler(handler chan bool) {
|
||||||
terminal.buffer.AttachDisplayChangeHandler(handler)
|
for i := range terminal.buffers {
|
||||||
|
terminal.buffers[i].AttachDisplayChangeHandler(handler)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) AttachTitleChangeHandler(handler chan bool) {
|
func (terminal *Terminal) AttachTitleChangeHandler(handler chan bool) {
|
||||||
|
@ -117,19 +145,19 @@ func (terminal *Terminal) emitTitleChange() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) GetLogicalCursorX() uint16 {
|
func (terminal *Terminal) GetLogicalCursorX() uint16 {
|
||||||
if terminal.buffer.CursorColumn() >= terminal.buffer.Width() {
|
if terminal.ActiveBuffer().CursorColumn() >= terminal.ActiveBuffer().Width() {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return terminal.buffer.CursorColumn()
|
return terminal.ActiveBuffer().CursorColumn()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) GetLogicalCursorY() uint16 {
|
func (terminal *Terminal) GetLogicalCursorY() uint16 {
|
||||||
if terminal.buffer.CursorColumn() >= terminal.buffer.Width() {
|
if terminal.ActiveBuffer().CursorColumn() >= terminal.ActiveBuffer().Width() {
|
||||||
return terminal.buffer.CursorLine() + 1
|
return terminal.ActiveBuffer().CursorLine() + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return terminal.buffer.CursorLine()
|
return terminal.ActiveBuffer().CursorLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) GetTitle() string {
|
func (terminal *Terminal) GetTitle() string {
|
||||||
|
@ -174,21 +202,21 @@ func (terminal *Terminal) Read() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) Clear() {
|
func (terminal *Terminal) Clear() {
|
||||||
terminal.buffer.Clear()
|
terminal.ActiveBuffer().Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) GetSize() (int, int) {
|
func (terminal *Terminal) GetSize() (int, int) {
|
||||||
return int(terminal.size.Width), int(terminal.size.Height)
|
return int(terminal.size.Width), int(terminal.size.Height)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (terminal *Terminal) SetSize(newCols int, newLines int) error {
|
func (terminal *Terminal) SetSize(newCols uint, newLines uint) error {
|
||||||
terminal.lock.Lock()
|
terminal.lock.Lock()
|
||||||
defer terminal.lock.Unlock()
|
defer terminal.lock.Unlock()
|
||||||
|
|
||||||
terminal.size.Width = uint16(newCols)
|
terminal.size.Width = uint16(newCols)
|
||||||
terminal.size.Height = uint16(newLines)
|
terminal.size.Height = uint16(newLines)
|
||||||
|
|
||||||
terminal.buffer.ResizeView(terminal.size.Width, terminal.size.Height)
|
terminal.ActiveBuffer().ResizeView(terminal.size.Width, terminal.size.Height)
|
||||||
|
|
||||||
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(terminal.pty.Fd()),
|
_, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(terminal.pty.Fd()),
|
||||||
uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(&terminal.size)))
|
uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(&terminal.size)))
|
||||||
|
|
Loading…
Reference in New Issue