summaryrefslogtreecommitdiffstats
path: root/blog/blog-2012-08-02-0027.org
blob: 86a205b887dc53fd00293307dc7576dee26933d1 (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
76
#+TITLE: Cool new scratch buffers

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=:

#+begin_src emacs-lisp
  (defun raise-scratch ()
    "Show the *scratch* buffer."
    (interactive)
    (switch-to-buffer "*scratch*"))
#+end_src

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.

#+begin_src emacs-lisp
  (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)
            (goto-char (point-max))
            (newline))))

      (switch-to-buffer buffer)))
#+end_src

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.