mirror of
https://github.com/charmbracelet/gum
synced 2026-03-14 21:55:45 +01:00
fix(pager): memory/cpu usage when using soft-wrap (#827)
easily reproducible, especially with something like ```sh PAGER="gum pager" man ls ``` Problems here were: - reflow's truncate is not very efficient - useless calls to truncate - bad strings.Replace calls (not necessary, and wouldn't work if text has ansi sequences)
This commit is contained in:
parent
e7c916cff6
commit
d1fc05155c
3 changed files with 26 additions and 18 deletions
2
go.mod
2
go.mod
|
|
@ -14,7 +14,6 @@ require (
|
|||
github.com/charmbracelet/x/ansi v0.8.0
|
||||
github.com/charmbracelet/x/editor v0.1.0
|
||||
github.com/charmbracelet/x/term v0.2.1
|
||||
github.com/muesli/reflow v0.3.0
|
||||
github.com/muesli/roff v0.1.0
|
||||
github.com/muesli/termenv v0.15.3-0.20241211131612-0d230cb6eb15
|
||||
github.com/rivo/uniseg v0.4.7
|
||||
|
|
@ -40,6 +39,7 @@ require (
|
|||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||
github.com/muesli/mango v0.2.0 // indirect
|
||||
github.com/muesli/reflow v0.3.0 // indirect
|
||||
github.com/yuin/goldmark v1.7.4 // indirect
|
||||
github.com/yuin/goldmark-emoji v1.0.4 // indirect
|
||||
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/charmbracelet/bubbles/viewport"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/muesli/reflow/truncate"
|
||||
"github.com/charmbracelet/x/ansi"
|
||||
)
|
||||
|
||||
type keymap struct {
|
||||
|
|
@ -146,17 +146,21 @@ func (m *model) processText(msg tea.WindowSizeMsg) {
|
|||
if m.showLineNumbers {
|
||||
text.WriteString(m.lineNumberStyle.Render(fmt.Sprintf("%4d │ ", i+1)))
|
||||
}
|
||||
for m.softWrap && lipgloss.Width(line) > m.maxWidth {
|
||||
truncatedLine := truncate.String(line, uint(m.maxWidth)) //nolint: gosec
|
||||
text.WriteString(textStyle.Render(truncatedLine))
|
||||
text.WriteString("\n")
|
||||
if m.showLineNumbers {
|
||||
text.WriteString(m.lineNumberStyle.Render(" │ "))
|
||||
idx := 0
|
||||
if w := ansi.StringWidth(line); m.softWrap && w > m.maxWidth {
|
||||
for w > idx {
|
||||
if m.showLineNumbers && idx != 0 {
|
||||
text.WriteString(m.lineNumberStyle.Render(" │ "))
|
||||
}
|
||||
truncatedLine := ansi.Cut(line, idx, m.maxWidth+idx)
|
||||
idx += m.maxWidth
|
||||
text.WriteString(textStyle.Render(truncatedLine))
|
||||
text.WriteString("\n")
|
||||
}
|
||||
line = strings.Replace(line, truncatedLine, "", 1)
|
||||
} else {
|
||||
text.WriteString(textStyle.Render(line)) //nolint: gosec
|
||||
text.WriteString("\n")
|
||||
}
|
||||
text.WriteString(textStyle.Render(truncate.String(line, uint(m.maxWidth)))) //nolint: gosec
|
||||
text.WriteString("\n")
|
||||
}
|
||||
|
||||
diffHeight := m.viewport.Height - lipgloss.Height(text.String())
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/charmbracelet/bubbles/textinput"
|
||||
"github.com/charmbracelet/gum/internal/utils"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/muesli/reflow/truncate"
|
||||
"github.com/charmbracelet/x/ansi"
|
||||
)
|
||||
|
||||
type search struct {
|
||||
|
|
@ -150,14 +150,18 @@ func (s *search) PrevMatch(m *model) {
|
|||
func softWrapEm(str string, maxWidth int, softWrap bool) string {
|
||||
var text strings.Builder
|
||||
for _, line := range strings.Split(str, "\n") {
|
||||
for softWrap && lipgloss.Width(line) > maxWidth {
|
||||
truncatedLine := truncate.String(line, uint(maxWidth)) //nolint: gosec
|
||||
text.WriteString(truncatedLine)
|
||||
idx := 0
|
||||
if w := ansi.StringWidth(line); softWrap && w > maxWidth {
|
||||
for w > idx {
|
||||
truncatedLine := ansi.Cut(line, idx, maxWidth+idx)
|
||||
idx += maxWidth
|
||||
text.WriteString(truncatedLine)
|
||||
text.WriteString("\n")
|
||||
}
|
||||
} else {
|
||||
text.WriteString(line) //nolint: gosec
|
||||
text.WriteString("\n")
|
||||
line = strings.Replace(line, truncatedLine, "", 1)
|
||||
}
|
||||
text.WriteString(truncate.String(line, uint(maxWidth))) //nolint: gosec
|
||||
text.WriteString("\n")
|
||||
}
|
||||
|
||||
return text.String()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue