summaryrefslogtreecommitdiffstats
path: root/posts/Cool_new_scratch_buffers.mdwn
blob: db63cf41af8d78dd361c7cc7d93e83413c8738e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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`:

[[!format el """
(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.

[[!format el """
(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.

[[!meta date="2012-08-02 00:27:00"]]
[[!tag emacs elisp coding]]