return fmt.Errorf("invalid rectangle character %q, this character occupies %d cells, the implementation only supports half-width runes that occupy exactly one cell", opt.char, cells)
// text.go contains code that prints UTF-8 encoded strings on the canvas.
18
18
19
19
import (
20
+
"bytes"
20
21
"fmt"
21
22
"image"
22
-
"unicode/utf8"
23
23
24
+
runewidth "github.com/mattn/go-runewidth"
24
25
"github.com/mum4k/termdash/canvas"
25
26
"github.com/mum4k/termdash/cell"
26
27
)
skipped 76 lines
103
104
})
104
105
}
105
106
107
+
// trimToCells trims the provided text so that it fits the specified amount of cells.
108
+
func trimToCells(text string, maxCells int, om OverrunMode) string {
109
+
if maxCells < 1 {
110
+
return ""
111
+
}
112
+
113
+
var b bytes.Buffer
114
+
cells := 0
115
+
for _, r := range text {
116
+
rw := runewidth.RuneWidth(r)
117
+
if cells+rw >= maxCells {
118
+
switch {
119
+
case om == OverrunModeTrim && rw == 1:
120
+
b.WriteRune(r)
121
+
case om == OverrunModeThreeDot:
122
+
b.WriteRune('…')
123
+
}
124
+
break
125
+
}
126
+
b.WriteRune(r)
127
+
cells += rw
128
+
}
129
+
return b.String()
130
+
}
131
+
106
132
// bounds enforces the text bounds based on the specified overrun mode.
107
133
// Returns test that can be safely drawn within the bounds.
108
-
func bounds(text string, maxRunes int, om OverrunMode) (string, error) {
109
-
runes := utf8.RuneCountInString(text)
110
-
if runes <= maxRunes {
134
+
func bounds(text string, maxCells int, om OverrunMode) (string, error) {
135
+
cells := runewidth.StringWidth(text)
136
+
if cells <= maxCells {
111
137
return text, nil
112
138
}
113
139
114
140
switch om {
115
141
case OverrunModeStrict:
116
-
return "", fmt.Errorf("the requested text %q takes %d runes to draw, space is available for only %d runes and overrun mode is %v", text, runes, maxRunes, om)
117
-
case OverrunModeTrim:
118
-
return text[:maxRunes], nil
119
-
120
-
case OverrunModeThreeDot:
121
-
return fmt.Sprintf("%s…", text[:maxRunes-1]), nil
142
+
return "", fmt.Errorf("the requested text %q takes %d cells to draw, space is available for only %d cells and overrun mode is %v", text, cells, maxCells, om)
panic(fmt.Errorf("invalid scroll up marker, it occupies %d cells, the implementation only supports scroll markers that occupy exactly one cell", cells))
130
+
}
131
+
return true, nil
132
+
}
133
+
return false, nil
134
+
}
135
+
136
+
// drawScrollDown draws the scroll down marker on the last line if there is
137
+
// more text "below" the canvas due to the scrolling position. Returns true if
panic(fmt.Errorf("invalid scroll down marker, it occupies %d cells, the implementation only supports scroll markers that occupy exactly one cell", cells))
149
+
}
150
+
return true, nil
151
+
}
152
+
return false, nil
153
+
}
154
+
128
155
// draw draws the text context on the canvas starting at the specified line.
129
-
// Argument starts are the starting positions of all the lines in the text.