@@ -3,6 +3,7 @@ package textarea
33import (
44 "crypto/sha256"
55 "fmt"
6+ "strconv"
67 "strings"
78 "unicode"
89
@@ -14,6 +15,7 @@ import (
1415 "github.com/charmbracelet/bubbles/viewport"
1516 tea "github.com/charmbracelet/bubbletea"
1617 "github.com/charmbracelet/lipgloss"
18+ "github.com/charmbracelet/x/ansi"
1719 rw "github.com/mattn/go-runewidth"
1820 "github.com/rivo/uniseg"
1921)
@@ -1170,36 +1172,71 @@ func (m Model) getPromptString(displayLine int) (prompt string) {
11701172func (m Model ) placeholderView () string {
11711173 var (
11721174 s strings.Builder
1173- p = rw . Truncate ( rw . Truncate ( m .Placeholder , m . width , "..." ), m . width , "" )
1175+ p = m .Placeholder
11741176 style = m .style .Placeholder .Inline (true )
11751177 )
11761178
1177- prompt := m .getPromptString (0 )
1178- prompt = m .style .Prompt .Render (prompt )
1179- s .WriteString (m .style .CursorLine .Render (prompt ))
1179+ // word wrap lines
1180+ pwordwrap := ansi .Wordwrap (p , m .width , "" )
1181+ // wrap lines (handles lines that could not be word wrapped)
1182+ pwrap := ansi .Hardwrap (pwordwrap , m .width , true )
1183+ // split string by new lines
1184+ plines := strings .Split (strings .TrimSpace (pwrap ), "\n " )
11801185
1181- if m .ShowLineNumbers {
1182- s .WriteString (m .style .CursorLine .Render (m .style .CursorLineNumber .Render ((fmt .Sprintf (m .lineNumberFormat , 1 )))))
1183- }
1184-
1185- m .Cursor .TextStyle = m .style .Placeholder
1186- m .Cursor .SetChar (string (p [0 ]))
1187- s .WriteString (m .style .CursorLine .Render (m .Cursor .View ()))
1188-
1189- // The rest of the placeholder text
1190- s .WriteString (m .style .CursorLine .Render (style .Render (p [1 :] + strings .Repeat (" " , max (0 , m .width - uniseg .StringWidth (p ))))))
1186+ for i := 0 ; i < m .height ; i ++ {
1187+ lineStyle := m .style .Placeholder
1188+ lineNumberStyle := m .style .LineNumber
1189+ if len (plines ) > i {
1190+ lineStyle = m .style .CursorLine
1191+ lineNumberStyle = m .style .CursorLineNumber
1192+ }
11911193
1192- // The rest of the new lines
1193- for i := 1 ; i < m .height ; i ++ {
1194- s .WriteRune ('\n' )
1194+ // render prompt
11951195 prompt := m .getPromptString (i )
11961196 prompt = m .style .Prompt .Render (prompt )
1197- s .WriteString (prompt )
1197+ s .WriteString (lineStyle . Render ( prompt ) )
11981198
1199+ // when show line numbers enabled:
1200+ // - render line number for only the cursor line
1201+ // - indent other placeholder lines
1202+ // this is consistent with vim with line numbers enabled
11991203 if m .ShowLineNumbers {
1204+ var ln string
1205+
1206+ switch {
1207+ case i == 0 :
1208+ ln = strconv .Itoa (i + 1 )
1209+ fallthrough
1210+ case len (plines ) > i :
1211+ s .WriteString (lineStyle .Render (lineNumberStyle .Render (fmt .Sprintf (m .lineNumberFormat , ln ))))
1212+ default :
1213+ }
1214+ }
1215+
1216+ switch {
1217+ // first line
1218+ case i == 0 :
1219+ // first character of first line as cursor with character
1220+ m .Cursor .TextStyle = m .style .Placeholder
1221+ m .Cursor .SetChar (string (plines [0 ][0 ]))
1222+ s .WriteString (lineStyle .Render (m .Cursor .View ()))
1223+
1224+ // the rest of the first line
1225+ s .WriteString (lineStyle .Render (style .Render (plines [0 ][1 :] + strings .Repeat (" " , max (0 , m .width - uniseg .StringWidth (plines [0 ]))))))
1226+ // remaining lines
1227+ case len (plines ) > i :
1228+ // current line placeholder text
1229+ if len (plines ) > i {
1230+ s .WriteString (lineStyle .Render (style .Render (plines [i ] + strings .Repeat (" " , max (0 , m .width - uniseg .StringWidth (plines [i ]))))))
1231+ }
1232+ default :
1233+ // end of line buffer character
12001234 eob := m .style .EndOfBuffer .Render (string (m .EndOfBufferCharacter ))
12011235 s .WriteString (eob )
12021236 }
1237+
1238+ // terminate with new line
1239+ s .WriteRune ('\n' )
12031240 }
12041241
12051242 m .viewport .SetContent (s .String ())
0 commit comments