Skip to content

Fix lineWrap issues #67

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

Merged
merged 11 commits into from
Dec 23, 2024
2 changes: 1 addition & 1 deletion gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ func (g *Gui) SetView(name string, x0, y0, x1, y1 int, overlaps byte) (*View, er

g.Mutexes.ViewsMutex.Lock()

v := newView(name, x0, y0, x1, y1, g.outputMode)
v := NewView(name, x0, y0, x1, y1, g.outputMode)
v.BgColor, v.FgColor = g.BgColor, g.FgColor
v.SelBgColor, v.SelFgColor = g.SelBgColor, g.SelFgColor
v.Overlaps = overlaps
Expand Down
53 changes: 22 additions & 31 deletions view.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,8 @@ func (l lineType) String() string {
return str
}

// newView returns a new View object.
func newView(name string, x0, y0, x1, y1 int, mode OutputMode) *View {
// NewView returns a new View object.
func NewView(name string, x0, y0, x1, y1 int, mode OutputMode) *View {
v := &View{
name: name,
x0: x0,
Expand Down Expand Up @@ -494,31 +494,15 @@ func (v *View) setRune(x, y int, ch rune, fgColor, bgColor Attribute) {
bgColor = v.BgColor
ch = v.Mask
} else if v.Highlight {
var ry, rcy int

_, ry, ok := v.realPosition(x, y)
if !ok {
return
}
_, rrcy, ok := v.realPosition(v.cx, v.cy)
// out of bounds is fine
if ok {
rcy = rrcy
}

rangeSelectStart := rcy
rangeSelectEnd := rcy
rangeSelectStart := v.cy
rangeSelectEnd := v.cy
if v.rangeSelectStartY != -1 {
_, realRangeSelectStart, ok := v.realPosition(0, v.rangeSelectStartY-v.oy)
if !ok {
return
}

rangeSelectStart = min(realRangeSelectStart, rcy)
rangeSelectEnd = max(realRangeSelectStart, rcy)
relativeRangeSelectStart := v.rangeSelectStartY - v.oy
rangeSelectStart = min(relativeRangeSelectStart, v.cy)
rangeSelectEnd = max(relativeRangeSelectStart, v.cy)
}

if ry >= rangeSelectStart && ry <= rangeSelectEnd {
if y >= rangeSelectStart && y <= rangeSelectEnd {
// this ensures we use the bright variant of a colour upon highlight
fgColorComponent := fgColor & ^AttrAll
if fgColorComponent >= AttrIsValidColor && fgColorComponent < AttrIsValidColor+8 {
Expand Down Expand Up @@ -1103,6 +1087,8 @@ func (v *View) updateSearchPositions() {

if v.searcher.modelSearchResults != nil {
for _, result := range v.searcher.modelSearchResults {
// This code only works when v.Wrap is false.

if result.Y >= len(v.lines) {
break
}
Expand Down Expand Up @@ -1131,8 +1117,9 @@ func (v *View) updateSearchPositions() {
}
}
} else {
for y, line := range v.lines {
v.searcher.searchPositions = append(v.searcher.searchPositions, searchPositionsForLine(line, y)...)
v.refreshViewLinesIfNeeded()
for y, line := range v.viewLines {
v.searcher.searchPositions = append(v.searcher.searchPositions, searchPositionsForLine(line.line, y)...)
}
}
}
Expand Down Expand Up @@ -1373,6 +1360,8 @@ func (v *View) ViewBufferLines() []string {
v.writeMutex.Lock()
defer v.writeMutex.Unlock()

v.refreshViewLinesIfNeeded()

lines := make([]string, len(v.viewLines))
for i, l := range v.viewLines {
str := lineType(l.line).String()
Expand Down Expand Up @@ -1512,18 +1501,20 @@ func lineWrap(line []cell, columns int) [][]cell {
lines = append(lines, line[offset:i])
offset = i
n = rw
} else if lastWhitespaceIndex != -1 && lastWhitespaceIndex+1 != i {
} else if lastWhitespaceIndex != -1 {
// if there is a space in the line and the line is not breaking at a space/hyphen
if line[lastWhitespaceIndex].chr == '-' {
// if break occurs at hyphen, we'll retain the hyphen
lines = append(lines, line[offset:lastWhitespaceIndex+1])
offset = lastWhitespaceIndex + 1
n = i - offset
} else {
// if break occurs at space, we'll omit the space
lines = append(lines, line[offset:lastWhitespaceIndex])
offset = lastWhitespaceIndex + 1
n = i - offset + 1
}
// Either way, continue *after* the break
offset = lastWhitespaceIndex + 1
n = 0
for _, c := range line[offset : i+1] {
n += runewidth.RuneWidth(c.chr)
}
} else {
// in this case we're breaking mid-word
Expand Down
43 changes: 42 additions & 1 deletion view_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,48 @@ func TestLineWrap(t *testing.T) {
expected: []string{
"one-two-",
"three-",
"four-five",
"four-",
"five",
},
},
{
name: "Several lines using all the available width",
line: "aaa bb cc ddd-ee ff",
columns: 5,
expected: []string{
"aaa",
"bb cc",
"ddd-",
"ee ff",
},
},
{
name: "Multi-cell runes",
line: "🐤🐤🐤 🐝🐝 🙉 🦊🦊🦊-🐬🐬 🦢🦢",
columns: 9,
expected: []string{
"🐤🐤🐤",
"🐝🐝 🙉",
"🦊🦊🦊-",
"🐬🐬 🦢🦢",
},
},
{
name: "Space in last column",
line: "hello world",
columns: 6,
expected: []string{
"hello",
"world",
},
},
{
name: "Hyphen in last column",
line: "hello-world",
columns: 6,
expected: []string{
"hello-",
"world",
},
},
{
Expand Down
Loading