mirror of https://github.com/liamg/aminal.git
added Tab Stops support (#175)
This commit is contained in:
parent
4e7b8b40e7
commit
d2214b7915
|
@ -717,22 +717,11 @@ func (buffer *Buffer) CarriageReturn() {
|
|||
}
|
||||
|
||||
func (buffer *Buffer) Tab() {
|
||||
tabSize := 4
|
||||
max := tabSize
|
||||
|
||||
// @todo rightMargin
|
||||
if buffer.terminalState.cursorX < buffer.terminalState.viewWidth {
|
||||
max = int(buffer.terminalState.viewWidth - buffer.terminalState.cursorX - 1)
|
||||
}
|
||||
|
||||
shift := tabSize - (int(buffer.terminalState.cursorX+1) % tabSize)
|
||||
|
||||
if shift > max {
|
||||
shift = max
|
||||
}
|
||||
|
||||
for i := 0; i < shift; i++ {
|
||||
for buffer.terminalState.cursorX < buffer.terminalState.viewWidth-1 { // @todo rightMargin
|
||||
buffer.Write(' ')
|
||||
if buffer.terminalState.IsTabSetAtCursor() {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ type TerminalState struct {
|
|||
LineFeedMode bool
|
||||
AutoWrap bool
|
||||
maxLines uint64
|
||||
tabStops map[uint16]struct{}
|
||||
}
|
||||
|
||||
// NewTerminalMode creates a new terminal state
|
||||
|
@ -31,6 +32,7 @@ func NewTerminalState(viewCols uint16, viewLines uint16, attr CellAttributes, ma
|
|||
topMargin: 0,
|
||||
bottomMargin: uint(viewLines - 1),
|
||||
}
|
||||
b.TabReset()
|
||||
return b
|
||||
}
|
||||
|
||||
|
@ -47,3 +49,48 @@ func (terminalState *TerminalState) ResetVerticalMargins() {
|
|||
func (terminalState *TerminalState) IsNewLineMode() bool {
|
||||
return terminalState.LineFeedMode == false
|
||||
}
|
||||
|
||||
func (terminalState *TerminalState) TabZonk() {
|
||||
terminalState.tabStops = make(map[uint16]struct{})
|
||||
}
|
||||
|
||||
func (terminalState *TerminalState) TabSet(index uint16) {
|
||||
terminalState.tabStops[index] = struct{}{}
|
||||
}
|
||||
|
||||
func (terminalState *TerminalState) TabClear(index uint16) {
|
||||
delete(terminalState.tabStops, index)
|
||||
}
|
||||
|
||||
func (terminalState *TerminalState) getTabIndexFromCursor() uint16 {
|
||||
index := terminalState.cursorX
|
||||
if index == terminalState.viewWidth {
|
||||
index = 0
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
func (terminalState *TerminalState) IsTabSetAtCursor() bool {
|
||||
index := terminalState.getTabIndexFromCursor()
|
||||
_, ok := terminalState.tabStops[index]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (terminalState *TerminalState) TabClearAtCursor() {
|
||||
terminalState.TabClear(terminalState.getTabIndexFromCursor())
|
||||
}
|
||||
|
||||
func (terminalState *TerminalState) TabSetAtCursor() {
|
||||
terminalState.TabSet(terminalState.getTabIndexFromCursor())
|
||||
}
|
||||
|
||||
func (terminalState *TerminalState) TabReset() {
|
||||
terminalState.TabZonk()
|
||||
const MaxTabs uint16 = 1024
|
||||
const TabStep = 4
|
||||
var i uint16
|
||||
for i < MaxTabs {
|
||||
terminalState.TabSet(i)
|
||||
i += TabStep
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ var ansiSequenceMap = map[rune]escapeSequenceHandler{
|
|||
'8': restoreCursorHandler,
|
||||
'D': indexHandler,
|
||||
'E': nextLineHandler, // NEL
|
||||
'H': tabSetHandler, // HTS
|
||||
'M': reverseIndexHandler,
|
||||
'P': sixelHandler,
|
||||
'c': risHandler, //RIS
|
||||
|
@ -75,3 +76,8 @@ func nextLineHandler(pty chan rune, terminal *Terminal) error {
|
|||
terminal.ActiveBuffer().NewLineEx(true)
|
||||
return nil
|
||||
}
|
||||
|
||||
func tabSetHandler(pty chan rune, terminal *Terminal) error {
|
||||
terminal.terminalState.TabSetAtCursor()
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ var csiSequences = []csiMapping{
|
|||
{id: 'c', handler: csiSendDeviceAttributesHandler, description: " Send Device Attributes (Primary/Secondary/Tertiary DA)"},
|
||||
{id: 'd', handler: csiLinePositionAbsolute, expectedParams: &expectedParams{min: 0, max: 1}, description: "Line Position Absolute [row] (default = [1,column]) (VPA)"},
|
||||
{id: 'f', handler: csiCursorPositionHandler, description: "Horizontal and Vertical Position [row;column] (default = [1,1]) (HVP)"},
|
||||
{id: 'g', handler: csiTabClearHandler, description: "Tab Clear (TBC)"},
|
||||
{id: 'h', handler: csiSetModeHandler, expectedParams: &expectedParams{min: 1, max: 1}, description: "Set Mode (SM)"},
|
||||
{id: 'l', handler: csiResetModeHandler, expectedParams: &expectedParams{min: 1, max: 1}, description: "Reset Mode (RM)"},
|
||||
{id: 'm', handler: sgrSequenceHandler, description: "Character Attributes (SGR)"},
|
||||
|
@ -463,6 +464,24 @@ func csiDeleteHandler(params []string, terminal *Terminal) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func csiTabClearHandler(params []string, terminal *Terminal) error {
|
||||
n := "0"
|
||||
if len(params) > 0 {
|
||||
n = params[0]
|
||||
}
|
||||
switch n {
|
||||
|
||||
case "0", "":
|
||||
terminal.terminalState.TabClearAtCursor()
|
||||
case "3":
|
||||
terminal.terminalState.TabZonk()
|
||||
default:
|
||||
return fmt.Errorf("Ignored TBC: CSI %s g", n)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CSI Ps J
|
||||
func csiEraseInDisplayHandler(params []string, terminal *Terminal) error {
|
||||
n := "0"
|
||||
|
|
Loading…
Reference in New Issue