feat: Ctrl+Home / Ctrl+End jump to document start / end
dabc84eb33cfc6b0142323bb1b316179606109d2
humdrum <me@humdrum.me> · 2026-06-29 08:22
parent ff079ce7
feat: Ctrl+Home / Ctrl+End jump to document start / end MoveDocStart/MoveDocEnd bound to Ctrl+Home/Ctrl+End — the terminal maps Cmd+Up/Down to these sequences for macOS-style document navigation.
2 files changed
internal/editor/editor.go +20 −0
@@ -127,6 +127,22 @@ e.Scroll = max
}
}
+// MoveDocStart jumps to the very start of the document (Cmd+Up via the terminal).
+func (e *Editor) MoveDocStart() {
+ e.Cursor = Position{Row: 0, Col: 0}
+ e.setGoal()
+ e.followCursor()
+}
+
+// MoveDocEnd jumps to the end of the last line (Cmd+Down via the terminal).
+func (e *Editor) MoveDocEnd() {
+ last := len(e.Lines) - 1
+ e.Cursor.Row = last
+ e.Cursor.Col = len([]rune(e.Lines[last]))
+ e.setGoal()
+ e.followCursor()
+}
+
func isWordSpace(r rune) bool { return r == ' ' || r == '\t' }
// MoveWordLeft moves to the start of the previous word (Alt+Left).
@@ -468,6 +484,10 @@ case tea.KeyHome:
e.MoveHome()
case tea.KeyEnd:
e.MoveEnd()
+ case tea.KeyCtrlHome:
+ e.MoveDocStart()
+ case tea.KeyCtrlEnd:
+ e.MoveDocEnd()
case tea.KeyTab:
e.InsertRune('\t')
case tea.KeyCtrlU:
internal/editor/editor_test.go +13 −0
@@ -412,3 +412,16 @@ if e.Cursor.Col != 16 {
t.Errorf("Alt+f → col %d, want 16 (end of gamma)", e.Cursor.Col)
}
}
+
+func TestDocStartEnd(t *testing.T) {
+ e := newEditorWith("first", "middle", "last line")
+ e.Cursor = Position{Row: 1, Col: 2}
+ e.HandleKey(tea.KeyMsg{Type: tea.KeyCtrlEnd})
+ if e.Cursor != (Position{Row: 2, Col: 9}) {
+ t.Errorf("Ctrl+End → %+v, want {2 9}", e.Cursor)
+ }
+ e.HandleKey(tea.KeyMsg{Type: tea.KeyCtrlHome})
+ if e.Cursor != (Position{Row: 0, Col: 0}) {
+ t.Errorf("Ctrl+Home → %+v, want {0 0}", e.Cursor)
+ }
+}