5

I use point-undo to jump between positions in the cursor history. However, point-undo uses every previous position of the cursor, and I often experience that what I actually want is to jump just to the last/next line where my cursor was. So I don't want to jump around within one line. In other words, I would like the cursor history to store only the last position per line.

How to do this?

Drew
  • 75,699
  • 9
  • 109
  • 225
Timm
  • 1,549
  • 12
  • 23
  • You might want to check [`avy`](https://github.com/abo-abo/avy) it allows you to quickly jump to any lines in the visible text with `avy-goto-lines` command. – Chakravarthy Raghunandan Oct 21 '16 at 12:41
  • 1
    You could give https://www.emacswiki.org/emacs/download/pointhistory.el a try. This is not on a per-line basis but it only saves "large jumps" as introduced by `scroll-up` and so on. Since multiple `next-line` commands also cause a `scroll-up` those line-commands are also covered in some sense. – Tobias Oct 21 '16 at 15:05
  • @Tobias Thanks for the hint! Unfortunately, jumps seem to be too large with `pointhistory`. And the way it jumps is somewhat enigmatic, as to the positions that go into the ring. Maybe the code of `pointhistory` could be modified to also include line-based jumps? – Timm Oct 22 '16 at 08:42
  • [`ace-jump-mode`](https://github.com/winterTTr/ace-jump-mode) is a nice alternative to `avy`. [Demoed here](https://www.youtube.com/watch?v=UZkpmegySnc). – young_souvlaki Oct 04 '21 at 15:50

1 Answers1

1

I've tried to modify point-undo. It seems to work. However I included the first jump on the current line. That's intended behaviour.

(defvar point-undo-ring-length 20)

(defvar point-undo-ring (make-ring point-undo-ring-length))
(make-variable-buffer-local 'point-undo-ring)

(defvar point-redo-ring (make-ring point-undo-ring-length))
(make-variable-buffer-local 'point-redo-ring)

(defun point-undo-pre-command-hook ()
  "Save positions before command."
  (unless (or (eq this-command 'point-undo)
              (eq this-command 'point-redo))
    (let ((line (line-number-at-pos)))
      (when (eq line (cdr (nth 0 (ring-elements point-undo-ring))))
        (ring-remove point-undo-ring 0))
      (ring-insert point-undo-ring (cons (point) line))
      (setq point-redo-ring (make-ring point-undo-ring-length)))))
(add-hook 'pre-command-hook 'point-undo-pre-command-hook)

(defun point-undo-doit (ring1 ring2)
  "ring1, ring2 = {point-undo-ring, point-redo-ring}"
  (condition-case nil
      (progn
        (goto-char (car (nth 0 (ring-elements ring1)))) 
        (ring-insert ring2 (ring-remove ring1 0)))
    (error nil)))

(defun point-undo ()
  "Undo position."
  (interactive)
  (point-undo-doit point-undo-ring point-redo-ring))

(defun point-redo ()
  "Redo position."
  (interactive)
  (when (or (eq last-command 'point-undo)
            (eq last-command 'point-redo))
    (point-undo-doit point-redo-ring point-undo-ring)))

(define-key global-map [f9] 'point-undo)
(define-key global-map [f10] 'point-redo)
bertfred
  • 1,699
  • 1
  • 11
  • 23