Skip to content

Commit bfe1b7c

Browse files
authored
text: Wrap* should account for display width; fixes #344 (#347)
1 parent 9dfb82e commit bfe1b7c

17 files changed

+427
-278
lines changed

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ require (
88
github.com/stretchr/testify v1.8.4
99
golang.org/x/sys v0.17.0
1010
golang.org/x/term v0.17.0
11+
golang.org/x/text v0.21.0
1112
)
1213

1314
require (

go.sum

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
1919
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
2020
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
2121
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
22-
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
2322
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
2423
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
2524
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
@@ -29,6 +28,8 @@ golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
2928
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
3029
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
3130
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
31+
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
32+
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
3233
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
3334
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3435
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

progress/indicator.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func indeterminateIndicatorMovingBackAndForth(indicator string) IndeterminateInd
9494

9595
if currentPosition == 0 {
9696
direction = 1
97-
} else if currentPosition+text.RuneWidthWithoutEscSequences(indicator) == maxLen {
97+
} else if currentPosition+text.StringWidthWithoutEscSequences(indicator) == maxLen {
9898
direction = -1
9999
}
100100
nextPosition += direction
@@ -113,7 +113,7 @@ func indeterminateIndicatorMovingLeftToRight(indicator string) IndeterminateIndi
113113
currentPosition := nextPosition
114114

115115
nextPosition++
116-
if nextPosition+text.RuneWidthWithoutEscSequences(indicator) > maxLen {
116+
if nextPosition+text.StringWidthWithoutEscSequences(indicator) > maxLen {
117117
nextPosition = 0
118118
}
119119

@@ -129,7 +129,7 @@ func indeterminateIndicatorMovingRightToLeft(indicator string) IndeterminateIndi
129129

130130
return func(maxLen int) IndeterminateIndicator {
131131
if nextPosition == -1 {
132-
nextPosition = maxLen - text.RuneWidthWithoutEscSequences(indicator)
132+
nextPosition = maxLen - text.StringWidthWithoutEscSequences(indicator)
133133
}
134134
currentPosition := nextPosition
135135
nextPosition--
@@ -165,7 +165,7 @@ func indeterminateIndicatorPacMan() IndeterminateIndicatorGenerator {
165165
if currentPosition == 0 {
166166
direction = 1
167167
indicator = pacManMovingRight
168-
} else if currentPosition+text.RuneWidthWithoutEscSequences(indicator) == maxLen {
168+
} else if currentPosition+text.StringWidthWithoutEscSequences(indicator) == maxLen {
169169
direction = -1
170170
indicator = pacManMovingLeft
171171
}

progress/progress.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -332,13 +332,13 @@ func (p *Progress) initForRender() {
332332
// calculate length of the actual progress bar by discounting the left/right
333333
// border/box chars
334334
p.lengthProgress = p.lengthTracker -
335-
text.RuneWidthWithoutEscSequences(p.style.Chars.BoxLeft) -
336-
text.RuneWidthWithoutEscSequences(p.style.Chars.BoxRight)
335+
text.StringWidthWithoutEscSequences(p.style.Chars.BoxLeft) -
336+
text.StringWidthWithoutEscSequences(p.style.Chars.BoxRight)
337337
p.lengthProgressOverall = p.lengthMessage +
338-
text.RuneWidthWithoutEscSequences(p.style.Options.Separator) +
338+
text.StringWidthWithoutEscSequences(p.style.Options.Separator) +
339339
p.lengthProgress + 1
340340
if p.style.Visibility.Percentage {
341-
p.lengthProgressOverall += text.RuneWidthWithoutEscSequences(
341+
p.lengthProgressOverall += text.StringWidthWithoutEscSequences(
342342
fmt.Sprintf(p.style.Options.PercentFormat, 0.0),
343343
)
344344
}

progress/render.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func (p *Progress) generateTrackerStrDeterminate(value int64, total int64, maxLe
129129
} else if pFinishedDotsFraction == 0 {
130130
pInProgress = ""
131131
}
132-
pFinishedStrLen := text.RuneWidthWithoutEscSequences(pFinished + pInProgress)
132+
pFinishedStrLen := text.StringWidthWithoutEscSequences(pFinished + pInProgress)
133133
if pFinishedStrLen < maxLen {
134134
pUnfinished = strings.Repeat(p.style.Chars.Unfinished, maxLen-pFinishedStrLen)
135135
}
@@ -149,8 +149,8 @@ func (p *Progress) generateTrackerStrIndeterminate(maxLen int) string {
149149
pUnfinished += strings.Repeat(p.style.Chars.Unfinished, indicator.Position)
150150
}
151151
pUnfinished += indicator.Text
152-
if text.RuneWidthWithoutEscSequences(pUnfinished) < maxLen {
153-
pUnfinished += strings.Repeat(p.style.Chars.Unfinished, maxLen-text.RuneWidthWithoutEscSequences(pUnfinished))
152+
if text.StringWidthWithoutEscSequences(pUnfinished) < maxLen {
153+
pUnfinished += strings.Repeat(p.style.Chars.Unfinished, maxLen-text.StringWidthWithoutEscSequences(pUnfinished))
154154
}
155155

156156
return p.style.Colors.Tracker.Sprintf("%s%s%s",
@@ -197,7 +197,7 @@ func (p *Progress) renderTracker(out *strings.Builder, t *Tracker, hint renderHi
197197
message = strings.ReplaceAll(message, "\t", " ")
198198
message = strings.ReplaceAll(message, "\r", "") // replace with text.ProcessCRLF?
199199
if p.lengthMessage > 0 {
200-
messageLen := text.RuneWidthWithoutEscSequences(message)
200+
messageLen := text.StringWidthWithoutEscSequences(message)
201201
if messageLen < p.lengthMessage {
202202
message = text.Pad(message, p.lengthMessage, ' ')
203203
} else {

table/render.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ func (t *Table) renderLine(out *strings.Builder, row rowStr, hint renderHint) {
227227

228228
func (t *Table) renderLineMergeOutputs(out *strings.Builder, outLine *strings.Builder) {
229229
outLineStr := outLine.String()
230-
if text.RuneWidthWithoutEscSequences(outLineStr) > t.style.Size.WidthMax {
230+
if text.StringWidthWithoutEscSequences(outLineStr) > t.style.Size.WidthMax {
231231
trimLength := t.style.Size.WidthMax - utf8.RuneCountInString(t.style.Box.UnfinishedRow)
232232
if trimLength > 0 {
233233
out.WriteString(text.Trim(outLineStr, trimLength))
@@ -392,15 +392,15 @@ func (t *Table) renderTitle(out *strings.Builder) {
392392
rowLength = wm
393393
}
394394
if t.style.Options.DrawBorder {
395-
lenBorder := rowLength - text.RuneWidthWithoutEscSequences(t.style.Box.TopLeft+t.style.Box.TopRight)
395+
lenBorder := rowLength - text.StringWidthWithoutEscSequences(t.style.Box.TopLeft+t.style.Box.TopRight)
396396
out.WriteString(colorsBorder.Sprint(t.style.Box.TopLeft))
397397
out.WriteString(colorsBorder.Sprint(text.RepeatAndTrim(t.style.Box.MiddleHorizontal, lenBorder)))
398398
out.WriteString(colorsBorder.Sprint(t.style.Box.TopRight))
399399
}
400400

401-
lenText := rowLength - text.RuneWidthWithoutEscSequences(t.style.Box.PaddingLeft+t.style.Box.PaddingRight)
401+
lenText := rowLength - text.StringWidthWithoutEscSequences(t.style.Box.PaddingLeft+t.style.Box.PaddingRight)
402402
if t.style.Options.DrawBorder {
403-
lenText -= text.RuneWidthWithoutEscSequences(t.style.Box.Left + t.style.Box.Right)
403+
lenText -= text.StringWidthWithoutEscSequences(t.style.Box.Left + t.style.Box.Right)
404404
}
405405
titleText := text.WrapText(t.title, lenText)
406406
for _, titleLine := range strings.Split(titleText, "\n") {

table/render_init.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func (t *Table) extractMaxColumnLengthsFromRow(row rowStr, mci mergedColumnIndic
7878

7979
func (t *Table) extractMaxColumnLengthsFromRowForMergedColumns(colIdx int, mergedColumnLength int, mci mergedColumnIndices) {
8080
numMergedColumns := mci.len(colIdx)
81-
mergedColumnLength -= (numMergedColumns - 1) * text.RuneWidthWithoutEscSequences(t.style.Box.MiddleSeparator)
81+
mergedColumnLength -= (numMergedColumns - 1) * text.StringWidthWithoutEscSequences(t.style.Box.MiddleSeparator)
8282
maxLengthSplitAcrossColumns := mergedColumnLength / numMergedColumns
8383
if maxLengthSplitAcrossColumns > t.maxColumnLengths[colIdx] {
8484
t.maxColumnLengths[colIdx] = maxLengthSplitAcrossColumns
@@ -177,22 +177,22 @@ func (t *Table) initForRenderHideColumns() {
177177
func (t *Table) initForRenderMaxRowLength() {
178178
t.maxRowLength = 0
179179
if t.autoIndex {
180-
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.PaddingLeft)
180+
t.maxRowLength += text.StringWidthWithoutEscSequences(t.style.Box.PaddingLeft)
181181
t.maxRowLength += len(fmt.Sprint(len(t.rows)))
182-
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.PaddingRight)
182+
t.maxRowLength += text.StringWidthWithoutEscSequences(t.style.Box.PaddingRight)
183183
if t.style.Options.SeparateColumns {
184-
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.MiddleSeparator)
184+
t.maxRowLength += text.StringWidthWithoutEscSequences(t.style.Box.MiddleSeparator)
185185
}
186186
}
187187
if t.style.Options.SeparateColumns {
188-
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.MiddleSeparator) * (t.numColumns - 1)
188+
t.maxRowLength += text.StringWidthWithoutEscSequences(t.style.Box.MiddleSeparator) * (t.numColumns - 1)
189189
}
190190
for _, maxColumnLength := range t.maxColumnLengths {
191-
maxColumnLength += text.RuneWidthWithoutEscSequences(t.style.Box.PaddingLeft + t.style.Box.PaddingRight)
191+
maxColumnLength += text.StringWidthWithoutEscSequences(t.style.Box.PaddingLeft + t.style.Box.PaddingRight)
192192
t.maxRowLength += maxColumnLength
193193
}
194194
if t.style.Options.DrawBorder {
195-
t.maxRowLength += text.RuneWidthWithoutEscSequences(t.style.Box.Left + t.style.Box.Right)
195+
t.maxRowLength += text.StringWidthWithoutEscSequences(t.style.Box.Left + t.style.Box.Right)
196196
}
197197
}
198198

@@ -282,7 +282,7 @@ func (t *Table) initForRenderRowPainterColors() {
282282
func (t *Table) initForRenderRowSeparator() {
283283
t.rowSeparator = make(rowStr, t.numColumns)
284284
for colIdx, maxColumnLength := range t.maxColumnLengths {
285-
maxColumnLength += text.RuneWidthWithoutEscSequences(t.style.Box.PaddingLeft + t.style.Box.PaddingRight)
285+
maxColumnLength += text.StringWidthWithoutEscSequences(t.style.Box.PaddingLeft + t.style.Box.PaddingRight)
286286
t.rowSeparator[colIdx] = text.RepeatAndTrim(t.style.Box.MiddleHorizontal, maxColumnLength)
287287
}
288288
}

0 commit comments

Comments
 (0)