fix(textinput): improve placeholder (#768)

similar to #767 but for textinputs
This commit is contained in:
Carlos Alexandro Becker
2025-10-01 10:22:53 -03:00
committed by GitHub
parent d6934a175b
commit 49ff5c03b7
2 changed files with 49 additions and 19 deletions
+11 -19
View File
@@ -14,6 +14,7 @@ import (
"github.com/charmbracelet/bubbles/runeutil"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/x/ansi"
rw "github.com/mattn/go-runewidth"
"github.com/rivo/uniseg"
)
@@ -703,40 +704,31 @@ func (m Model) placeholderView() string {
var (
v string
style = m.PlaceholderStyle.Inline(true).Render
p = m.PromptStyle.Render(m.Prompt)
)
p := make([]rune, m.Width+1)
copy(p, []rune(m.Placeholder))
m.Cursor.TextStyle = m.PlaceholderStyle
m.Cursor.SetChar(string(p[:1]))
first, rest, _, _ := uniseg.FirstGraphemeClusterInString(m.Placeholder, 0)
m.Cursor.SetChar(first)
v += m.Cursor.View()
// If the entire placeholder is already set and no padding is needed, finish
if m.Width < 1 && len(p) <= 1 {
if m.Width < 1 && uniseg.StringWidth(rest) <= 1 {
return m.PromptStyle.Render(m.Prompt) + v
}
// If Width is set then size placeholder accordingly
if m.Width > 0 {
// available width is width - len + cursor offset of 1
minWidth := lipgloss.Width(m.Placeholder)
availWidth := m.Width - minWidth + 1
// if width < len, 'subtract'(add) number to len and dont add padding
if availWidth < 0 {
minWidth += availWidth
availWidth = 0
}
// append placeholder[len] - cursor, append padding
v += style(string(p[1:minWidth]))
v += style(strings.Repeat(" ", availWidth))
width := m.Width - lipgloss.Width(p) - lipgloss.Width(v)
placeholderRest := ansi.Truncate(rest, width, "…")
availWidth := max(0, width-lipgloss.Width(placeholderRest))
v += style(placeholderRest) + strings.Repeat(" ", availWidth)
} else {
// if there is no width, the placeholder can be any length
v += style(string(p[1:]))
v += style(rest)
}
return m.PromptStyle.Render(m.Prompt) + v
return p + v
}
// Blink is a command used to initialize cursor blinking.
+38
View File
@@ -5,6 +5,8 @@ import (
"strconv"
"strings"
"testing"
tea "github.com/charmbracelet/bubbletea"
)
func Test_CurrentSuggestion(t *testing.T) {
@@ -46,6 +48,30 @@ func Test_SlicingOutsideCap(t *testing.T) {
textinput.View()
}
func TestChinesePlaceholder(t *testing.T) {
textinput := New()
textinput.Placeholder = "输入消息..."
textinput.Width = 20
got := textinput.View()
expected := "> 输入消息... "
if got != expected {
t.Fatalf("expected %q but got %q", expected, got)
}
}
func TestPlaceholderTruncate(t *testing.T) {
textinput := New()
textinput.Placeholder = "A very long placeholder, or maybe not so much"
textinput.Width = 10
got := textinput.View()
expected := "> A very …"
if got != expected {
t.Fatalf("expected %q but got %q", expected, got)
}
}
func ExampleValidateFunc() {
creditCardNumber := New()
creditCardNumber.Placeholder = "4505 **** **** 1234"
@@ -78,3 +104,15 @@ func ExampleValidateFunc() {
return err
}
}
func keyPress(key rune) tea.Msg {
return tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{key}, Alt: false}
}
func sendString(m Model, str string) Model {
for _, k := range str {
m, _ = m.Update(keyPress(k))
}
return m
}