Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use inhouse wcwidth package instead of go-runewidth #643

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ require (
github.com/charmbracelet/lipgloss v0.13.0
github.com/charmbracelet/x/ansi v0.3.2
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91
github.com/charmbracelet/x/wcwidth v0.0.0-20241021033131-8140f283f8ec
github.com/dustin/go-humanize v1.0.1
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/mattn/go-runewidth v0.0.16
github.com/muesli/termenv v0.15.2
github.com/rivo/uniseg v0.4.7
github.com/sahilm/fuzzy v0.1.1
)

Expand All @@ -26,9 +25,11 @@ require (
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-localereader v0.0.1 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.24.0 // indirect
golang.org/x/text v0.3.8 // indirect
golang.org/x/text v0.19.0 // indirect
)
6 changes: 4 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payR
github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U=
github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0=
github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0=
github.com/charmbracelet/x/wcwidth v0.0.0-20241021033131-8140f283f8ec h1:uzb9WgyFdLApCiC41+GWjIWY1wNZ6MrS2NRp0U/0hCI=
github.com/charmbracelet/x/wcwidth v0.0.0-20241021033131-8140f283f8ec/go.mod h1:Ey8PFmYwH+/td9bpiEx07Fdx9ZVkxfIjWXxBluxF4Nw=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
Expand Down Expand Up @@ -49,5 +51,5 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
6 changes: 3 additions & 3 deletions table/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/charmbracelet/bubbles/viewport"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/mattn/go-runewidth"
"github.com/charmbracelet/x/ansi"
)

// Model defines a state for the table widget.
Expand Down Expand Up @@ -412,7 +412,7 @@ func (m Model) headersView() string {
continue
}
style := lipgloss.NewStyle().Width(col.Width).MaxWidth(col.Width).Inline(true)
renderedCell := style.Render(runewidth.Truncate(col.Title, col.Width, "…"))
renderedCell := style.Render(ansi.Truncate(col.Title, col.Width, "…"))
s = append(s, m.styles.Header.Render(renderedCell))
}
return lipgloss.JoinHorizontal(lipgloss.Top, s...)
Expand All @@ -425,7 +425,7 @@ func (m *Model) renderRow(r int) string {
continue
}
style := lipgloss.NewStyle().Width(m.cols[i].Width).MaxWidth(m.cols[i].Width).Inline(true)
renderedCell := m.styles.Cell.Render(style.Render(runewidth.Truncate(value, m.cols[i].Width, "…")))
renderedCell := m.styles.Cell.Render(style.Render(ansi.Truncate(value, m.cols[i].Width, "…")))
s = append(s, renderedCell)
}

Expand Down
33 changes: 16 additions & 17 deletions textarea/textarea.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/x/ansi"
rw "github.com/mattn/go-runewidth"
"github.com/rivo/uniseg"
"github.com/charmbracelet/x/wcwidth"
)

const (
Expand Down Expand Up @@ -462,7 +461,7 @@
func (m *Model) Length() int {
var l int
for _, row := range m.value {
l += uniseg.StringWidth(string(row))
l += wcwidth.StringWidth(string(row))
}
// We add len(m.value) to include the newline characters.
return l + len(m.value) - 1
Expand Down Expand Up @@ -507,7 +506,7 @@
if m.row >= len(m.value) || m.col >= len(m.value[m.row]) || offset >= nli.CharWidth-1 {
break
}
offset += rw.RuneWidth(m.value[m.row][m.col])
offset += wcwidth.RuneWidth(m.value[m.row][m.col])
m.col++
}
}
Expand Down Expand Up @@ -541,7 +540,7 @@
if m.col >= len(m.value[m.row]) || offset >= nli.CharWidth-1 {
break
}
offset += rw.RuneWidth(m.value[m.row][m.col])
offset += wcwidth.RuneWidth(m.value[m.row][m.col])
m.col++
}
}
Expand Down Expand Up @@ -829,19 +828,19 @@
RowOffset: i + 1,
StartColumn: m.col,
Width: len(grid[i+1]),
CharWidth: uniseg.StringWidth(string(line)),
CharWidth: wcwidth.StringWidth(string(line)),
}
}

