Skip to content

Commit

Permalink
feat(cellbuf): append runes to cell without changing width and accept…
Browse files Browse the repository at this point in the history
… escape sequences
  • Loading branch information
aymanbagabas committed Feb 6, 2025
1 parent 2ef4961 commit af001ce
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 20 deletions.
13 changes: 13 additions & 0 deletions cellbuf/cell.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ type Cell struct {
Rune rune
}

// Append appends runes to the cell without changing the width. This is useful
// when we want to use the cell to store escape sequences or other runes that
// don't affect the width of the cell.
func (c *Cell) Append(r ...rune) {
for i, r := range r {
if i == 0 && c.Rune == 0 {
c.Rune = r
continue
}
c.Comb = append(c.Comb, r)
}
}

// String returns the string content of the cell excluding any styles, links,
// and escape sequences.
func (c Cell) String() string {
Expand Down
39 changes: 19 additions & 20 deletions cellbuf/screen.go
Original file line number Diff line number Diff line change
Expand Up @@ -1520,21 +1520,15 @@ func (s *Screen) printString(x, y int, bounds Rectangle, str string, truncate bo
}
}

var cell Cell
var state byte
for len(str) > 0 {
seq, width, n, newState := s.method.DecodeSequenceInString(str, state, p)

var cell *Cell
switch width {
case 1, 2, 3, 4: // wide cells can go up to 4 cells wide
cell = &Cell{Width: width}
for i, r := range seq {
if i == 0 {
cell.Rune = r
} else {
cell.Comb = append(cell.Comb, r)
}
}
cell.Width += width
cell.Append([]rune(seq)...)

if !truncate && x+cell.Width > bounds.Max.X {
// Wrap the string to the width of the window
Expand All @@ -1553,33 +1547,38 @@ func (s *Screen) printString(x, y int, bounds Rectangle, str string, truncate bo
// Print the cell to the screen
cell.Style = s.cur.Style
cell.Link = s.cur.Link
s.SetCell(x, y, cell) //nolint:errcheck
s.SetCell(x, y, &cell) //nolint:errcheck
cell.Reset()
x += width
}
} // String is too long for the line, truncate it.
default:
// Valid sequences always have a non-zero Cmd.
// TODO: Handle cursor movement and other sequences
switch {
case ansi.HasCsiPrefix(seq) && p.Command() != 0:
switch p.Command() {
case 'm': // SGR - Select Graphic Rendition
ReadStyle(p.Params(), &s.cur.Style)
}
case ansi.HasOscPrefix(seq) && p.Command() != 0:
switch p.Command() {
case 8: // Hyperlinks
ReadLink(p.Data(), &s.cur.Link)
}
case ansi.HasCsiPrefix(seq) && p.Command() == 'm':
// SGR - Select Graphic Rendition
ReadStyle(p.Params(), &s.cur.Style)
case ansi.HasOscPrefix(seq) && p.Command() == 8:
// Hyperlinks
ReadLink(p.Data(), &s.cur.Link)
case ansi.Equal(seq, "\n"):
y++
case ansi.Equal(seq, "\r"):
x = bounds.Min.X
default:
cell.Append([]rune(seq)...)
}
}

// Advance the state and data
state = newState
str = str[n:]
}

// Make sure to set the last cell if it's not empty.
if !cell.Empty() {
s.SetCell(x, y, &cell) //nolint:errcheck
cell.Reset()
}
}

0 comments on commit af001ce

Please sign in to comment.