Q: How to store/reuse the evaluated result of an element of the mode-line-format
.
I am implementing a system within the mode-line-format
that is similar to how flyspell.el
handles deplacement-commands
-- i.e., if this-command
is eq
to last-command
and this-command
is a member
of the list of deplacement-commands
, then skip the time-costly function(s). I am storing the values for this-command
and last-command
in variables by way of the pre-command-hook
, because those values could not reliably be used otherwise at the time the mode-line-format
is evaluated during redisplay
-- i.e., this-command
and last-command
have short life expetencies.
The following code was developed in a related thread for alphabetizing the minor-mode-alist
: Sort minor-mode-alist alphabetically (in the mode-line) using :lighter However, it is too slow for rapid-fire repetitive commands such as previous-line
, next-line
, left-char
and right-char
.
When "this-command
is eq
to last-command
and this-command
is a member
of the list of deplacement-commands
", I would like to use the previous stored value for the alphabetized minor-mode-alist
. In other words, I do not want Emacs to recalculate the value -- I would like the old value to appear in the mode-line-format
so that it costs nothing in terms of time.
(require 'cl)
(defmacro non-empty-name-p (name) ; Error if NAME is neither nil nor a string.
"NAME if non-nil and not \"\", else nil."
`(and ,name (not (string= "" ,name)) ,name))
(setq mode-line-format '(
(:eval
(let* (
(copied-list
(delq nil
(mapcar
(lambda (x)
(when
(or
(and
(symbolp (cadr x))
(non-empty-name-p (symbol-value (cadr x))))
(stringp (cadr x)))
x))
(copy-list minor-mode-alist))))
(sorted-list
(sort
copied-list
(lambda (x y)
(let* (
(xname (cadr x))
(yname (cadr y)) )
(when (symbolp xname) (setq xname (symbol-value xname)))
(when (symbolp yname) (setq yname (symbol-value yname)))
(when (and (stringp xname) (non-empty-name-p xname)
(stringp yname) (non-empty-name-p yname))
(when (eq ?\s (aref xname 0))
(setq xname (replace-regexp-in-string "^\s" "" xname)))
(when (eq ?\s (aref yname 0))
(setq yname (replace-regexp-in-string "^\s" "" yname)))
(string< xname yname)))))) )
(list
`(:propertize ("" mode-name)
help-echo "Major mode help message."
face '(:foreground "red")
mouse-face '(:foreground "blue")
local-map ,mode-line-major-mode-keymap)
`(:propertize ("" ,sorted-list)
face '(:foreground "purple")
mouse-face '(:foreground "blue")
help-echo "Minor mode help message."
local-map ,mode-line-minor-mode-keymap))))))