Easy bookmarks in Emacs

Emacs is an incredibly feature rich editor. You can do just about anything you would ever want to do and much more. Unfortunately the power and flexibility of Emacs can be a bit unfriendly and cumbersome at times. I seem to rediscover this fact every 2-3 weeks and I usually customize Emacs in some way to make things easier for me.

My latest discovery is the complicated bookmarking system. Setting a bookmark in Emacs involves moving to the line in the file you want to bookmark, typing C-x r m and then giving the bookmark a unique name. To find the bookmark later, you type C-x r b and then type the unique name you gave the bookmark. This bookmarking system is very flexible but can difficult to work with.

I’ve used Visual Studio in the past and I became quite fond of its simple bookmarking system. You simply type Ctrl-F2 to set a bookmark and F2 to cycle between bookmarks. Shift-F2 cycles bookmarks in reverse. It is such a brain dead system. No need to remember bookmark names. No tiresome keystrokes to type.

Since Emacs is *the* programmable text editor, I was able to extend the existing bookmarking system to emulate the Visual Studio style bookmarks. Now I have a “dumbed down” bookmarking system that is quick and easy to use.

Here’s the code I wrote to make it happen:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 
;; Easy bookmarks management
;;
;; Author: Anthony Fairchild
;;

;;;; Keymaping examples
;; (global-set-key [(control f2)]  'af-bookmark-toggle )
;; (global-set-key [f2]  'af-bookmark-cycle-forward )
;; (global-set-key [(shift f2)]  'af-bookmark-cycle-reverse )
;; (global-set-key [(control shift f2)]  'af-bookmark-clear-all )

;; Include common lisp stuff
(require 'cl)
(require 'bookmark)
(defvar af-current-bookmark nil)

(defun af-bookmark-make-name ()
  "makes a bookmark name from the buffer name and cursor position"
  (concat (buffer-name (current-buffer))
          " - " (number-to-string (point))))

(defun af-bookmark-toggle ()
  "remove a bookmark if it exists, create one if it doesnt exist"
  (interactive)
  (let ((bm-name (af-bookmark-make-name)))
    (if (bookmark-get-bookmark bm-name)
        (progn (bookmark-delete bm-name)
               (message "bookmark removed"))
      (progn (bookmark-set bm-name)
             (setf af-current-bookmark bm-name)
             (message "bookmark set")))))
(defun af-bookmark-cycle (i)
  "Cycle through bookmarks by i.  'i' should be 1 or -1"
  (if bookmark-alist
      (progn (unless af-current-bookmark
               (setf af-current-bookmark (first (first bookmark-alist))))
             (let ((cur-bm (assoc af-current-bookmark bookmark-alist)))
               (setf af-current-bookmark
                     (if cur-bm
                         (first (nth (mod (+ i (position cur-bm bookmark-alist))
                                          (length bookmark-alist))
                                     bookmark-alist))
                       (first (first bookmark-alist))))
               (bookmark-jump af-current-bookmark)
               ;; Update the position and name of the bookmark.  We
               ;; only need to do this when the bookmark has changed
               ;; position, but lets go ahead and do it all the time
               ;; anyway.
               (bookmark-set-position af-current-bookmark (point))
               (let ((new-name (af-bookmark-make-name)))
                 (bookmark-set-name af-current-bookmark new-name)
                 (setf af-current-bookmark new-name))))
    (message "There are no bookmarks set!")))
(defun af-bookmark-cycle-forward ()
  "find the next bookmark in the bookmark-alist"
  (interactive)
  (af-bookmark-cycle 1))
(defun af-bookmark-cycle-reverse ()
  "find the next bookmark in the bookmark-alist"
  (interactive)
  (af-bookmark-cycle -1))

(defun af-bookmark-clear-all()
  "clears all bookmarks"
  (interactive)
  (setf bookmark-alist nil))

8 Responses to “Easy bookmarks in Emacs”

  1. Phil! Says:

    I generally don’t bother with emacs’s bookmarks, because I find them somewhat cumbersome to use. I usually use emacs’s ability to save the location of the point in a register, via C-x r SPC <register> and then jump to that location via C-x r j <register>. It doesn’t quite have the stack/cycle nature of your approach, but I usually use the convention that I start with the register ‘j’ (because that makes jumping to it easy) and then go alphabetically from there.

  2. Mac Says:

    Very nice, thanks

  3. Armchair Guy Says:

    This is great, exactly what I was looking for. Thanks!

    Funny thing though, when I did a cut-and-paste into emacs from firefox, it used weird characters for the quotes that confused emacs. I changed them to the standard ‘ and ” quotes.

  4. Pankaj Says:

    Great! Emacs is awesome.

  5. DesLynccyPe Says:

    продам Форд-Фокус 2008 года за 200 тр. торг возможет. срочно!!!
    +7 960 200 9209

  6. Seb Says:

    Well, there are tons of applications in Emacs that make the built-in bookmarking system unnecessary; e.g. planner, remember, org-mode. OTOH, a simple completion mechanism like that given by icicles is enough to make the built-in bookmark system much more efficient

  7. Leo Says:

    Awesome; exactly what I was looking for. It’s broken in Emacs 23.0.95 though — but the fix is easy: change
    (if (bookmark-get-bookmark bm-name)
    to
    (if (bookmark-get-bookmark bm-name t)
    in af-bookmark-toggle

  8. Jo Says:

    There is already a bookmark extention for Emacs inspired by Visual Studio bookmarks, http://www.nongnu.org/bm/

Leave a Reply