tags:

views:

151

answers:

4

In Emacs, C-u C-SPC will "jump to the mark, and set the mark from position popped off the local mark ring". Is there a way to go the opposite way around the mark ring? Say you have typed C-u C-SPC several times and want to go back to a mark you have seen without going all the way around the ring.

A: 

Have you tried browse-kill-ring? Download it from Emacswiki, put it in your load-path and then add this to your emacs-conf:

(when (require 'browse-kill-ring nil 'noerror)
  (browse-kill-ring-default-keybindings))

Then, when you press M-y you will be shown the kill-ring, search it like ordinary text etc. Really handy. There is also some more practical info on emacs-fu on how to use browse-kill-ring

monotux
That would be a useful answer to a question about the kill ring.
phils
He's asking about the mark-ring, which is a circular list of places where the mark has been set.
Joel J. Adamson
...doh. Note to self: never answer questions while being extremely tired.
monotux
A: 

The manual says this:

The variable mark-ring-max specifies the maximum number of entries to keep in the mark ring. If that many entries exist and another one is pushed, the earliest one in the list is discarded. Repeating `C-u C-' cycles through the positions currently in the ring.

I suggest you use that to contain the size of the mark ring (to 3 or 4, mine is currently 16). Then you can move around it much faster using prefixes.

Also:

If you want to move back to the same place over and over, the mark ring may not be convenient enough. If so, you can record the position in a register for later retrieval (*note Saving Positions in Registers: RegPos.).

Joel J. Adamson
+1  A: 

It doesn't do exactly what you're asking for, but it might be worth looking for a package called marker-visit.el which lets you navigate the marks in the current buffer in 'buffer position order'. From that file:

;;; Commentary:

;; This file provides a simple way to navigate among marks in a
;; buffer.  C-u C-SPC is similar, but takes you haphazardly around the
;; buffer.  Setting bookmarks is a lot of extra work if you just want
;; to jump around your buffer quickly; plus, you have to come up with
;; a name for every bookmark.

;; All the marks you've left while editing a buffer serve as bread
;; crumb trails of areas in the buffer you've edited.  It is
;; convenient to navigate back and forth among these marks in order.
;; This file provides two methods to do just that, marker-visit-prev
;; and marker-visit-next.  These two functions will take you, from
;; point, to the nearest mark in either direction.  The function
;; marker-visit-truncate-mark-ring will truncate the mark ring.

;; The marks you can visit in a buffer consist of: "the mark" plus the
;; contents of the mark-ring.

I bind [S-up] and [S-down] to marker-visit-prev and marker-visit-next respectively.

If you really want/need to navigate in the order your mark-ring has currently, then you might get somewhere by looking at the functions pop-to-mark-command and pop-mark and implementing your own versions to rotate the mark ring in the opposite direction.

Simon
Damyan
Ah, apologies - didn't realise it was hard to find. I suspect half the gathered elisp in my config is collecting a weekly pension.
Simon
+1  A: 

Here's a function to do it:

(defun unpop-to-mark-command ()
  "Unpop off mark ring into the buffer's actual mark.
Does not set point.  Does nothing if mark ring is empty."
  (interactive)
  (let ((num-times (if (equal last-command 'pop-to-mark-command) 2
                     (if (equal last-command 'unpop-to-mark-command) 1
                       (error "Previous command was not a (un)pop-to-mark-command")))))
    (dotimes (x num-times)
      (when mark-ring
        (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
        (set-marker (mark-marker) (+ 0 (car (last mark-ring))) (current-buffer))
        (when (null (mark t)) (ding))
        (setq mark-ring (nbutlast mark-ring))
        (goto-char (mark t)))
      (deactivate-mark))))
scottfrazer
Any thoughts on a sensible binding to relate this to the existing pop-to-mark mechanism? e.g. If you start with `C-u C-SPC C-SPC C-SPC ...` and over-shoot, it would be good to have something simple to reverse the direction. Maybe some before-advice for `set-mark-command` to make `C-u C-SPC` act as a toggle between the two functions?
phils