Skip to content

Commit 8c3085a

Browse files
committed
feat(textarea): use a real cursor position
This sets the real cursor to its correct position when the cursor is moved.
1 parent 0719711 commit 8c3085a

File tree

1 file changed

+29
-4
lines changed

1 file changed

+29
-4
lines changed

textarea/textarea.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,12 @@ type Model struct {
272272
// Cursor row.
273273
row int
274274

275+
// The bubble offset relative to the parent bubble.
276+
offsetX, offsetY int
277+
278+
// The last recorded real cursor position.
279+
realCol, realRow int
280+
275281
// Last character offset, used to maintain state when the cursor is moved
276282
// vertically such that we can maintain the same navigating position.
277283
lastCharOffset int
@@ -358,6 +364,11 @@ func DefaultDarkStyles() Styles {
358364
return DefaultStyles(true)
359365
}
360366

367+
// SetOffset sets the offset of the textarea relative to the parent bubble.
368+
func (m *Model) SetOffset(x, y int) {
369+
m.offsetX, m.offsetY = x, y
370+
}
371+
361372
// SetValue sets the value of the text input.
362373
func (m *Model) SetValue(s string) {
363374
m.Reset()
@@ -1101,11 +1112,23 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
11011112

11021113
newRow, newCol := m.cursorLineNumber(), m.col
11031114
m.Cursor, cmd = m.Cursor.Update(msg)
1104-
if (newRow != oldRow || newCol != oldCol) && m.Cursor.Mode() == cursor.CursorBlink {
1115+
if cmd != nil {
1116+
cmds = append(cmds, cmd)
1117+
}
1118+
1119+
if m.Cursor.Mode() == cursor.CursorBlink && (newRow != oldRow || newCol != oldCol) {
11051120
m.Cursor.Blink = false
1106-
cmd = m.Cursor.BlinkCmd()
1121+
cmds = append(cmds, m.Cursor.BlinkCmd())
1122+
}
1123+
1124+
// Ensure the real cursor is at the correct position.
1125+
row := m.cursorLineNumber()
1126+
lineInfo := m.LineInfo()
1127+
realCol, realRow := m.offsetX+lineInfo.ColumnOffset, m.offsetY+row-m.viewport.YOffset
1128+
if realCol != m.realCol || realRow != m.realRow {
1129+
m.realCol, m.realRow = realCol, realRow
1130+
cmds = append(cmds, tea.SetCursorPosition(realCol, realRow))
11071131
}
1108-
cmds = append(cmds, cmd)
11091132

11101133
m.repositionView()
11111134

@@ -1183,7 +1206,9 @@ func (m Model) View() string {
11831206
wrappedLine = []rune(strings.TrimSuffix(string(wrappedLine), " "))
11841207
padding -= m.width - strwidth
11851208
}
1186-
if m.row == l && lineInfo.RowOffset == wl {
1209+
1210+
// We don't need to render the cursor if it's hidden.
1211+
if m.Cursor.Mode() != cursor.CursorHide && m.row == l && lineInfo.RowOffset == wl {
11871212
s.WriteString(style.Render(string(wrappedLine[:lineInfo.ColumnOffset])))
11881213
if m.col >= len(line) && lineInfo.CharOffset >= m.width {
11891214
m.Cursor.SetChar(" ")

0 commit comments

Comments
 (0)