1

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))))))

1 Answer 1

1

I think you're looking for the format-mode-line function.

E.g. you could do something like:

(:eval
 (if <reuse>
     my-local-var
   (setq-local my-local-var
      (format-mode-line
       `(:propertize ...)))))
1
  • Yes, Emacs works like new again -- thank you very much -- greatly appreciated!
    – lawlist
    Aug 8, 2015 at 4:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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