For the English part of the blog, see Content AND Presentation.
I have to admit that I probably have a bit of OCD, and when I finish my work, I like to put my Emacs in a sort of “clean slate” state. By that I don’t mean closing it or killing all buffers (although when I leave the office, I do kill all work-related buffers). Instead, I mean going back to displaying just one window with the *GNU Emacs*
buffer (the one with the logo and links to the tutorial etc.) The problem is, I sometimes accidentally kill that buffer, and then I have no place to go back to.
Well, some time ago it occurred to me that something in Emacs must create that buffer, and I can find that something and learn how to do that whenever I want. Grepping for a few words on that splash screen I quickly found the fancy-startup-screen
function which does exactly that. I was a bit surprised that it is not an interactive function (IOW, a command), but – as I learned several years ago – this is easy to fix:
;; warning: this does not work! (put 'fancy-startup-screen 'interactive-form '(interactive))
Sadly, the interactive-form
symbol property no longer works. As Stefan Monnier pointed out in that thread, there is another (perhaps cleaner) way to make a non-interactive function into a command:
(advice-add 'fancy-startup-screen :before (lambda () (interactive) nil))
This method is a bit more verbose, but is clean, the intent is obvious and – last but not least – it works. What else could you want?
This is a third post in a short series of posts about code which helps me deal with numerical timestamps in Emacs. Last time I wrote a function which decides if a number is a Unix timestamp or a JavaScript Date
and converts it to a human-readable ISO-8601 timestamp. What would be even more useful is to see the ISO representation of the timestamp at point without even doing anything. Emacs already has support for showing stuff related to the thing at point in the modeline – ElDoc. Several years ago I had some thoughts about using the ElDoc machinery to do something for me, but I found it too complicated then.
Well, either they modified ElDoc to make it easier to program, or I matured as a programmer, or both. It turned out that it took me about 15 minutes to come up with a working prototype, which is extremely cool!
One way to use ElDoc in your own Elisp code is to write a function which accepts a single argument callback
, decides if whatever is at point “deserves” printing something in the echo area, and if yes, call the callback
with suitable arguments. This function is next added to eldoc-documentation-functions
. (Check its docstring to learn the exact syntax of the callback
I mentioned above.) Let’s use the code from the previous post and add the following.
(defun timestamp-conversion-eldoc-function (callback) "An ElDoc-compatible wrapper around `number-to-iso-8601'." (when-let* ((number-at-point (thing-at-point 'number)) (timestamp (number-to-iso-8601 number-at-point))) (funcall callback (cdr timestamp) :thing (car timestamp) :face 'font-lock-keyword-face))) (define-minor-mode eldoc-timestamp-conversion-mode "Toggle ElDoc Timestamp Conversion mode. When enabled, this mode causes numbers at point to be displayed as timestamps in the echo area using ElDoc (which must be enabled, too). Numbers greater than `maximum-unix-timestamp-for-conversion' are treated as JavaScript `Date's and the rest as Unix timestamps (seconds since 1970-01-01)." :init-value nil (if eldoc-timestamp-conversion-mode (add-hook 'eldoc-documentation-functions #'timestamp-conversion-eldoc-function nil t) (remove-hook 'eldoc-documentation-functions #'timestamp-conversion-eldoc-function t)))
As you can see, I made a somewhat controversial decision to not have a lighter for this mode – my modeline is very crowded and I really don’t need even more noise there. I use diminish for that, but recently Emacs got a new feature which might make it obsolete for me.
That’s it for today! I’m now going to think what other uses for ElDoc I could have…
For quite a few years, when I needed my Node.js scripts to wait for some time, I used this promisified version of setTimeout
:
const sleep = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds))
Having that function, I can now say await sleep(1000)
to make my script wait a second.
Of course, I could also use util.promisify
for that:
import {promisify} from 'util' const sleep = promisify(setTimeout)
which is a bit shorter and has a very similar effect.
Recently, however, I learned that there is an even shorter way of defining an equivalent sleep
function:
import {setTimeout as sleep} from 'node:timers/promises'
and that’s it! Go check the docs (linked above) to learn about built-in promisified version of setInterval
and a few other utilities in the timers/promises
module.