onilog

Cool new scratch buffers

2 August 2012 0:27 AM (emacs | elisp | coding)

I had a thought today: It would be nice if I could have more than one scratch buffer, and even nicer if they could easily have different major modes.

So, I had this function in my emacs init file, raise-scratch:

(defun raise-scratch ()
  "Show the *scratch* buffer."
  (interactive)
  (switch-to-buffer "*scratch*"))

Its nice, it allowed me to do exactly what I wanted to do, easily open my scratch buffer. I bound this to XF86HomePage, which makes sense to me, since emacs always starts in the *scratch* buffer.

Today, though, it didn't seem to be quite enough. As I said, it would be nice to have the ability to have multiple scratch buffers with different major modes. This is handy for messing around with some sawfish-mode code, or python-mode, for example.

(defun raise-scratch (&optional mode)
  "Show the *scratch* buffer. If called with a universal
argument, ask the user which mode to use. If MODE is not nil,
open a new buffer with the name *MODE-scratch* and load MODE as
its major mode."
  (interactive (list (if current-prefix-arg
                         (read-string "Mode: ")
                       nil)))
  (let* ((bname (if mode
                    (concat "*" mode "-scratch*")
                  "*scratch*"))
         (buffer (get-buffer bname))
         (mode-sym (intern (concat mode "-mode"))))

    (unless buffer
      (setq buffer (generate-new-buffer bname))
      (with-current-buffer buffer
        (when (fboundp mode-sym)
          (funcall mode-sym))))

    (switch-to-buffer buffer)))

This is quite a bit bigger. It now takes an optional mode argument, when it is called interactively it will check if the universal prefix argument (C-u) was used and if so, asks for the value of mode.

If mode has been specified it will create a new buffer with the name *MODE-scratch*. It will then insert a file local property line specifying the major mode to use and then switches to it.

It's the first time I'm using a list with the interactive command, it always seemed very alien to me, but it seems quite clear how it works now.

It was a challenge to figure out how I wanted to do this. My first idea was to ask for a file extension and match that to auto-mode-alist, but that has regexps for keys, so not easily matched. Then there is the problem of figuring out how to load the right major mode in another way, since adding such a file local property line happens after the buffer has been loaded, and thus has no effect on which major mode is chosen.

Of course, this approach doesn't ensure the right major mode gets chosen, but that's really up to whomever uses it.

It makes me very happy to use such an extensible editor.

Update: fixed my flawed code.

No responses

Leave a Reply