if counter+len(line) >= m.col {
return LineInfo{
CharOffset: uniseg.StringWidth(string(line[:max(0, m.col-counter)])),
CharOffset: wcwidth.StringWidth(string(line[:max(0, m.col-counter)])),
ColumnOffset: m.col - counter,
Height: len(grid),
RowOffset: i,
StartColumn: counter,
Width: len(line),
CharWidth: uniseg.StringWidth(string(line)),
CharWidth: wcwidth.StringWidth(string(line)),
}
}

Expand Down Expand Up @@ -891,7 +890,7 @@
// Update prompt width only if there is no prompt function as SetPromptFunc
// updates the prompt width when it is called.
if m.promptFunc == nil {
m.promptWidth = uniseg.StringWidth(m.Prompt)
m.promptWidth = wcwidth.StringWidth(m.Prompt)
}

// Add base style borders and padding to reserved outer width.
Expand Down Expand Up @@ -1119,7 +1118,7 @@
displayLine++

var ln string
if m.ShowLineNumbers {

Check failure on line 1121 in textarea/textarea.go

View workflow job for this annotation

GitHub Actions / lint-soft

`if m.ShowLineNumbers` has complex nested blocks (complexity: 8) (nestif)
if wl == 0 {
if m.row == l {
ln = style.Render(m.style.computedCursorLineNumber().Render(m.formatLineNumber(l + 1)))
Expand All @@ -1145,7 +1144,7 @@
widestLineNumber = lnw
}

strwidth := uniseg.StringWidth(string(wrappedLine))
strwidth := wcwidth.StringWidth(string(wrappedLine))
padding := m.width - strwidth
// If the trailing space causes the line to be wider than the
// width, we should not draw it to the screen since it will result
Expand Down Expand Up @@ -1198,7 +1197,7 @@
}

// formatLineNumber formats the line number for display dynamically based on
// the maximum number of lines

Check failure on line 1200 in textarea/textarea.go

View workflow job for this annotation

GitHub Actions / lint-soft

Comment should end in a period (godot)
func (m Model) formatLineNumber(x any) string {
// XXX: ultimately we should use a max buffer height, which has yet to be
// implemented.
Expand All @@ -1212,7 +1211,7 @@
return prompt
}
prompt = m.promptFunc(displayLine)
pl := uniseg.StringWidth(prompt)
pl := wcwidth.StringWidth(prompt)
if pl < m.promptWidth {
prompt = fmt.Sprintf("%*s%s", m.promptWidth-pl, "", prompt)
}
Expand Down Expand Up @@ -1273,12 +1272,12 @@
s.WriteString(lineStyle.Render(m.Cursor.View()))

// the rest of the first line
s.WriteString(lineStyle.Render(style.Render(plines[0][1:] + strings.Repeat(" ", max(0, m.width-uniseg.StringWidth(plines[0]))))))
s.WriteString(lineStyle.Render(style.Render(plines[0][1:] + strings.Repeat(" ", max(0, m.width-wcwidth.StringWidth(plines[0]))))))
// remaining lines
case len(plines) > i:
// current line placeholder text
if len(plines) > i {
s.WriteString(lineStyle.Render(style.Render(plines[i] + strings.Repeat(" ", max(0, m.width-uniseg.StringWidth(plines[i]))))))
s.WriteString(lineStyle.Render(style.Render(plines[i] + strings.Repeat(" ", max(0, m.width-wcwidth.StringWidth(plines[i]))))))
}
default:
// end of line buffer character
Expand Down Expand Up @@ -1407,8 +1406,8 @@
word = append(word, r)
}

