@@ -231,8 +231,8 @@ type Model struct {
231
231
// when switching focus states.
232
232
activeStyle * StyleState
233
233
234
- // Cursor is the text area cursor.
235
- Cursor cursor.Model
234
+ // VirtualCursor is the text area cursor.
235
+ VirtualCursor cursor.Model
236
236
237
237
// CharLimit is the maximum number of characters this input element will
238
238
// accept. If 0 or less, there's no limit.
@@ -305,7 +305,7 @@ func New() Model {
305
305
cache : memoization.NewMemoCache [line , [][]rune ](maxLines ),
306
306
EndOfBufferCharacter : ' ' ,
307
307
ShowLineNumbers : true ,
308
- Cursor : cur ,
308
+ VirtualCursor : cur ,
309
309
KeyMap : DefaultKeyMap (),
310
310
311
311
value : make ([][]rune , minHeight , maxLines ),
@@ -600,15 +600,15 @@ func (m Model) Focused() bool {
600
600
func (m * Model ) Focus () tea.Cmd {
601
601
m .focus = true
602
602
m .activeStyle = & m .Styles .Focused
603
- return m .Cursor .Focus ()
603
+ return m .VirtualCursor .Focus ()
604
604
}
605
605
606
606
// Blur removes the focus state on the model. When the model is blurred it can
607
607
// not receive keyboard input and the cursor will be hidden.
608
608
func (m * Model ) Blur () {
609
609
m .focus = false
610
610
m .activeStyle = & m .Styles .Blurred
611
- m .Cursor .Blur ()
611
+ m .VirtualCursor .Blur ()
612
612
}
613
613
614
614
// Reset sets the input to its default state with no input.
@@ -976,7 +976,7 @@ func (m *Model) SetHeight(h int) {
976
976
// Update is the Bubble Tea update loop.
977
977
func (m Model ) Update (msg tea.Msg ) (Model , tea.Cmd ) {
978
978
if ! m .focus {
979
- m .Cursor .Blur ()
979
+ m .VirtualCursor .Blur ()
980
980
return m , nil
981
981
}
982
982
@@ -1098,10 +1098,10 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
1098
1098
cmds = append (cmds , cmd )
1099
1099
1100
1100
newRow , newCol := m .cursorLineNumber (), m .col
1101
- m .Cursor , cmd = m .Cursor .Update (msg )
1102
- if (newRow != oldRow || newCol != oldCol ) && m .Cursor .Mode () == cursor .CursorBlink {
1103
- m .Cursor .Blink = false
1104
- cmd = m .Cursor .BlinkCmd ()
1101
+ m .VirtualCursor , cmd = m .VirtualCursor .Update (msg )
1102
+ if (newRow != oldRow || newCol != oldCol ) && m .VirtualCursor .Mode () == cursor .CursorBlink {
1103
+ m .VirtualCursor .Blink = false
1104
+ cmd = m .VirtualCursor .BlinkCmd ()
1105
1105
}
1106
1106
cmds = append (cmds , cmd )
1107
1107
@@ -1115,7 +1115,7 @@ func (m Model) View() string {
1115
1115
if m .Value () == "" && m .row == 0 && m .col == 0 && m .Placeholder != "" {
1116
1116
return m .placeholderView ()
1117
1117
}
1118
- m .Cursor .TextStyle = m .activeStyle .computedCursorLine ()
1118
+ m .VirtualCursor .TextStyle = m .activeStyle .computedCursorLine ()
1119
1119
1120
1120
var (
1121
1121
s strings.Builder
@@ -1184,11 +1184,11 @@ func (m Model) View() string {
1184
1184
if m .row == l && lineInfo .RowOffset == wl {
1185
1185
s .WriteString (style .Render (string (wrappedLine [:lineInfo .ColumnOffset ])))
1186
1186
if m .col >= len (line ) && lineInfo .CharOffset >= m .width {
1187
- m .Cursor .SetChar (" " )
1188
- s .WriteString (m .Cursor .View ())
1187
+ m .VirtualCursor .SetChar (" " )
1188
+ s .WriteString (m .VirtualCursor .View ())
1189
1189
} else {
1190
- m .Cursor .SetChar (string (wrappedLine [lineInfo .ColumnOffset ]))
1191
- s .WriteString (style .Render (m .Cursor .View ()))
1190
+ m .VirtualCursor .SetChar (string (wrappedLine [lineInfo .ColumnOffset ]))
1191
+ s .WriteString (style .Render (m .VirtualCursor .View ()))
1192
1192
s .WriteString (style .Render (string (wrappedLine [lineInfo .ColumnOffset + 1 :])))
1193
1193
}
1194
1194
} else {
@@ -1291,9 +1291,9 @@ func (m Model) placeholderView() string {
1291
1291
// first line
1292
1292
case i == 0 :
1293
1293
// first character of first line as cursor with character
1294
- m .Cursor .TextStyle = m .activeStyle .computedPlaceholder ()
1295
- m .Cursor .SetChar (string (plines [0 ][0 ]))
1296
- s .WriteString (lineStyle .Render (m .Cursor .View ()))
1294
+ m .VirtualCursor .TextStyle = m .activeStyle .computedPlaceholder ()
1295
+ m .VirtualCursor .SetChar (string (plines [0 ][0 ]))
1296
+ s .WriteString (lineStyle .Render (m .VirtualCursor .View ()))
1297
1297
1298
1298
// the rest of the first line
1299
1299
s .WriteString (lineStyle .Render (style .Render (plines [0 ][1 :] + strings .Repeat (" " , max (0 , m .width - uniseg .StringWidth (plines [0 ]))))))
@@ -1322,6 +1322,19 @@ func Blink() tea.Msg {
1322
1322
return cursor .Blink ()
1323
1323
}
1324
1324
1325
+ // Cursor returns the current cursor position accounting any
1326
+ // soft-wrapped lines.
1327
+ func (m Model ) Cursor () * tea.Cursor {
1328
+ lineInfo := m .LineInfo ()
1329
+ x , y := lineInfo .CharOffset , m .cursorLineNumber ()- m .viewport .YOffset
1330
+
1331
+ // TODO: sort out where these properties live.
1332
+ c := tea .NewCursor (x , y )
1333
+ c .Blink = true
1334
+ c .Color = m .VirtualCursor .Style .GetForeground ()
1335
+ return c
1336
+ }
1337
+
1325
1338
func (m Model ) memoizedWrap (runes []rune , width int ) [][]rune {
1326
1339
input := line {runes : runes , width : width }
1327
1340
if v , ok := m .cache .Get (input ); ok {
0 commit comments