From f8e532b0d7bfbaa317e4713e2807879a15d4bcc2 Mon Sep 17 00:00:00 2001 From: hchac Date: Sat, 20 Jul 2024 06:21:57 -0400 Subject: [PATCH] Adding selection for ParagraphPrevious and ParagraphNext. (#3353) Also tweaked the behavior of Paragraph/{Previous/Next} so that it skips all empty lines immediately next to cursor position, until it finds the start/end of the paragraph closest to it. Once it finds the paragraph closest to it, the same behavior as before applies. With the previous behavior if the cursor was surrounded by empty lines, then Paragraph/{Previous/Next} would only jump to the next empty line, instead of jumping to the start/end of a paragraph. --- internal/action/actions.go | 84 ++++++++++++++++++++++++++++++------- internal/action/bufpane.go | 2 + runtime/help/keybindings.md | 2 + 3 files changed, 73 insertions(+), 15 deletions(-) diff --git a/internal/action/actions.go b/internal/action/actions.go index 28d0e53d..036a8c2b 100644 --- a/internal/action/actions.go +++ b/internal/action/actions.go @@ -490,38 +490,92 @@ func (h *BufPane) SelectToEndOfLine() bool { return true } -// ParagraphPrevious moves the cursor to the previous empty line, or beginning of the buffer if there's none -func (h *BufPane) ParagraphPrevious() bool { +func (h *BufPane) paragraphPrevious() { var line int + // Skip to the first non-empty line for line = h.Cursor.Y; line > 0; line-- { - if len(h.Buf.LineBytes(line)) == 0 && line != h.Cursor.Y { + if len(h.Buf.LineBytes(line)) != 0 { + break + } + } + // Find the first empty line + for ; line > 0; line-- { + if len(h.Buf.LineBytes(line)) == 0 { h.Cursor.X = 0 h.Cursor.Y = line break } } - // If no empty line found. move cursor to end of buffer + // If no empty line was found, move the cursor to the start of the buffer if line == 0 { h.Cursor.Loc = h.Buf.Start() } +} + +func (h *BufPane) paragraphNext() { + var line int + // Skip to the first non-empty line + for line = h.Cursor.Y; line < h.Buf.LinesNum(); line++ { + if len(h.Buf.LineBytes(line)) != 0 { + break + } + } + // Find the first empty line + for ; line < h.Buf.LinesNum(); line++ { + if len(h.Buf.LineBytes(line)) == 0 { + h.Cursor.X = 0 + h.Cursor.Y = line + break + } + } + // If no empty line was found, move the cursor to the end of the buffer + if line == h.Buf.LinesNum() { + h.Cursor.Loc = h.Buf.End() + } +} + +// ParagraphPrevious moves the cursor to the first empty line that comes before +// the paragraph closest to the cursor, or beginning of the buffer if there +// isn't a paragraph +func (h *BufPane) ParagraphPrevious() bool { + h.Cursor.Deselect(true) + h.paragraphPrevious() h.Relocate() return true } -// ParagraphNext moves the cursor to the next empty line, or end of the buffer if there's none +// ParagraphNext moves the cursor to the first empty line that comes after the +// paragraph closest to the cursor, or end of the buffer if there isn't a +// paragraph func (h *BufPane) ParagraphNext() bool { - var line int - for line = h.Cursor.Y; line < h.Buf.LinesNum(); line++ { - if len(h.Buf.LineBytes(line)) == 0 && line != h.Cursor.Y { - h.Cursor.X = 0 - h.Cursor.Y = line - break - } + h.Cursor.Deselect(true) + h.paragraphNext() + h.Relocate() + return true +} + +// SelectToParagraphPrevious selects to the first empty line that comes before +// the paragraph closest to the cursor, or beginning of the buffer if there +// isn't a paragraph +func (h *BufPane) SelectToParagraphPrevious() bool { + if !h.Cursor.HasSelection() { + h.Cursor.OrigSelection[0] = h.Cursor.Loc } - // If no empty line found. move cursor to end of buffer - if line == h.Buf.LinesNum() { - h.Cursor.Loc = h.Buf.End() + h.paragraphPrevious() + h.Cursor.SelectTo(h.Cursor.Loc) + h.Relocate() + return true +} + +// SelectToParagraphNext selects to the first empty line that comes after the +// paragraph closest to the cursor, or end of the buffer if there isn't a +// paragraph +func (h *BufPane) SelectToParagraphNext() bool { + if !h.Cursor.HasSelection() { + h.Cursor.OrigSelection[0] = h.Cursor.Loc } + h.paragraphNext() + h.Cursor.SelectTo(h.Cursor.Loc) h.Relocate() return true } diff --git a/internal/action/bufpane.go b/internal/action/bufpane.go index 14e04089..8724f21a 100644 --- a/internal/action/bufpane.go +++ b/internal/action/bufpane.go @@ -759,6 +759,8 @@ var BufKeyActions = map[string]BufKeyAction{ "SelectToEndOfLine": (*BufPane).SelectToEndOfLine, "ParagraphPrevious": (*BufPane).ParagraphPrevious, "ParagraphNext": (*BufPane).ParagraphNext, + "SelectToParagraphPrevious": (*BufPane).SelectToParagraphPrevious, + "SelectToParagraphNext": (*BufPane).SelectToParagraphNext, "InsertNewline": (*BufPane).InsertNewline, "Backspace": (*BufPane).Backspace, "Delete": (*BufPane).Delete, diff --git a/runtime/help/keybindings.md b/runtime/help/keybindings.md index 3198c8fb..7d1339e3 100644 --- a/runtime/help/keybindings.md +++ b/runtime/help/keybindings.md @@ -237,6 +237,8 @@ StartOfText StartOfTextToggle ParagraphPrevious ParagraphNext +SelectToParagraphPrevious +SelectToParagraphNext ToggleHelp ToggleDiffGutter ToggleRuler