if spaces > 0 {

Check failure on line 1409 in textarea/textarea.go

View workflow job for this annotation

GitHub Actions / lint-soft

`if spaces > 0` has complex nested blocks (complexity: 6) (nestif)
if uniseg.StringWidth(string(lines[row]))+uniseg.StringWidth(string(word))+spaces > width {
if wcwidth.StringWidth(string(lines[row]))+wcwidth.StringWidth(string(word))+spaces > width {
row++
lines = append(lines, []rune{})
lines[row] = append(lines[row], word...)
Expand All @@ -1424,8 +1423,8 @@
} else {
// If the last character is a double-width rune, then we may not be able to add it to this line
// as it might cause us to go past the width.
lastCharLen := rw.RuneWidth(word[len(word)-1])
if uniseg.StringWidth(string(word))+lastCharLen > width {
lastCharLen := wcwidth.RuneWidth(word[len(word)-1])
if wcwidth.StringWidth(string(word))+lastCharLen > width {
// If the current line has any content, let's move to the next
// line because the current word fills up the entire line.
if len(lines[row]) > 0 {
Expand All @@ -1438,7 +1437,7 @@
}
}

if uniseg.StringWidth(string(lines[row]))+uniseg.StringWidth(string(word))+spaces >= width {
if wcwidth.StringWidth(string(lines[row]))+wcwidth.StringWidth(string(word))+spaces >= width {
lines = append(lines, []rune{})
lines[row+1] = append(lines[row+1], word...)
// We add an extra space at the end of the line to account for the
Expand Down
13 changes: 6 additions & 7 deletions textinput/textinput.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
"github.com/charmbracelet/bubbles/runeutil"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
rw "github.com/mattn/go-runewidth"
"github.com/rivo/uniseg"
"github.com/charmbracelet/x/wcwidth"
)

// Internal messages for clipboard operations.
Expand Down Expand Up @@ -325,7 +324,7 @@
// If a max width is defined, perform some logic to treat the visible area
// as a horizontally scrolling viewport.
func (m *Model) handleOverflow() {
if m.Width <= 0 || uniseg.StringWidth(string(m.value)) <= m.Width {
if m.Width <= 0 || wcwidth.StringWidth(string(m.value)) <= m.Width {
m.offset = 0
m.offsetRight = len(m.value)
return
Expand All @@ -342,7 +341,7 @@
runes := m.value[m.offset:]

for i < len(runes) && w <= m.Width {
w += rw.RuneWidth(runes[i])
w += wcwidth.RuneWidth(runes[i])
if w <= m.Width+1 {
i++
}
Expand All @@ -357,7 +356,7 @@
i := len(runes) - 1

for i > 0 && w < m.Width {
w += rw.RuneWidth(runes[i])
w += wcwidth.RuneWidth(runes[i])
if w <= m.Width {
i--
}
Expand Down Expand Up @@ -538,7 +537,7 @@
func (m Model) echoTransform(v string) string {
switch m.EchoMode {
case EchoPassword:
return strings.Repeat(string(m.EchoCharacter), uniseg.StringWidth(v))
return strings.Repeat(string(m.EchoCharacter), wcwidth.StringWidth(v))
case EchoNone:
return ""
case EchoNormal:
Expand Down Expand Up @@ -658,7 +657,7 @@
pos := max(0, m.pos-m.offset)
v := styleText(m.echoTransform(string(value[:pos])))

if pos < len(value) {

Check failure on line 660 in textinput/textinput.go

View workflow job for this annotation

GitHub Actions / lint-soft

`if pos < len(value)` has complex nested blocks (complexity: 6) (nestif)
char := m.echoTransform(string(value[pos]))
m.Cursor.SetChar(char)
v += m.Cursor.View() // cursor and text under it
Expand All @@ -684,7 +683,7 @@

// If a max width and background color were set fill the empty spaces with
// the background color.
valWidth := uniseg.StringWidth(string(value))
valWidth := wcwidth.StringWidth(string(value))
if m.Width > 0 && valWidth <= m.Width {
padding := max(0, m.Width-valWidth)
if valWidth+padding <= m.Width && pos < len(value) {
Expand Down
Loading