Skip to content

textarea: Public API for document-level cursor navigation #1684

@Javier162380

Description

@Javier162380

Description

Vim has gg and G, VSCode has Ctrl+Home and Ctrl+Endtextarea has... keyboard shortcuts only.

Currently, there's no programmatic way to move the cursor to the start or end of a multi-line document in textarea. The component provides CursorStart() and CursorEnd(), but these only work for the current line. For document-level navigation, the functionality exists internally (moveToBegin() and moveToEnd()) but is private.

The Problem

When wrapping textarea in custom components, you often need to control cursor position programmatically:

ta := textarea.New()
ta.SetValue("Line 1\nLine 2\nLine 3")
// After SetValue, cursor is at (row 2, col 6) — the end

// Try to go to document start...
ta.CursorStart()  // Only goes to (row 2, col 0) — still on last line!

// Current workaround: simulate a keypress 🤮
msg := tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{'<'}, Alt: true}
ta, _ = ta.Update(msg)  // Finally at (row 0, col 0)

This workaround is:

  • Non-discoverable (you need to know the internal keybindings)
  • Fragile (relies on implementation details)
  • Verbose (requires constructing KeyMsg structs)
  • Unintuitive (simulating user input for programmatic control)

Proposed Solution

Add two public methods mirroring the existing private ones:

 // GotoTop moves the cursor to the beginning of the document.
 func (m *Model) GotoTop() {
     m.row = 0
     m.SetCursor(0)
 }

 // GotoBottom moves the cursor to the end of the document.
 func (m *Model) GotoBottom() {
     m.row = len(m.value) - 1
     m.SetCursor(len(m.value[m.row]))
 }

 Usage:
 ta := textarea.New()
 ta.SetValue(longContent)
 ta.GotoTop()    // Clean and obvious
 ta.GotoBottom() // Just works

Benefits

  • Consistency — Matches the pattern of other cursor methods (CursorUp, CursorDown, etc.)
  • Discoverability — Shows up in autocomplete and godoc
  • Zero breaking changes — Pure API addition
  • Already implemented — Just needs to be exposed

Use Cases

  1. Content loading — Reset cursor to top when loading new content
  2. Custom navigation — Implement vim-style g/G or other shortcuts
  3. Form helpers — Jump to end of document before appending
  4. Testing — Set predictable cursor positions in tests

Questions

  1. Naming: Would you prefer GotoTop/GotoBottom, MoveToStart/MoveToEnd, or something else?
  2. Implementation: Should we just capitalize the existing moveToBegin/moveToEnd, or create new methods?
  3. Viewport scrolling: Should these methods also scroll the viewport to show the new cursor position, or leave that separate?

Happy to submit a PR once we align on the approach!

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions