From 8b55efb2944ed8eb81df685f8dcfabbbf8897698 Mon Sep 17 00:00:00 2001 From: Carlos Alexandro Becker Date: Mon, 31 Mar 2025 19:55:03 -0300 Subject: [PATCH 1/2] fix(textarea): placeholder with chinese chars (#767) --- go.mod | 2 +- textarea/textarea.go | 6 ++++-- textarea/textarea_test.go | 22 ++++++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e316a0a..42d6dd9 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ toolchain go1.23.7 require ( github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 + github.com/aymanbagabas/go-udiff v0.2.0 github.com/charmbracelet/bubbletea v1.3.4 github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss v1.1.0 @@ -22,7 +23,6 @@ require ( require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/aymanbagabas/go-udiff v0.2.0 // indirect github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect github.com/charmbracelet/x/term v0.2.1 // indirect diff --git a/textarea/textarea.go b/textarea/textarea.go index 620201c..d82ae97 100644 --- a/textarea/textarea.go +++ b/textarea/textarea.go @@ -1271,11 +1271,13 @@ func (m Model) placeholderView() string { case i == 0: // first character of first line as cursor with character m.Cursor.TextStyle = m.style.computedPlaceholder() - m.Cursor.SetChar(string(plines[0][0])) + + ch, rest, _, _ := uniseg.FirstGraphemeClusterInString(plines[0], 0) + m.Cursor.SetChar(ch) s.WriteString(lineStyle.Render(m.Cursor.View())) // the rest of the first line - s.WriteString(lineStyle.Render(style.Render(plines[0][1:] + strings.Repeat(" ", max(0, m.width-uniseg.StringWidth(plines[0])))))) + s.WriteString(lineStyle.Render(style.Render(rest))) // remaining lines case len(plines) > i: // current line placeholder text diff --git a/textarea/textarea_test.go b/textarea/textarea_test.go index 9b272c5..ea3e3cc 100644 --- a/textarea/textarea_test.go +++ b/textarea/textarea_test.go @@ -6,6 +6,7 @@ import ( "unicode" "github.com/MakeNowJust/heredoc" + "github.com/aymanbagabas/go-udiff" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/x/ansi" @@ -1671,6 +1672,26 @@ func TestView(t *testing.T) { `), }, }, + { + name: "placeholder chinese character", + modelFunc: func(m Model) Model { + m.Placeholder = "输入消息..." + m.ShowLineNumbers = true + m.SetWidth(20) + return m + }, + want: want{ + view: heredoc.Doc(` + > 1 输入消息... + > + > + > + > + > + + `), + }, + }, } for _, tt := range tests { @@ -1689,6 +1710,7 @@ func TestView(t *testing.T) { wantView := stripString(tt.want.view) if view != wantView { + t.Log(udiff.Unified("expected", "got", wantView, view)) t.Fatalf("Want:\n%v\nGot:\n%v\n", wantView, view) } From 3e2a8caedbb58cb51dfa6e2fea042460ee5012b6 Mon Sep 17 00:00:00 2001 From: Andrey Nering Date: Thu, 10 Apr 2025 10:33:14 -0300 Subject: [PATCH 2/2] chore: fix lint warning --- textarea/textarea.go | 2 +- textinput/textinput.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/textarea/textarea.go b/textarea/textarea.go index d82ae97..61c5537 100644 --- a/textarea/textarea.go +++ b/textarea/textarea.go @@ -653,7 +653,7 @@ func (m *Model) deleteWordLeft() { // Linter note: it's critical that we acquire the initial cursor position // here prior to altering it via SetCursor() below. As such, moving this // call into the corresponding if clause does not apply here. - oldCol := m.col //nolint:ifshort + oldCol := m.col m.SetCursor(m.col - 1) for unicode.IsSpace(m.value[m.row][m.col]) { diff --git a/textinput/textinput.go b/textinput/textinput.go index 84cbbc9..9c6666e 100644 --- a/textinput/textinput.go +++ b/textinput/textinput.go @@ -400,7 +400,7 @@ func (m *Model) deleteWordBackward() { // Linter note: it's critical that we acquire the initial cursor position // here prior to altering it via SetCursor() below. As such, moving this // call into the corresponding if clause does not apply here. - oldPos := m.pos //nolint:ifshort + oldPos := m.pos m.SetCursor(m.pos - 1) for unicode.IsSpace(m.value[m.pos]) {