macOS Emacs 26 display-line-numbers, neotree and me, or How I Became an Emacs Power User Today
I’ve been reviving my GNU Emacs config as part of becoming a more active daily user. I typically use a macOS workstation, sometimes connecting to Linux machines (tramp/ssh). The release of Emacs 26.1 about a week ago gave me additional impetus to consume
Emacs’s customizable, extensible goodness.
- Table of Contents
The origins of my current emacs config1 are from Emacs Bootstrap. I forget exactly when I first declared “Emacs bankruptcy” and started over with the emacs-bootstrap files as a template. Originally I tried a
helm-based completion setup but
helm never really clicked with me.
In my most recent overhaul, I have switched to
company for completions. And I am coming around to using
projectile and its related packages.
projectile helps me with myriad Git clones, including on remote hosts.
tramp is the greatest thing including the proverbial Emacs kitchen sink, BTW!
Any way, this tidbit from the NEWS file caught my eyes:
** Emacs now supports optional display of line numbers in the buffer. This is similar to what 'linum-mode' provides, but much faster and doesn't usurp the display margin for the line numbers. Customize the buffer-local variable 'display-line-numbers' to activate this optional display. Alternatively, you can use the 'display-line-numbers-mode' minor mode or the global 'global-display-line-numbers-mode'. When using these modes, customize 'display-line-numbers-type' with the same value as you would use with 'display-line-numbers'. Line numbers are not displayed at all in minibuffer windows and in tooltips, as they are not useful there. Lisp programs can disable line-number display for a particular screen line by putting the 'display-line-numbers-disable' text property or overlay property on the first character of that screen line. This is intended for add-on packages that need a finer control of the display. Lisp programs that need to know how much screen estate is used up for line-number display in a window can use the new function 'line-number-display-width'. 'linum-mode' and all similar packages are henceforth becoming obsolete. Users and developers are encouraged to switch to this new feature instead.
So Emacs 26 has deprecated
Side note: filed an issue for hlinum-mode since it works with
linum-mode but does not work with Emacs 26
display-line-numbers.el. It was closed with a “not going to fix”, as apparently the hooks that it had relied on are gone with the new, preferred-in-Emacs-26 way.
display-line-numbers out of the box
I have been using neotree package, which I would describe as a “sidebar and dired in one”. It can work with
projectile and so is a nice way to navigate and grok fresh projects.
Since everything in Emacs is “just a buffer”,
neotree hadnt yet been updated to work with the
display-line-numbers hotness new in Emacs 26. So it looked like this with
Note the line numbers being included on the left side of the image, in the
The Process of Getting
display-line-numbers to Play Nice Together
No problem. I knew that
neotree already had a hook allowing this behavior to be overridden. In fact, this same hook was the way to turn off
linum-mode numbering (the pre-Emacs 26 way) in
neotree2. Lemme just use the same hook,
(defun display-line-numbers-disable-hook () "Disable display-line-numbers locally." (display-line-numbers-mode -1)) ;; Disable line-numbers minor mode for neotree (add-hook 'neo-after-create-hook 'display-line-numbers-disable-hook)
Problem solved, right? No. Got an error in the emacs
mode-line (mode-line status text is impossible to copy directly to system clipboard, BTW):
Wrong number of arguments: (lambda nil "Disable display-line-numbers locally." (display-line-numbers-mode -1)), 1
I am by no means expert in
emacs-lisp but have been reading about it and trying to understand basic functionality. Maybe I was creating the function for the hook wrong? After some googling, I thought that this related form might work:
(add-hook 'neo-after-create-hook (lambda () (display-line-numbers-mode -1)))
Nope. Got the same error! What is going on?
…looking further at the error in the
run-hook-with-args: Wrong number of arguments: (lambda nil (display-line-numbers-mode -1)), 1
OK. This might be a helpful clue? The function being called is
run-hook-with-args, but my
hook functions didn’t expect any arguments.
**Some more googling**
The emacs manual says that
run-hook-with-args is a less common way to implement hooks. Tracing
neo-after-create-hook into the
neotree.el source I arrived at:
(run-hook-with-args 'neo-after-create-hook '(window))
It turns out
neotree was passing a
'(window) argument to the hook function(s).
So all I really needed was a
hook function that could accept another argument to its invocation. OK, I just need to add this to my
hook function. I remember seeing
&optional all over the place in the emacs manual info browser in function call signatures. I’ll just use one of those:
;; Disable line-numbers minor mode for neotree (add-hook 'neo-after-create-hook (lambda (&optional dummy) (display-line-numbers-mode -1)))
For the full config I use for
neotree on Emacs 26 and
;; original post had this (lambda (&optional dummy) ...
a better way would be
;; more idiomatic of emacs (lambda (&rest _) ...
so I’ve updated the gist.
Turns out having all the source code and built-in introspection and help files for your editor, that you can edit, are a “Really Good Idea”
Emacs is like the infinity editor.