diff --git a/internal/action/actions.go b/internal/action/actions.go index 97074653..ed4151f8 100644 --- a/internal/action/actions.go +++ b/internal/action/actions.go @@ -291,6 +291,19 @@ func (h *BufPane) StartOfText() bool { return true } +// StartOfTextToggle toggles the cursor between the start of the text of the line +// and the start of the line +func (h *BufPane) StartOfTextToggle() bool { + h.Cursor.Deselect(true) + if h.Cursor.IsStartOfText() { + h.Cursor.Start() + } else { + h.Cursor.StartOfText() + } + h.Relocate() + return true +} + // StartOfLine moves the cursor to the start of the line func (h *BufPane) StartOfLine() bool { h.Cursor.Deselect(true) @@ -325,6 +338,23 @@ func (h *BufPane) SelectToStartOfText() bool { return true } +// SelectToStartOfTextToggle toggles the selection between the start of the text +// on the current line and the start of the line +func (h *BufPane) SelectToStartOfTextToggle() bool { + if !h.Cursor.HasSelection() { + h.Cursor.OrigSelection[0] = h.Cursor.Loc + } + if h.Cursor.IsStartOfText() { + h.Cursor.Start() + } else { + h.Cursor.StartOfText() + } + h.Cursor.SelectTo(h.Cursor.Loc) + h.Relocate() + return true +} + + // SelectToStartOfLine selects to the start of the current line func (h *BufPane) SelectToStartOfLine() bool { if !h.Cursor.HasSelection() { diff --git a/internal/action/bufpane.go b/internal/action/bufpane.go index 91e2040e..07ba5d68 100644 --- a/internal/action/bufpane.go +++ b/internal/action/bufpane.go @@ -517,110 +517,112 @@ func (h *BufPane) SetActive(b bool) { // BufKeyActions contains the list of all possible key actions the bufhandler could execute var BufKeyActions = map[string]BufKeyAction{ - "CursorUp": (*BufPane).CursorUp, - "CursorDown": (*BufPane).CursorDown, - "CursorPageUp": (*BufPane).CursorPageUp, - "CursorPageDown": (*BufPane).CursorPageDown, - "CursorLeft": (*BufPane).CursorLeft, - "CursorRight": (*BufPane).CursorRight, - "CursorStart": (*BufPane).CursorStart, - "CursorEnd": (*BufPane).CursorEnd, - "SelectToStart": (*BufPane).SelectToStart, - "SelectToEnd": (*BufPane).SelectToEnd, - "SelectUp": (*BufPane).SelectUp, - "SelectDown": (*BufPane).SelectDown, - "SelectLeft": (*BufPane).SelectLeft, - "SelectRight": (*BufPane).SelectRight, - "WordRight": (*BufPane).WordRight, - "WordLeft": (*BufPane).WordLeft, - "SelectWordRight": (*BufPane).SelectWordRight, - "SelectWordLeft": (*BufPane).SelectWordLeft, - "DeleteWordRight": (*BufPane).DeleteWordRight, - "DeleteWordLeft": (*BufPane).DeleteWordLeft, - "SelectLine": (*BufPane).SelectLine, - "SelectToStartOfLine": (*BufPane).SelectToStartOfLine, - "SelectToStartOfText": (*BufPane).SelectToStartOfText, - "SelectToEndOfLine": (*BufPane).SelectToEndOfLine, - "ParagraphPrevious": (*BufPane).ParagraphPrevious, - "ParagraphNext": (*BufPane).ParagraphNext, - "InsertNewline": (*BufPane).InsertNewline, - "Backspace": (*BufPane).Backspace, - "Delete": (*BufPane).Delete, - "InsertTab": (*BufPane).InsertTab, - "Save": (*BufPane).Save, - "SaveAll": (*BufPane).SaveAll, - "SaveAs": (*BufPane).SaveAs, - "Find": (*BufPane).Find, - "FindNext": (*BufPane).FindNext, - "FindPrevious": (*BufPane).FindPrevious, - "Center": (*BufPane).Center, - "Undo": (*BufPane).Undo, - "Redo": (*BufPane).Redo, - "Copy": (*BufPane).Copy, - "Cut": (*BufPane).Cut, - "CutLine": (*BufPane).CutLine, - "DuplicateLine": (*BufPane).DuplicateLine, - "DeleteLine": (*BufPane).DeleteLine, - "MoveLinesUp": (*BufPane).MoveLinesUp, - "MoveLinesDown": (*BufPane).MoveLinesDown, - "IndentSelection": (*BufPane).IndentSelection, - "OutdentSelection": (*BufPane).OutdentSelection, - "Autocomplete": (*BufPane).Autocomplete, - "CycleAutocompleteBack": (*BufPane).CycleAutocompleteBack, - "OutdentLine": (*BufPane).OutdentLine, - "IndentLine": (*BufPane).IndentLine, - "Paste": (*BufPane).Paste, - "PastePrimary": (*BufPane).PastePrimary, - "SelectAll": (*BufPane).SelectAll, - "OpenFile": (*BufPane).OpenFile, - "Start": (*BufPane).Start, - "End": (*BufPane).End, - "PageUp": (*BufPane).PageUp, - "PageDown": (*BufPane).PageDown, - "SelectPageUp": (*BufPane).SelectPageUp, - "SelectPageDown": (*BufPane).SelectPageDown, - "HalfPageUp": (*BufPane).HalfPageUp, - "HalfPageDown": (*BufPane).HalfPageDown, - "StartOfText": (*BufPane).StartOfText, - "StartOfLine": (*BufPane).StartOfLine, - "EndOfLine": (*BufPane).EndOfLine, - "ToggleHelp": (*BufPane).ToggleHelp, - "ToggleKeyMenu": (*BufPane).ToggleKeyMenu, - "ToggleDiffGutter": (*BufPane).ToggleDiffGutter, - "ToggleRuler": (*BufPane).ToggleRuler, - "ClearStatus": (*BufPane).ClearStatus, - "ShellMode": (*BufPane).ShellMode, - "CommandMode": (*BufPane).CommandMode, - "ToggleOverwriteMode": (*BufPane).ToggleOverwriteMode, - "Escape": (*BufPane).Escape, - "Quit": (*BufPane).Quit, - "QuitAll": (*BufPane).QuitAll, - "AddTab": (*BufPane).AddTab, - "PreviousTab": (*BufPane).PreviousTab, - "NextTab": (*BufPane).NextTab, - "NextSplit": (*BufPane).NextSplit, - "PreviousSplit": (*BufPane).PreviousSplit, - "Unsplit": (*BufPane).Unsplit, - "VSplit": (*BufPane).VSplitAction, - "HSplit": (*BufPane).HSplitAction, - "ToggleMacro": (*BufPane).ToggleMacro, - "PlayMacro": (*BufPane).PlayMacro, - "Suspend": (*BufPane).Suspend, - "ScrollUp": (*BufPane).ScrollUpAction, - "ScrollDown": (*BufPane).ScrollDownAction, - "SpawnMultiCursor": (*BufPane).SpawnMultiCursor, - "SpawnMultiCursorUp": (*BufPane).SpawnMultiCursorUp, - "SpawnMultiCursorDown": (*BufPane).SpawnMultiCursorDown, - "SpawnMultiCursorSelect": (*BufPane).SpawnMultiCursorSelect, - "RemoveMultiCursor": (*BufPane).RemoveMultiCursor, - "RemoveAllMultiCursors": (*BufPane).RemoveAllMultiCursors, - "SkipMultiCursor": (*BufPane).SkipMultiCursor, - "JumpToMatchingBrace": (*BufPane).JumpToMatchingBrace, - "JumpLine": (*BufPane).JumpLine, - "None": (*BufPane).None, + "CursorUp": (*BufPane).CursorUp, + "CursorDown": (*BufPane).CursorDown, + "CursorPageUp": (*BufPane).CursorPageUp, + "CursorPageDown": (*BufPane).CursorPageDown, + "CursorLeft": (*BufPane).CursorLeft, + "CursorRight": (*BufPane).CursorRight, + "CursorStart": (*BufPane).CursorStart, + "CursorEnd": (*BufPane).CursorEnd, + "SelectToStart": (*BufPane).SelectToStart, + "SelectToEnd": (*BufPane).SelectToEnd, + "SelectUp": (*BufPane).SelectUp, + "SelectDown": (*BufPane).SelectDown, + "SelectLeft": (*BufPane).SelectLeft, + "SelectRight": (*BufPane).SelectRight, + "WordRight": (*BufPane).WordRight, + "WordLeft": (*BufPane).WordLeft, + "SelectWordRight": (*BufPane).SelectWordRight, + "SelectWordLeft": (*BufPane).SelectWordLeft, + "DeleteWordRight": (*BufPane).DeleteWordRight, + "DeleteWordLeft": (*BufPane).DeleteWordLeft, + "SelectLine": (*BufPane).SelectLine, + "SelectToStartOfLine": (*BufPane).SelectToStartOfLine, + "SelectToStartOfText": (*BufPane).SelectToStartOfText, + "SelectToStartOfTextToggle":(*BufPane).SelectToStartOfTextToggle, + "SelectToEndOfLine": (*BufPane).SelectToEndOfLine, + "ParagraphPrevious": (*BufPane).ParagraphPrevious, + "ParagraphNext": (*BufPane).ParagraphNext, + "InsertNewline": (*BufPane).InsertNewline, + "Backspace": (*BufPane).Backspace, + "Delete": (*BufPane).Delete, + "InsertTab": (*BufPane).InsertTab, + "Save": (*BufPane).Save, + "SaveAll": (*BufPane).SaveAll, + "SaveAs": (*BufPane).SaveAs, + "Find": (*BufPane).Find, + "FindNext": (*BufPane).FindNext, + "FindPrevious": (*BufPane).FindPrevious, + "Center": (*BufPane).Center, + "Undo": (*BufPane).Undo, + "Redo": (*BufPane).Redo, + "Copy": (*BufPane).Copy, + "Cut": (*BufPane).Cut, + "CutLine": (*BufPane).CutLine, + "DuplicateLine": (*BufPane).DuplicateLine, + "DeleteLine": (*BufPane).DeleteLine, + "MoveLinesUp": (*BufPane).MoveLinesUp, + "MoveLinesDown": (*BufPane).MoveLinesDown, + "IndentSelection": (*BufPane).IndentSelection, + "OutdentSelection": (*BufPane).OutdentSelection, + "Autocomplete": (*BufPane).Autocomplete, + "CycleAutocompleteBack": (*BufPane).CycleAutocompleteBack, + "OutdentLine": (*BufPane).OutdentLine, + "IndentLine": (*BufPane).IndentLine, + "Paste": (*BufPane).Paste, + "PastePrimary": (*BufPane).PastePrimary, + "SelectAll": (*BufPane).SelectAll, + "OpenFile": (*BufPane).OpenFile, + "Start": (*BufPane).Start, + "End": (*BufPane).End, + "PageUp": (*BufPane).PageUp, + "PageDown": (*BufPane).PageDown, + "SelectPageUp": (*BufPane).SelectPageUp, + "SelectPageDown": (*BufPane).SelectPageDown, + "HalfPageUp": (*BufPane).HalfPageUp, + "HalfPageDown": (*BufPane).HalfPageDown, + "StartOfText": (*BufPane).StartOfText, + "StartOfTextToggle": (*BufPane).StartOfTextToggle, + "StartOfLine": (*BufPane).StartOfLine, + "EndOfLine": (*BufPane).EndOfLine, + "ToggleHelp": (*BufPane).ToggleHelp, + "ToggleKeyMenu": (*BufPane).ToggleKeyMenu, + "ToggleDiffGutter": (*BufPane).ToggleDiffGutter, + "ToggleRuler": (*BufPane).ToggleRuler, + "ClearStatus": (*BufPane).ClearStatus, + "ShellMode": (*BufPane).ShellMode, + "CommandMode": (*BufPane).CommandMode, + "ToggleOverwriteMode": (*BufPane).ToggleOverwriteMode, + "Escape": (*BufPane).Escape, + "Quit": (*BufPane).Quit, + "QuitAll": (*BufPane).QuitAll, + "AddTab": (*BufPane).AddTab, + "PreviousTab": (*BufPane).PreviousTab, + "NextTab": (*BufPane).NextTab, + "NextSplit": (*BufPane).NextSplit, + "PreviousSplit": (*BufPane).PreviousSplit, + "Unsplit": (*BufPane).Unsplit, + "VSplit": (*BufPane).VSplitAction, + "HSplit": (*BufPane).HSplitAction, + "ToggleMacro": (*BufPane).ToggleMacro, + "PlayMacro": (*BufPane).PlayMacro, + "Suspend": (*BufPane).Suspend, + "ScrollUp": (*BufPane).ScrollUpAction, + "ScrollDown": (*BufPane).ScrollDownAction, + "SpawnMultiCursor": (*BufPane).SpawnMultiCursor, + "SpawnMultiCursorUp": (*BufPane).SpawnMultiCursorUp, + "SpawnMultiCursorDown": (*BufPane).SpawnMultiCursorDown, + "SpawnMultiCursorSelect": (*BufPane).SpawnMultiCursorSelect, + "RemoveMultiCursor": (*BufPane).RemoveMultiCursor, + "RemoveAllMultiCursors": (*BufPane).RemoveAllMultiCursors, + "SkipMultiCursor": (*BufPane).SkipMultiCursor, + "JumpToMatchingBrace": (*BufPane).JumpToMatchingBrace, + "JumpLine": (*BufPane).JumpLine, + "None": (*BufPane).None, // This was changed to InsertNewline but I don't want to break backwards compatibility - "InsertEnter": (*BufPane).InsertNewline, + "InsertEnter": (*BufPane).InsertNewline, } // BufMouseActions contains the list of all possible mouse actions the bufhandler could execute @@ -634,54 +636,56 @@ var BufMouseActions = map[string]BufMouseAction{ // Generally actions that modify global editor state like quitting or // saving should not be included in this list var MultiActions = map[string]bool{ - "CursorUp": true, - "CursorDown": true, - "CursorPageUp": true, - "CursorPageDown": true, - "CursorLeft": true, - "CursorRight": true, - "CursorStart": true, - "CursorEnd": true, - "SelectToStart": true, - "SelectToEnd": true, - "SelectUp": true, - "SelectDown": true, - "SelectLeft": true, - "SelectRight": true, - "WordRight": true, - "WordLeft": true, - "SelectWordRight": true, - "SelectWordLeft": true, - "DeleteWordRight": true, - "DeleteWordLeft": true, - "SelectLine": true, - "SelectToStartOfLine": true, - "SelectToStartOfText": true, - "SelectToEndOfLine": true, - "ParagraphPrevious": true, - "ParagraphNext": true, - "InsertNewline": true, - "Backspace": true, - "Delete": true, - "InsertTab": true, - "FindNext": true, - "FindPrevious": true, - "Cut": true, - "CutLine": true, - "DuplicateLine": true, - "DeleteLine": true, - "MoveLinesUp": true, - "MoveLinesDown": true, - "IndentSelection": true, - "OutdentSelection": true, - "OutdentLine": true, - "IndentLine": true, - "Paste": true, - "PastePrimary": true, - "SelectPageUp": true, - "SelectPageDown": true, - "StartOfLine": true, - "StartOfText": true, - "EndOfLine": true, - "JumpToMatchingBrace": true, + "CursorUp": true, + "CursorDown": true, + "CursorPageUp": true, + "CursorPageDown": true, + "CursorLeft": true, + "CursorRight": true, + "CursorStart": true, + "CursorEnd": true, + "SelectToStart": true, + "SelectToEnd": true, + "SelectUp": true, + "SelectDown": true, + "SelectLeft": true, + "SelectRight": true, + "WordRight": true, + "WordLeft": true, + "SelectWordRight": true, + "SelectWordLeft": true, + "DeleteWordRight": true, + "DeleteWordLeft": true, + "SelectLine": true, + "SelectToStartOfLine": true, + "SelectToStartOfText": true, + "SelectToStartOfTextToggle": true, + "SelectToEndOfLine": true, + "ParagraphPrevious": true, + "ParagraphNext": true, + "InsertNewline": true, + "Backspace": true, + "Delete": true, + "InsertTab": true, + "FindNext": true, + "FindPrevious": true, + "Cut": true, + "CutLine": true, + "DuplicateLine": true, + "DeleteLine": true, + "MoveLinesUp": true, + "MoveLinesDown": true, + "IndentSelection": true, + "OutdentSelection": true, + "OutdentLine": true, + "IndentLine": true, + "Paste": true, + "PastePrimary": true, + "SelectPageUp": true, + "SelectPageDown": true, + "StartOfLine": true, + "StartOfText": true, + "StartOfTextToggle": true, + "EndOfLine": true, + "JumpToMatchingBrace": true, } diff --git a/internal/action/defaults_darwin.go b/internal/action/defaults_darwin.go index 45b6359a..89f03290 100644 --- a/internal/action/defaults_darwin.go +++ b/internal/action/defaults_darwin.go @@ -17,10 +17,10 @@ func DefaultBindings() map[string]string { "AltDown": "MoveLinesDown", "AltShiftRight": "SelectWordRight", "AltShiftLeft": "SelectWordLeft", - "CtrlLeft": "StartOfText", + "CtrlLeft": "StartOfTextToggle", "CtrlRight": "EndOfLine", - "CtrlShiftLeft": "SelectToStartOfText", - "ShiftHome": "SelectToStartOfText", + "CtrlShiftLeft": "SelectToStartOfTextToggle", + "ShiftHome": "SelectToStartOfTextToggle", "CtrlShiftRight": "SelectToEndOfLine", "ShiftEnd": "SelectToEndOfLine", "CtrlUp": "CursorStart", @@ -52,7 +52,7 @@ func DefaultBindings() map[string]string { "CtrlT": "AddTab", "Alt,": "PreviousTab", "Alt.": "NextTab", - "Home": "StartOfText", + "Home": "StartOfTextToggle", "End": "EndOfLine", "CtrlHome": "CursorStart", "CtrlEnd": "CursorEnd", diff --git a/internal/action/defaults_other.go b/internal/action/defaults_other.go index 1ee40648..e63c1ee1 100644 --- a/internal/action/defaults_other.go +++ b/internal/action/defaults_other.go @@ -19,10 +19,10 @@ func DefaultBindings() map[string]string { "AltDown": "MoveLinesDown", "CtrlShiftRight": "SelectWordRight", "CtrlShiftLeft": "SelectWordLeft", - "AltLeft": "StartOfText", + "AltLeft": "StartOfTextToggle", "AltRight": "EndOfLine", - "AltShiftLeft": "SelectToStartOfText", - "ShiftHome": "SelectToStartOfText", + "AltShiftLeft": "SelectToStartOfTextToggle", + "ShiftHome": "SelectToStartOfTextToggle", "AltShiftRight": "SelectToEndOfLine", "ShiftEnd": "SelectToEndOfLine", "CtrlUp": "CursorStart", @@ -54,7 +54,7 @@ func DefaultBindings() map[string]string { "CtrlT": "AddTab", "Alt,": "PreviousTab", "Alt.": "NextTab", - "Home": "StartOfText", + "Home": "StartOfTextToggle", "End": "EndOfLine", "CtrlHome": "CursorStart", "CtrlEnd": "CursorEnd", diff --git a/internal/buffer/cursor.go b/internal/buffer/cursor.go index f3d6d059..6ea9a3d1 100644 --- a/internal/buffer/cursor.go +++ b/internal/buffer/cursor.go @@ -109,6 +109,19 @@ func (c *Cursor) StartOfText() { } } +// IsStartOfText returns whether the cursor is at the first +// non-whitespace rune of the line it is on +func (c *Cursor) IsStartOfText() bool { + x := 0 + for util.IsWhitespace(c.RuneUnder(x)) { + if x == utf8.RuneCount(c.buf.LineBytes(c.Y)) { + break + } + x++ + } + return c.X == x +} + // End moves the cursor to the end of the line it is on func (c *Cursor) End() { c.X = utf8.RuneCount(c.buf.LineBytes(c.Y)) diff --git a/runtime/help/keybindings.md b/runtime/help/keybindings.md index 12105306..f303e8a2 100644 --- a/runtime/help/keybindings.md +++ b/runtime/help/keybindings.md @@ -162,6 +162,8 @@ SelectUp SelectDown SelectLeft SelectRight +SelectToStartOfText +SelectToStartOfTextToggle WordRight WordLeft SelectWordRight @@ -209,6 +211,8 @@ HalfPageUp HalfPageDown StartOfLine EndOfLine +StartOfText +StartOfTextToggle ParagraphPrevious ParagraphNext ToggleHelp @@ -245,6 +249,9 @@ JumpToMatchingBrace Autocomplete ``` +The `StartOfTextToggle` and `SelectToStartOfTextToggle` actions toggle between +jumping to the start of the text (first) and start of the line. + You can also bind some mouse actions (these must be bound to mouse buttons) ``` @@ -410,21 +417,21 @@ conventions for text editing defaults. "ShiftDown": "SelectDown", "ShiftLeft": "SelectLeft", "ShiftRight": "SelectRight", - "AltLeft": "WordLeft", - "AltRight": "WordRight", + "AltLeft": "WordLeft", (Mac) + "AltRight": "WordRight", (Mac) "AltUp": "MoveLinesUp", "AltDown": "MoveLinesDown", "CtrlShiftRight": "SelectWordRight", "CtrlShiftLeft": "SelectWordLeft", - "AltLeft": "StartOfLine", + "AltLeft": "StartOfTextToggle", "AltRight": "EndOfLine", "AltShiftRight": "SelectWordRight", (Mac) "AltShiftLeft": "SelectWordLeft", (Mac) "CtrlLeft": "StartOfText", (Mac) "CtrlRight": "EndOfLine", (Mac) - "AltShiftLeft": "SelectToStartOfLine", - "CtrlShiftLeft": "SelectToStartOfText", (Mac) - "ShiftHome": "SelectToStartOfLine", + "AltShiftLeft": "SelectToStartOfTextToggle", + "CtrlShiftLeft": "SelectToStartOfTextToggle", (Mac) + "ShiftHome": "SelectToStartOfTextToggle", "AltShiftRight": "SelectToEndOfLine", "CtrlShiftRight": "SelectToEndOfLine", (Mac) "ShiftEnd": "SelectToEndOfLine",