If you really just want a list (and not a tree like format-mode-line
) that can be evaluated takes element-wise to strings and then concatenated mapconcat
and eval
are your friends:
(let ((my-list '("Hello, I am " (number-to-string (user-uid)) " and it is " (format-time-string " %T, %F"))))
(mapconcat #'eval my-list ""))
The output is:
Hello, I am 1000 and it is 11:47:45, 2021-02-03
A more general version can also be implemented quite simple in a recursive way:
(defun tree-to-string (tree &optional lexical)
"Convert TREE recursively to a string.
TREE can be one of the following:
- lists with car :eval : the cdr is evaluated and the result is passed to `tree-to-string'
- other lists: element-wise processed with `tree-to-string'
- any other element: transformed to string with `prin1-to-string'
The optional argument LEXICAL is passed to `eval'."
(if (listp tree)
(if (eq (car tree) :eval)
(tree-to-string (eval (cons 'progn (cdr tree)) lexical))
(mapconcat (lambda (item) (tree-to-string item lexical)) tree ""))
(prin1-to-string tree t)))
(tree-to-string '("Hello, I am " (:eval (user-uid)) (" and it is " (:eval (format-time-string "%T, %F"))) "."))
The output is:
Hello, I am 1000 and it is 11:47:45, 2021-02-03.
format-mode-line
can be used to store any portion of themode-line
as a string -- saving it to a local/global variable -- it is not just for special mode-line codes .... I use it to store an alphabetically sorted minor-mode-alist so that I can use the stored value when I need to save time; e.g., rapid fire movements ... scrolling up/down, moving cursor left/right, etc. The disadvantage, is that the mouse interaction with a saved string will be limited .... To store a value, you can use(setq my-variable (format-mode-line COMPONENT))
– lawlist Feb 3 at 7:16%p
- and similar characters though? (besides replacing%
with%%
). I'm wondering if the ability to merge a string and evaluate:eval
property is available in a more generic, less mode-line spesific function. – ideasman42 Feb 3 at 8:49