summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoradamdotdevin <[email protected]>2025-08-12 07:52:09 -0500
committeradamdotdevin <[email protected]>2025-08-12 07:52:19 -0500
commitb2f2c9ac37e05455c282bf4106a5288d3a1478b3 (patch)
treeb6fc6977a630d01bfa3d88d763a6168f6f16b1d7
parent631722213b177a0cf4e0ebdbf1adf698730dac6a (diff)
downloadopencode-b2f2c9ac37e05455c282bf4106a5288d3a1478b3.tar.gz
opencode-b2f2c9ac37e05455c282bf4106a5288d3a1478b3.zip
fix: use real cursor instead of virtual cursor
-rw-r--r--packages/tui/internal/components/chat/editor.go6
-rw-r--r--packages/tui/internal/tui/tui.go48
2 files changed, 41 insertions, 13 deletions
diff --git a/packages/tui/internal/components/chat/editor.go b/packages/tui/internal/components/chat/editor.go
index 509de6244..980d5262c 100644
--- a/packages/tui/internal/components/chat/editor.go
+++ b/packages/tui/internal/components/chat/editor.go
@@ -31,6 +31,7 @@ type EditorComponent interface {
tea.Model
tea.ViewModel
Content() string
+ Cursor() *tea.Cursor
Lines() int
Value() string
Length() int
@@ -407,6 +408,10 @@ func (m *editorComponent) Content() string {
return content
}
+func (m *editorComponent) Cursor() *tea.Cursor {
+ return m.textarea.Cursor()
+}
+
func (m *editorComponent) View() string {
width := m.width
if m.app.Session.ID == "" {
@@ -694,6 +699,7 @@ func NewEditorComponent(app *app.App) EditorComponent {
ta.Prompt = " "
ta.ShowLineNumbers = false
ta.CharLimit = -1
+ ta.VirtualCursor = false
ta = updateTextareaStyles(ta)
m := &editorComponent{
diff --git a/packages/tui/internal/tui/tui.go b/packages/tui/internal/tui/tui.go
index 6a56e2012..7895adeac 100644
--- a/packages/tui/internal/tui/tui.go
+++ b/packages/tui/internal/tui/tui.go
@@ -59,6 +59,8 @@ const interruptDebounceTimeout = 1 * time.Second
const exitDebounceTimeout = 1 * time.Second
type Model struct {
+ tea.Model
+ tea.CursorModel
width, height int
app *app.App
modal layout.Modal
@@ -748,15 +750,17 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return a, tea.Batch(cmds...)
}
-func (a Model) View() string {
+func (a Model) View() (string, *tea.Cursor) {
t := theme.CurrentTheme()
var mainLayout string
+ var editorX int
+ var editorY int
if a.app.Session.ID == "" {
- mainLayout = a.home()
+ mainLayout, editorX, editorY = a.home()
} else {
- mainLayout = a.chat()
+ mainLayout, editorX, editorY = a.chat()
}
mainLayout = styles.NewStyle().
Background(t.Background()).
@@ -780,7 +784,12 @@ func (a Model) View() string {
if theme.CurrentThemeUsesAnsiColors() {
mainLayout = util.ConvertRGBToAnsi16Colors(mainLayout)
}
- return mainLayout + "\n" + a.status.View()
+
+ cursor := a.editor.Cursor()
+ cursor.Position.X += editorX
+ cursor.Position.Y += editorY
+
+ return mainLayout + "\n" + a.status.View(), cursor
}
func (a Model) Cleanup() {
@@ -807,7 +816,7 @@ func (a Model) openFile(filepath string) (tea.Model, tea.Cmd) {
return a, cmd
}
-func (a Model) home() string {
+func (a Model) home() (string, int, int) {
t := theme.CurrentTheme()
effectiveWidth := a.width - 4
baseStyle := styles.NewStyle().Background(t.Background())
@@ -899,14 +908,21 @@ func (a Model) home() string {
styles.WhitespaceStyle(t.Background()),
)
- editorX := (effectiveWidth - editorWidth) / 2
+ editorX := max(0, (effectiveWidth-editorWidth)/2)
editorY := (a.height / 2) + (mainHeight / 2) - 2
if editorLines > 1 {
+ content := a.editor.Content()
+ editorHeight := lipgloss.Height(content)
+
+ if editorY+editorHeight > a.height {
+ difference := (editorY + editorHeight) - a.height
+ editorY -= difference
+ }
mainLayout = layout.PlaceOverlay(
editorX,
editorY,
- a.editor.Content(),
+ content,
mainLayout,
)
}
@@ -924,10 +940,10 @@ func (a Model) home() string {
)
}
- return mainLayout
+ return mainLayout, editorX + 5, editorY + 2
}
-func (a Model) chat() string {
+func (a Model) chat() (string, int, int) {
effectiveWidth := a.width - 4
t := theme.CurrentTheme()
editorView := a.editor.View()
@@ -944,14 +960,20 @@ func (a Model) chat() string {
)
mainLayout := messagesView + "\n" + editorView
- editorX := (effectiveWidth - editorWidth) / 2
+ editorX := max(0, (effectiveWidth-editorWidth)/2)
+ editorY := a.height - editorHeight
if lines > 1 {
- editorY := a.height - editorHeight
+ content := a.editor.Content()
+ editorHeight := lipgloss.Height(content)
+ if editorY+editorHeight > a.height {
+ difference := (editorY + editorHeight) - a.height
+ editorY -= difference
+ }
mainLayout = layout.PlaceOverlay(
editorX,
editorY,
- a.editor.Content(),
+ content,
mainLayout,
)
}
@@ -970,7 +992,7 @@ func (a Model) chat() string {
)
}
- return mainLayout
+ return mainLayout, editorX + 5, editorY + 2
}
func (a Model) executeCommand(command commands.Command) (tea.Model, tea.Cmd) {