(Note to English-speaking readers: the links entitled Komentarze na tej stronie lead to comment pages.)
Emacs has had suggesting keybindings for some time (according to
blame, about four years): if you M-x some command, and that command has a keybinding, it will show sth like
You can run the command ‘find-file’ with C-x C-f
for two seconds (by default). It is quite nice, non-intrusive and helpful.
Emacs 25.1 took that to the next level. When you M-x some command now, and it is possible to M-x it with much fewer keystrokes (thanks to autocompletion), a message like
You can run the command ‘emacs-uptime’ with M-x -upt RET
will be shown.
And for some reason I don’t like it. Not that it’s bad; it’s not, and it can be useful. I just find it annoying sometimes, especially that it does not play well with Ivy: in stock Emacs, it will not annoy you if your way of invoking the command is not much longer that the optimum, and with Ivy this mechanism somehow won’t work. Anyway, it turns out that it’s easy to disable: just put this line
(setq extended-command-suggest-shorter nil)
init.el. (You can also customize the option
suggest-key-bindings to the length of time in seconds – not necessarily an integer! – to change the amout of time the message is visible.)
In case you actually want to have that hint, here’s one way to do it:
(defun display-extended-command-shorter (command) "Display information on a shorter way to M-x a command." (interactive (list (read-extended-command))) (message "The command `%s' can be invoked with `M-x %s'" command (execute-extended-command--shorter command command)))
It’s old news, but I was reminded about it recently. While Emacs has had support for rectangle operations (press
C-x r C-h and look for commands with “rectangle” in their name) since a very long time, it acquired
rectangle-mark-mode rather recently (a few years ago, in v24.4). It is a minor mode, switched on by
C-x SPC, which temporarily (until the region is deactivated) highlights it as a rectangle, and changes the killing and yanking operations to their rectangle analogs. Also,
C-x C-x in that mode behaves in a funny (though perfectly reasonable!) way. Of course, it doesn’t do anything that couldn’t be done earlier with rectangle commands, but you don’t need to remember so many keybindings anymore – just press
C-x SPC and things like
M-w Just Work™.
If you are like me, you probably check your email too often. (Maybe nobody does anything stupid like that and it’s only me who has such unproductive habits, but I doubt it…) As many Emacs users, I try to boost my productivity, and email notifications or checking email too often is a great way to actually worsen it.
What I do is hit Update way too often in my mu4e. To the point that I even wished it was possible that my email client said to me: /tsk tsk, you’ve just checked your email, you’d better wait another 30 minutes before you do that again!/
Ah, wait a moment.
So, here is my first (actually, second, but don’t tell anyone) stab at it.
(defun not-too-often-add-guard (fun interval) "Add a not-too-often guard to FUN with INTERVAL. This means that if FUN gets called less than INTERVAL minutes after last call, the use is asked whether s?he really wants to run the command." (let* ((fun-name (symbol-name fun)) (nto-int-sym (intern (concat "not-too-often-interval-" fun-name))) (nto-last-time-sym (intern (concat "not-too-often-last-time-" fun-name))) (nto-guard-sym (intern (concat "not-too-often-guard-" fun-name)))) (set nto-int-sym interval) (set nto-last-time-sym 0) (fset nto-guard-sym (lambda (orig-fun &rest args) (let ((elapsed (time-to-seconds (time-subtract (current-time) (symbol-value nto-last-time-sym))))) (if (< elapsed (* 60 (symbol-value nto-int-sym))) (cond ((y-or-n-p (format "You called %s %s minutes ago. Are you sure you want to proceed? " fun-name (/ elapsed 60.0))) (set nto-last-time-sym (current-time)) (apply orig-fun args)) (t (keyboard-quit))) (set nto-last-time-sym (current-time)) (apply orig-fun args))))) (put nto-guard-sym 'function-documentation (format "Issue a warning if function `%s' is called less than %s minutes from last call." fun-name interval)) (advice-add fun :around nto-guard-sym)))
It works, and this is pretty much everything I can say about it. In fact, when I posted this to the Emacs ML, Michael Heerdegen suggested a nice improvement: a way to create generic functions (closures, in fact) which measure time since their last invocation. (If it were Java, it would be called
GenericStopWatchMeasuringTimeFromLastInvocationFactory, I guess. I’d take the liberty of calling it
create-stopwatch, though.) After some consideration, I decided that I won’t use that solution (even though it is nice). While I know that closures can serve to hide (“encapsulate”) the “private” variables (like
not-too-often-interval-mu4e-update-mail-and-index) so that it is impossible (well, not really impossible, but difficult) to access them from outside code, this is not exactly what I want: I guess it is actually desirable for the user to be able to access those variables. And now that I think about it, it would even be better to use
defcustom for them, so that the user could inspect them using the “Customize” interface.
It seems that my above code will need some refactoring… And while at that, I could (also per Michael’s suggestion) get rid of that
fset stuff, and make my
not-too-often-guard function into a macro. Then, I could utilize the backquoting mechanism to achieve a similar effect in a nicer way.
So, expect a follow-up to this post in some time!
(Więcej means More in Polish; click it to see older entries.)