diff --git a/internal/action/actions.go b/internal/action/actions.go index 74e701f47c..a135d7692f 100644 --- a/internal/action/actions.go +++ b/internal/action/actions.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "io/fs" + "math" "os" "regexp" "runtime" @@ -482,6 +483,20 @@ func (h *BufPane) CursorEnd() bool { return true } +// CursorRatio moves the cursor to a given ratio of the buffer. +// For example, if ratio is 0.5, the cursor is moved to the center line. +func (h *BufPane) CursorRatio(ratio float64) bool { + if ratio < 0 || ratio > 1 { + return false + } + targetLocation := buffer.Loc{0, int(math.Round(float64(h.Buf.End().Y) * ratio))} + h.Cursor.Deselect(true) + h.Cursor.Loc = targetLocation + h.Cursor.StoreVisualX() + h.Relocate() + return true +} + // SelectToStart selects the text from the cursor to the start of the buffer func (h *BufPane) SelectToStart() bool { if !h.Cursor.HasSelection() { diff --git a/internal/action/command.go b/internal/action/command.go index 16d2fff812..a38c0439a4 100644 --- a/internal/action/command.go +++ b/internal/action/command.go @@ -702,7 +702,12 @@ func (h *BufPane) QuitCmd(args []string) { // For example: `goto line`, or `goto line:col` func (h *BufPane) GotoCmd(args []string) { if len(args) <= 0 { - InfoBar.Error("Not enough arguments") + // No argument given, alternate between jumping to the top or the bottom + if h.Cursor.Loc.Y > 0 { + h.CursorStart() + } else { + h.CursorEnd() + } } else { h.RemoveAllMultiCursors() if strings.Contains(args[0], ":") { @@ -723,6 +728,20 @@ func (h *BufPane) GotoCmd(args []string) { line = util.Clamp(line-1, 0, h.Buf.LinesNum()-1) col = util.Clamp(col-1, 0, util.CharacterCount(h.Buf.LineBytes(line))) h.GotoLoc(buffer.Loc{col, line}) + } else if strings.HasSuffix(args[0], "%") { // Jump to a percentage, like 50% + percentage, err := strconv.Atoi(args[0][:len(args[0])-1]) + if err != nil { + InfoBar.Error(err) + return + } + h.CursorRatio(float64(percentage) * 0.01) // Convert from percentage to ratio with * 0.01 + } else if strings.Count(args[0], ".") == 1 || strings.Count(args[0], ",") == 1 { // Jump to a ratio, like .5 or ,5 ? + ratio, err := strconv.ParseFloat(strings.ReplaceAll(args[0], ",", "."), 64) + if err != nil { + InfoBar.Error(err) + return + } + h.CursorRatio(ratio) } else { line, err := strconv.Atoi(args[0]) if err != nil {