Some things I'd like to show in the mode-line are quite expensive to compute, so I'd rather use an idle timer.

Is there a general way to do this? or does this need to be added individually? (using a method similar to which-function-mode, for example).

  • Here is what I did a few years ago as a workaround and have been happily using it ever since: Use a pre-command-hook and a post-command-hook to record (for purposes of comparison) four (4) values each command loop: this-command; last-command; the currently (selected-window); and, the previously (selected-window). Set up a set of rules regarding which commands have a high rate of repetition; e.g., undo / redo; left-char / right-char; scroll-up / scroll-down; etc... [To be continued in the following comment hereinbelow.] – lawlist Nov 15 '20 at 16:27
  • Continuation: If this-command is eq to last-command and the current command is a memq of the list of the aforementioned high rate of repetition commands, then use a pre-recorded value for the expensive command. When the aforementioned situation is not happening, anything that is expensive gets calculated and stored to a variable using format-mode-line to convert it to a string, which can contain colors as well as other properties for mouse-over help, etc. When the aforementioned condition exists, the stored values are used for the expensive components of the mode-line. – lawlist Nov 15 '20 at 16:37
  • Continuation: Here is the function I use for the post-command-hook: (defun ml-post-command-hook-fn () (setq ml-selected-window--post-command-hook (selected-window))) Here is the function I use for the pre-command-hook: (defun ml-pre-command-hook-fn () (setq ml-selected-window--pre-command-hook (selected-window)) (setq ml-this-command this-command) (setq ml-last-command last-command)). These values can also be used to differentiate the mode-line in the selected-window versus a non-selected window, so the colors and so forth for the components can be different; e.g., dim / bold. – lawlist Nov 15 '20 at 16:43
  • Continuation: If changing colors in the mode-line for the mode-line face and the mode-line-inactive face and the minibuffer-prompt face to better distinguish between a selected window versus a non-selected window -- in conjunction with the method described in the previous comments -- be sure to use the face-remapping-alist instead of expensive functions such as set-face-attribute and the like. Use methods such as setq-default and setq-local ... The manual suggests using face-remap-add-relative instead of directly controlling the face-remapping-alist, but I am adventurous. – lawlist Nov 15 '20 at 16:53
  • Continuation: Be aware that this-command and last-command have a short shelf-life, which is why it must be recorded and that recorded value is used when the mode-line is being computed / updated; i.e., when comparing ml-this-command to ml-last-command. When the mode-line is computed / updated the (selected-window) also changes, which why it is necessary to use the recorded values instead for comparison purposes; i.e., ml-selected-window--post-command-hook versus ml-selected-window--pre-command-hook (both of which are custom global variables). – lawlist Nov 15 '20 at 17:09

This can be done using idle timers, although this can get a little involved if you have multiple idle timers and want to prevent them setting each other off.

I've wrapped this up into a small package: mode-line-idle, a small dedicated package which does just this, without any configuration or minor-modes.

Calls to the main function can be done in :eval blocks in the mode-line-format variable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.