Skip to content

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

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions