From 651a30105b5e7d833efa18a4e5246d3ac95a3ed4 Mon Sep 17 00:00:00 2001 From: Ilya Grigoriev Date: Thu, 20 Apr 2023 15:23:35 -0700 Subject: [PATCH] Goto next/previous diff commands + minor cleanups (#2759) * Comment fix & gofmt fix * Goto next/previous diff commands These commands will work in `git` repositories or whenever `set diff on` is working. They are bound to `Alt-[` and `Alt-]` by default. I would prefer `Alt-Up` and `Alt-Down`, but that's already taken. There are no tests at the moment; I'm looking into writing some since that will be needed for the rest of the plan to make https://github.com/zyedidia/micro/discussions/2753 a reality. I'm not sure how difficult that will be. * Realign JSON in keybindings.md --- internal/action/actions.go | 24 +++++++++++- internal/action/bufpane.go | 2 + internal/action/defaults_darwin.go | 2 + internal/action/defaults_other.go | 3 ++ internal/buffer/buffer.go | 37 +++++++++++++++++- runtime/help/keybindings.md | 63 ++++++++++++++++-------------- 6 files changed, 100 insertions(+), 31 deletions(-) diff --git a/internal/action/actions.go b/internal/action/actions.go index b5d7f768..2b36795a 100644 --- a/internal/action/actions.go +++ b/internal/action/actions.go @@ -1027,6 +1027,28 @@ func (h *BufPane) FindPrevious() bool { return true } +// DiffNext searches forward until the beginning of the next block of diffs +func (h *BufPane) DiffNext() bool { + cur := h.Cursor.Loc.Y + dl, err := h.Buf.FindNextDiffLine(cur, true) + if err != nil { + return false + } + h.GotoLoc(buffer.Loc{0, dl}) + return true +} + +// DiffPrevious searches forward until the end of the previous block of diffs +func (h *BufPane) DiffPrevious() bool { + cur := h.Cursor.Loc.Y + dl, err := h.Buf.FindNextDiffLine(cur, false) + if err != nil { + return false + } + h.GotoLoc(buffer.Loc{0, dl}) + return true +} + // Undo undoes the last action func (h *BufPane) Undo() bool { h.Buf.Undo() @@ -1311,7 +1333,7 @@ func (h *BufPane) OpenFile() bool { return true } -// OpenFile opens a new file in the buffer +// JumpLine asks the user to enter a line number to jump to func (h *BufPane) JumpLine() bool { InfoBar.Prompt("> ", "goto ", "Command", nil, func(resp string, canceled bool) { if !canceled { diff --git a/internal/action/bufpane.go b/internal/action/bufpane.go index 847f5641..f9da9b3a 100644 --- a/internal/action/bufpane.go +++ b/internal/action/bufpane.go @@ -708,6 +708,8 @@ var BufKeyActions = map[string]BufKeyAction{ "FindLiteral": (*BufPane).FindLiteral, "FindNext": (*BufPane).FindNext, "FindPrevious": (*BufPane).FindPrevious, + "DiffNext": (*BufPane).DiffNext, + "DiffPrevious": (*BufPane).DiffPrevious, "Center": (*BufPane).Center, "Undo": (*BufPane).Undo, "Redo": (*BufPane).Redo, diff --git a/internal/action/defaults_darwin.go b/internal/action/defaults_darwin.go index bae69910..24b1f060 100644 --- a/internal/action/defaults_darwin.go +++ b/internal/action/defaults_darwin.go @@ -41,6 +41,8 @@ var bufdefaults = map[string]string{ "Alt-F": "FindLiteral", "Ctrl-n": "FindNext", "Ctrl-p": "FindPrevious", + "Alt-[": "DiffPrevious|CursorStart", + "Alt-]": "DiffNext|CursorEnd", "Ctrl-z": "Undo", "Ctrl-y": "Redo", "Ctrl-c": "CopyLine|Copy", diff --git a/internal/action/defaults_other.go b/internal/action/defaults_other.go index 39a9e0e3..2edc48e0 100644 --- a/internal/action/defaults_other.go +++ b/internal/action/defaults_other.go @@ -1,3 +1,4 @@ +//go:build !darwin // +build !darwin package action @@ -43,6 +44,8 @@ var bufdefaults = map[string]string{ "Alt-F": "FindLiteral", "Ctrl-n": "FindNext", "Ctrl-p": "FindPrevious", + "Alt-[": "DiffPrevious|CursorStart", + "Alt-]": "DiffNext|CursorEnd", "Ctrl-z": "Undo", "Ctrl-y": "Redo", "Ctrl-c": "CopyLine|Copy", diff --git a/internal/buffer/buffer.go b/internal/buffer/buffer.go index 56302e9d..38461fbf 100644 --- a/internal/buffer/buffer.go +++ b/internal/buffer/buffer.go @@ -474,7 +474,7 @@ func (b *Buffer) GetName() string { return name } -//SetName changes the name for this buffer +// SetName changes the name for this buffer func (b *Buffer) SetName(s string) { b.name = s } @@ -1211,6 +1211,41 @@ func (b *Buffer) DiffStatus(lineN int) DiffStatus { return b.diff[lineN] } +// FindNextDiffLine returns the line number of the next block of diffs. +// If `startLine` is already in a block of diffs, lines in that block are skipped. +func (b *Buffer) FindNextDiffLine(startLine int, forward bool) (int, error) { + if b.diff == nil { + return 0, errors.New("no diff data") + } + startStatus, ok := b.diff[startLine] + if !ok { + startStatus = DSUnchanged + } + curLine := startLine + for { + curStatus, ok := b.diff[curLine] + if !ok { + curStatus = DSUnchanged + } + if curLine < 0 || curLine > b.LinesNum() { + return 0, errors.New("no next diff hunk") + } + if curStatus != startStatus { + if startStatus != DSUnchanged && curStatus == DSUnchanged { + // Skip over the block of unchanged text + startStatus = DSUnchanged + } else { + return curLine, nil + } + } + if forward { + curLine++ + } else { + curLine-- + } + } +} + // SearchMatch returns true if the given location is within a match of the last search. // It is used for search highlighting func (b *Buffer) SearchMatch(pos Loc) bool { diff --git a/runtime/help/keybindings.md b/runtime/help/keybindings.md index 8d14da7d..f4aba70f 100644 --- a/runtime/help/keybindings.md +++ b/runtime/help/keybindings.md @@ -30,8 +30,8 @@ following in the `bindings.json` file. ```json { - "Ctrl-y": "Undo", - "Ctrl-z": "Redo" + "Ctrl-y": "Undo", + "Ctrl-z": "Redo" } ``` @@ -200,6 +200,8 @@ Find FindLiteral FindNext FindPrevious +DiffPrevious +DiffNext Undo Redo Copy @@ -461,29 +463,31 @@ conventions for text editing defaults. "Alt-{": "ParagraphPrevious", "Alt-}": "ParagraphNext", "Enter": "InsertNewline", - "Ctrl-h": "Backspace", + "Ctrl-h": "Backspace", "Backspace": "Backspace", "Alt-CtrlH": "DeleteWordLeft", "Alt-Backspace": "DeleteWordLeft", "Tab": "Autocomplete|IndentSelection|InsertTab", "Backtab": "OutdentSelection|OutdentLine", - "Ctrl-o": "OpenFile", - "Ctrl-s": "Save", - "Ctrl-f": "Find", - "Alt-F": "FindLiteral", - "Ctrl-n": "FindNext", - "Ctrl-p": "FindPrevious", - "Ctrl-z": "Undo", - "Ctrl-y": "Redo", - "Ctrl-c": "CopyLine|Copy", - "Ctrl-x": "Cut", - "Ctrl-k": "CutLine", - "Ctrl-d": "DuplicateLine", - "Ctrl-v": "Paste", - "Ctrl-a": "SelectAll", - "Ctrl-t": "AddTab", - "Alt-,": "PreviousTab", - "Alt-.": "NextTab", + "Ctrl-o": "OpenFile", + "Ctrl-s": "Save", + "Ctrl-f": "Find", + "Alt-F": "FindLiteral", + "Ctrl-n": "FindNext", + "Ctrl-p": "FindPrevious", + "Alt-[": "DiffPrevious|CursorStart", + "Alt-]": "DiffNext|CursorEnd", + "Ctrl-z": "Undo", + "Ctrl-y": "Redo", + "Ctrl-c": "CopyLine|Copy", + "Ctrl-x": "Cut", + "Ctrl-k": "CutLine", + "Ctrl-d": "DuplicateLine", + "Ctrl-v": "Paste", + "Ctrl-a": "SelectAll", + "Ctrl-t": "AddTab", + "Alt-,": "PreviousTab", + "Alt-.": "NextTab", "Home": "StartOfText", "End": "EndOfLine", "CtrlHome": "CursorStart", @@ -492,17 +496,17 @@ conventions for text editing defaults. "PageDown": "CursorPageDown", "CtrlPageUp": "PreviousTab", "CtrlPageDown": "NextTab", - "Ctrl-g": "ToggleHelp", + "Ctrl-g": "ToggleHelp", "Alt-g": "ToggleKeyMenu", - "Ctrl-r": "ToggleRuler", - "Ctrl-l": "command-edit:goto ", + "Ctrl-r": "ToggleRuler", + "Ctrl-l": "command-edit:goto ", "Delete": "Delete", - "Ctrl-b": "ShellMode", - "Ctrl-q": "Quit", - "Ctrl-e": "CommandMode", - "Ctrl-w": "NextSplit", - "Ctrl-u": "ToggleMacro", - "Ctrl-j": "PlayMacro", + "Ctrl-b": "ShellMode", + "Ctrl-q": "Quit", + "Ctrl-e": "CommandMode", + "Ctrl-w": "NextSplit", + "Ctrl-u": "ToggleMacro", + "Ctrl-j": "PlayMacro", "Insert": "ToggleOverwriteMode", // Emacs-style keybindings @@ -526,6 +530,7 @@ conventions for text editing defaults. "MouseMiddle": "PastePrimary", "Ctrl-MouseLeft": "MouseMultiCursor", + // Multi-cursor bindings "Alt-n": "SpawnMultiCursor", "AltShiftUp": "SpawnMultiCursorUp", "AltShiftDown": "SpawnMultiCursorDown",