Emacs buffer mode histogram
Tonight I noticed that I had over 200 buffers open in emacs. I’ve been programming a lot in Python recently, so many of them are in Python mode. I wondered how many Python files I had open, and I counted them by hand. About 90. I then wondered how many were in Javascript mode, in RST mode, etc. I wondered what a histogram would look like, for me and for others, at times when I’m programming versus working on documentation, etc.
Because it’s emacs, it wasn’t hard to write a function to display a buffer mode histogram. Here’s mine:
235 buffers open, in 23 distinct modes 91 python +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 47 fundamental +++++++++++++++++++++++++++++++++++++++++++++++ 24 js2 ++++++++++++++++++++++++ 21 dired +++++++++++++++++++++ 16 html ++++++++++++++++ 7 text +++++++ 4 help ++++ 4 emacs-lisp ++++ 3 sh +++ 3 makefile-gmake +++ 2 compilation ++ 2 css ++ 1 Buffer-menu + 1 mail + 1 grep + 1 completion-list + 1 vm + 1 org + 1 comint + 1 apropos + 1 Info + 1 vm-summary + 1 vm-presentation +
Tempting as it is, I’m not going to go on about the heady delights of having a fully programmable editor. You either already know, or you can just drool in slack-jawed wonder.
Unfortunately I’m a terrible emacs lisp programmer. I can barely remember a thing each time I use it. But the interpreter is of course just emacs itself and the elisp documentation is in emacs, so it’s a really fun environment to develop in. And because emacs lisp has a ton of support for doing things to itself, code that acts on emacs and your own editing session or buffers is often very succinct. See for example the save-excursion and with-output-to-temp-buffer functions below.
"Display a histogram of emacs buffer modes."
(interactive)
(let* ((totals ‘())
(buffers (buffer-list()))
(total-buffers (length buffers))
(ht (make-hash-table :test ‘equal)))
(save-excursion
(dolist (buffer buffers)
(set-buffer buffer)
(let
((mode-name (symbol-name major-mode)))
(puthash mode-name (1+ (gethash mode-name ht 0)) ht))))
(maphash (lambda (key value)
(setq totals (cons (list key value) totals)))
ht)
(setq totals (sort totals (lambda (x y) (> (cadr x) (cadr y)))))
(with-output-to-temp-buffer "Buffer mode histogram"
(princ (format "%d buffers open, in %d distinct modes\n\n"
total-buffers (length totals)))
(dolist (item totals)
(let
((key (car item))
(count (cadr item)))
(if (equal (substring key -5) "-mode")
(setq key (substring key 0 -5)))
(princ (format "%2d %20s %s\n" count key
(make-string count ?+))))))))
Various things about the formatting could be improved. E.g., not use fixed-width fields for the count and the mode names, and make the + signs indicate more than one buffer mode when there are many.