Preserve UTF-8 when truncating input status

This commit is contained in:
Brandon McGinty (chatgpt)
2026-08-09 15:12:53 -04:00
committed by Brandon McGinty
parent 5480dee0fd
commit cbc6369071
2 changed files with 20 additions and 3 deletions
+10
View File
@@ -5,6 +5,7 @@ import (
"strings" "strings"
"testing" "testing"
"time" "time"
"unicode/utf8"
"git.stormux.org/storm/barnard/gumble/gumble" "git.stormux.org/storm/barnard/gumble/gumble"
) )
@@ -57,6 +58,15 @@ func TestNotificationExpansionIsSinglePassAndNotifyDoesNotBlock(t *testing.T) {
// and renderer resources. Cleanup must be safe for repeated disconnects. // and renderer resources. Cleanup must be safe for repeated disconnects.
// Regression: user and channel names in the navigation tree bypassed message // Regression: user and channel names in the navigation tree bypassed message
// escaping and could still carry terminal control characters. // escaping and could still carry terminal control characters.
// Regression: status truncation used byte indexes and could create invalid
// UTF-8 when a non-ASCII user or channel name exceeded the display limit.
func TestTruncateInputStatusPreservesUTF8(t *testing.T) {
got := truncateInputStatus(strings.Repeat("é", 21))
if !utf8.ValidString(got) || utf8.RuneCountInString(got) != 21 {
t.Fatalf("invalid truncation %q", got)
}
}
func TestTreeItemSanitizesServerNames(t *testing.T) { func TestTreeItemSanitizesServerNames(t *testing.T) {
item := TreeItem{Channel: &gumble.Channel{Name: "\x1b[2Jroom"}} item := TreeItem{Channel: &gumble.Channel{Name: "\x1b[2Jroom"}}
if got := item.String(); got != "#[2Jroom" { if got := item.String(); got != "#[2Jroom" {
+10 -3
View File
@@ -62,14 +62,21 @@ func (b *Barnard) GetInputStatus() string {
} }
func (b *Barnard) UpdateInputStatus(status string) { func (b *Barnard) UpdateInputStatus(status string) {
if len(status) > 20 { status = truncateInputStatus(status)
status = status[:17] + "..." + "]"
}
b.UiInputStatus.Text = status b.UiInputStatus.Text = status
b.RebuildUserChannelTreePreservingSelection() b.RebuildUserChannelTreePreservingSelection()
b.Ui.Refresh() b.Ui.Refresh()
} }
// truncateInputStatus limits terminal cells without splitting UTF-8 runes.
func truncateInputStatus(status string) string {
chars := []rune(status)
if len(chars) > 20 {
return string(chars[:17]) + "..." + "]"
}
return status
}
func (b *Barnard) AddOutputLine(line string) { func (b *Barnard) AddOutputLine(line string) {
now := time.Now() now := time.Now()
b.UiOutput.AddLine(fmt.Sprintf("%s [%02d:%02d:%02d]", line, now.Hour(), now.Minute(), now.Second())) b.UiOutput.AddLine(fmt.Sprintf("%s [%02d:%02d:%02d]", line, now.Hour(), now.Minute(), now.Second()))