The default mode line looks like this:
At least, it looks sort of like this if you ignore the lamenesses in the screenshot. If you’re like me you probably don’t remember what all these things mean, at least not without looking them up. What’s that “U”? Why the “:” or why three hyphens?
At a local Emacs meetup with Damon Haley and Greg Pfeil, Greg mentioned that he’d done some experiments on using unicode characters in his mode-line. I decided to give it a try.
I took a good look at the above. I rarely use any of it — I normally don’t care about the coding system or the line ending style. I can’t remember the last time I had a buffer that was both read-only and modified. The VC information, when it appears, is generally too verbose and doesn’t show me the one thing I need to know (see below). And, though I do like to see the name of the major mode, I don’t really need to see most minor mode names; furthermore I like to have a bit of extra space so that I can use other modes that display information that I do want to see in the mode line.
What’s that VC thing? Well, ordinarily you may see something like Git-master
in the mode line. But, usually I already know the version control system being used — or even if I don’t know, I probably don’t care if I am using VC. By default the branch name is in there too. This can be quite long and seems to get stale when I switch branches; and anyway because I do a lot of work via vc-dir
, I don’t really need this in every buffer anyway.
However, what is missing is that the mode-line won’t tell me if a buffer should be registered with version control but is not. This is a pretty common source of errors.
So, first the code to deal with the VC state. We need a bit more code than you might think, because the information we need isn’t already computed, and my tries to compute it while updating the mode line caused weird behavior. Our rule for “should be registered” is “a VC back end claims this file, but the file isn’t actually registered”:
(defvar tromey-vc-mode nil) (make-variable-buffer-local 'tromey-vc-mode) (require 'vc) (defun tromey-vc-command-hook (&rest args) (let ((file-name (buffer-file-name))) (setq tromey-vc-mode (and file-name (not (vc-registered file-name)) (ignore-errors (vc-responsible-backend file-name)))))) (add-hook 'vc-post-command-functions #'tromey-vc-command-hook) (add-hook 'find-file-hook #'tromey-vc-command-hook) (defun tromey-vc-info () (if tromey-vc-mode (propertize (string #x26c3 32) 'face 'error) " "))
We’ll use that final function in the mode line. Note the odd character in there — my choice was U+26C3 (BLACK DRAUGHTS KING), since I thought it looked disk-drive-like — but you can easily replace it with something else. (Also note the weirdness of using string
rather than a string constant. This is just for WordPress’ benefit as its editor kept mangling the actual character.)
To deal with minor modes, I used diminish. This made it easy to remove any display of some modes that I don’t care to know about, and replace the name of some others with a single character:
(require 'diminish) (diminish 'abbrev-mode) (diminish 'projectile-mode) (diminish 'eldoc-mode) (diminish 'flyspell-mode (string 32 #x2708)) (diminish 'auto-fill-function (string 32 #xa7)) (diminish 'isearch-mode (string 32 #x279c))
Here flyspell is U+2708 (AIRPLANE), auto-fill is U+00A7 (SECTION SIGN), and isearch is U+279C (HEAVY ROUND-TIPPED RIGHTWARDS ARROW). Haha, Unicode names.
I wanted to try out which-func-mode
, now that I had extra space on the mode line, so:
(setq which-func-unknown "") (which-function-mode)
Finally, we can use all the above and remove some other things from the mode line at the same time:
(setq-default mode-line-format '("%e" (:eval (if (buffer-modified-p) (propertize (string #x21a7) 'face 'error) " ")) (:eval (tromey-vc-info)) " " mode-line-buffer-identification " " mode-line-position " " mode-line-modes mode-line-misc-info))
The “modified” character in there is U+21A7 (DOWNWARDS ARROW FROM BAR).
Here’s how it looks normally (another badly cropped screenshot):
Here’s how it looks when the file is not registered with the version control system:
And here’s how it looks when the file is also modified:
Occasionally I run into some other minor mode I want to diminish, but this is easily done by editing it into my .emacs and evaluating it for immediate effect.
3 Comments
There are lots of great single-character symbols scattered around the unicode map. If you want to browse the map, try gucharmap on Linux. You’ll find all sorts of oddities which might be useful, like:
U+2328 KEYBOARD
U+2332 CONICAL TAPER (looks like a paper airplane)
U+26CF PICK (if you happen to be editing Minecraft)
For modelines, you may want to study Block Elements unicode block:
U+2580 UPPER HALF BLOCK
to
U+259F QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
and Box Drawing unicode block:
U+2500 BOX DRAWINGS LIGHT HORIZONTAL
through to
U+257F BOX DRAWINGS HEAVY UP AND LIGHT DOWN
Browse unicode characters in emacs:
(defun list-unicode-display (&optional regexp)
“Display a list of unicode characters and their names in a buffer.”
(interactive “sRegexp (default \”.*\”): “)
(let* ((regexp (or regexp “.*”))
(case-fold-search t)
(cmp (lambda (x y) (< (cdr x) (cdr y))))
;; alist like ("name" . code-point)
(char-alist (sort (cl-remove-if-not (lambda (x) (string-match regexp (car x)))
(ucs-names))
cmp)))
(with-help-window "*Unicode characters*"
(with-current-buffer standard-output
(dolist (c char-alist)
(insert (format "0x%06X\t" (cdr c)))
(insert (cdr c))
(insert (format "\t%s\n" (car c))))))))
I took the liberty of wrapping up @jpkotta’s code from the above comment as a package.