Skip to content

Commit

Permalink
fix(term): ansi: remove dot-imports and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
aymanbagabas committed Mar 19, 2024
1 parent 7166446 commit 2f4b840
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 102 deletions.
89 changes: 44 additions & 45 deletions exp/term/ansi/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"math"
"unicode/utf8"

. "github.com/charmbracelet/x/exp/term/ansi/parser"
"github.com/charmbracelet/x/exp/term/ansi/parser"
)

const (
Expand Down Expand Up @@ -102,7 +102,7 @@ type Parser struct {
// than 2.
inters [maxIntermediates]byte

state State
state parser.State

// ignoring is set to true when the number of parameters exceeds the
// maximum allowed. This is to prevent the parser from consuming too much
Expand Down Expand Up @@ -145,76 +145,76 @@ func (p *Parser) advanceUtf8(code byte) {
if p.Print != nil {
p.Print(r)
}
p.state = GroundState
p.state = parser.GroundState
p.clearUtf8()
}

// State returns the current state of the parser.
func (p *Parser) State() State {
func (p *Parser) State() parser.State {
return p.state
}

// StateName returns the name of the current state.
func (p *Parser) StateName() string {
return StateNames[p.state]
return parser.StateNames[p.state]
}

// Advance advances the state machine.
func (p *Parser) Advance(code byte, more bool) {
if p.state == Utf8State {
if p.state == parser.Utf8State {
p.advanceUtf8(code)
} else {
state, action := Table.Transition(p.state, code)
state, action := parser.Table.Transition(p.state, code)
p.performStateChange(state, action, code, more)
}
}

func (p *Parser) performEscapeStateChange(code byte, more bool) {
switch p.state {
case GroundState:
case parser.GroundState:
if !more {
// End of input, execute Esc
p.performAction(ExecuteAction, code)
p.performAction(parser.ExecuteAction, code)
}
case EscapeState:
case parser.EscapeState:
// More input mean possible Esc sequence, execute the previous Esc
p.performAction(ExecuteAction, code)
p.performAction(parser.ExecuteAction, code)
if !more {
// No more input means execute the current Esc
p.performAction(ExecuteAction, code)
p.performAction(parser.ExecuteAction, code)
}
default:
if !more {
// No more input means execute the current Esc
p.performAction(ExecuteAction, code)
p.performAction(parser.ExecuteAction, code)
}
}
}

func (p *Parser) performStateChange(state State, action Action, code byte, more bool) {
func (p *Parser) performStateChange(state parser.State, action parser.Action, code byte, more bool) {
// Handle Esc execute action
if code == ESC {
p.performEscapeStateChange(code, more)
}

if p.state != state {
switch p.state {
case DcsPassthroughState:
p.performAction(DcsUnhookAction, code)
case OscStringState:
p.performAction(OscEndAction, code)
case SosPmApcStringState:
p.performAction(SosPmApcEndAction, code)
case parser.DcsPassthroughState:
p.performAction(parser.DcsUnhookAction, code)
case parser.OscStringState:
p.performAction(parser.OscEndAction, code)
case parser.SosPmApcStringState:
p.performAction(parser.SosPmApcEndAction, code)
}
}

p.performAction(action, code)

if p.state != state {
switch state {
case CsiEntryState, DcsEntryState, EscapeState:
p.performAction(ClearAction, code)
case SosPmApcStringState:
case parser.CsiEntryState, parser.DcsEntryState, parser.EscapeState:
p.performAction(parser.ClearAction, code)
case parser.SosPmApcStringState:
switch code {
case SOS, 'X':
p.sosPmApc = SOS
Expand All @@ -224,36 +224,35 @@ func (p *Parser) performStateChange(state State, action Action, code byte, more
p.sosPmApc = APC
}
fallthrough
case OscStringState:
p.performAction(StartAction, code)
case DcsPassthroughState:
p.performAction(DcsHookAction, code)
case parser.OscStringState:
p.performAction(parser.StartAction, code)
case parser.DcsPassthroughState:
p.performAction(parser.DcsHookAction, code)
}
}

p.state = state
}

func (p *Parser) performAction(action Action, code byte) {
// log.Printf("performing action: %s, code: %q", ActionNames[action], code)
func (p *Parser) performAction(action parser.Action, code byte) {
switch action {
case NoneAction:
case parser.NoneAction:
break

case IgnoreAction:
case parser.IgnoreAction:
break

case PrintAction:
case parser.PrintAction:
if p.Print != nil {
p.Print(rune(code))
}

case ExecuteAction:
case parser.ExecuteAction:
if p.Execute != nil {
p.Execute(code)
}

case EscDispatchAction:
case parser.EscDispatchAction:
if p.EscDispatch != nil {
p.EscDispatch(
p.inters[1],
Expand All @@ -262,16 +261,16 @@ func (p *Parser) performAction(action Action, code byte) {
)
}

case SosPmApcEndAction:
case parser.SosPmApcEndAction:
if p.SosPmApcDispatch != nil {
p.SosPmApcDispatch(p.sosPmApc, p.buf)
}

case StartAction:
case parser.StartAction:
p.buf = make([]byte, 0)
p.oscNumParams = 0

case OscPutAction:
case parser.OscPutAction:
idx := len(p.buf)
if code == ';' {
paramIdx := p.oscNumParams
Expand All @@ -290,7 +289,7 @@ func (p *Parser) performAction(action Action, code byte) {
p.buf = append(p.buf, code)
}

case OscEndAction:
case parser.OscEndAction:
paramIdx := p.oscNumParams
idx := len(p.buf)

Expand All @@ -314,7 +313,7 @@ func (p *Parser) performAction(action Action, code byte) {
)
}

case DcsHookAction:
case parser.DcsHookAction:
p.buf = make([]byte, 0)
if p.isParamsFull() {
p.ignoring = true
Expand All @@ -323,10 +322,10 @@ func (p *Parser) performAction(action Action, code byte) {
}
p.param = uint(code)

case PutAction:
case parser.PutAction:
p.buf = append(p.buf, code)

case DcsUnhookAction:
case parser.DcsUnhookAction:
if p.DcsDispatch != nil {
p.DcsDispatch(
p.inters[0],
Expand All @@ -338,7 +337,7 @@ func (p *Parser) performAction(action Action, code byte) {
)
}

case CsiDispatchAction:
case parser.CsiDispatchAction:
if p.isParamsFull() {
p.ignoring = true
} else if p.param > 0 || p.hasParams {
Expand All @@ -355,14 +354,14 @@ func (p *Parser) performAction(action Action, code byte) {
)
}

case CollectAction:
case parser.CollectAction:
if utf8ByteLen(code) > 1 {
p.collectUtf8(code)
} else {
p.collect(code)
}

case ParamAction:
case parser.ParamAction:
if p.isParamsFull() {
p.ignoring = true
return
Expand All @@ -381,7 +380,7 @@ func (p *Parser) performAction(action Action, code byte) {
p.param = saddu(p.param, uint(code-'0'))
}

case ClearAction:
case parser.ClearAction:
p.clear()
}
}
Expand Down
84 changes: 40 additions & 44 deletions exp/term/ansi/truncate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package ansi
import (
"bytes"

. "github.com/charmbracelet/x/exp/term/ansi/parser"
"github.com/charmbracelet/x/exp/term/ansi/parser"
"github.com/rivo/uniseg"
)

Expand All @@ -23,7 +23,7 @@ func Truncate(s string, length int, tail string) string {
curWidth := 0
ignoring := false
gstate := -1
pstate := GroundState // initial state
pstate := parser.GroundState // initial state
b := []byte(s)
i := 0

Expand All @@ -33,51 +33,49 @@ func Truncate(s string, length int, tail string) string {
// Once we reach the given length, we start ignoring characters and only
// collect ANSI escape codes until we reach the end of string.
for i < len(b) {
state, action := Table.Transition(pstate, b[i])
// log.Printf("pstate: %s, state: %s, action: %s, code: %q", StateNames[pstate], StateNames[state], ActionNames[action], s[i])
state, action := parser.Table.Transition(pstate, b[i])

switch action {
case CollectAction:
// This action happens when we transition to the Utf8State.
if w := utf8ByteLen(b[i]); w > 1 {
var width int
cluster, _, width, gstate = uniseg.FirstGraphemeCluster(b[i:], gstate)

// log.Printf("cluster: %q, width: %d, curWidth: %d", string(cluster), width, curWidth)

// increment the index by the length of the cluster
i += len(cluster)

// Are we ignoring? Skip to the next byte
if ignoring {
continue
}

// Is this gonna be too wide?
// If so write the tail and stop collecting.
if curWidth+width > length && !ignoring {
ignoring = true
buf.WriteString(tail)
}

if curWidth+width > length {
continue
}

curWidth += width
for _, r := range cluster {
buf.WriteByte(r)
}

gstate = -1 // reset grapheme state otherwise, width calculation might be off
// Done collecting, now we're back in the ground state.
pstate = GroundState
continue
} else {
case parser.CollectAction:
if w := utf8ByteLen(b[i]); w <= 1 {
// Collecting sequence intermediate bytes
buf.WriteByte(b[i])
break
}

// This action happens when we transition to the Utf8State.
var width int
cluster, _, width, gstate = uniseg.FirstGraphemeCluster(b[i:], gstate)

// increment the index by the length of the cluster
i += len(cluster)

// Are we ignoring? Skip to the next byte
if ignoring {
continue
}

// Is this gonna be too wide?
// If so write the tail and stop collecting.
if curWidth+width > length && !ignoring {
ignoring = true
buf.WriteString(tail)
}
case PrintAction:

if curWidth+width > length {
continue
}

curWidth += width
for _, r := range cluster {
buf.WriteByte(r)
}

gstate = -1 // reset grapheme state otherwise, width calculation might be off
// Done collecting, now we're back in the ground state.
pstate = parser.GroundState
continue
case parser.PrintAction:
// Is this gonna be too wide?
// If so write the tail and stop collecting.
if curWidth >= length && !ignoring {
Expand All @@ -102,8 +100,6 @@ func Truncate(s string, length int, tail string) string {
// Transition to the next state.
pstate = state

// log.Printf("buf: %q, curWidth: %d, ignoring: %v", buf.String(), curWidth, ignoring)

// Once we reach the given length, we start ignoring runes and write
// the tail to the buffer.
if curWidth > length && !ignoring {
Expand Down
1 change: 1 addition & 0 deletions exp/term/ansi/truncate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"
)

// nolint
var tcases = []struct {
name string
input string
Expand Down
Loading

0 comments on commit 2f4b840

Please sign in to comment.