El formato s-lex de s.el es realmente lo que quieres, pero si realmente quieres poner código dentro de los bloques de sustitución y no solo nombres de variables, escribí esto como una prueba de concepto.
(defmacro fmt (str)
"Elisp string interpolation for any expression."
(let ((exprs nil))
(with-temp-buffer
(insert str)
(goto-char 1)
(while (re-search-forward "#{" nil t 1)
(let ((here (point))
(emptyp (eql (char-after) ?})))
(unless emptyp (push (read (buffer-substring (point) (progn (forward-sexp 1) (point)))) exprs))
(delete-region (- here 2) (progn (search-forward "}") (point)))
(unless emptyp (insert "%s"))
(ignore-errors (forward-char 1))))
(append (list 'format (buffer-string)) (reverse exprs)))))
;; demo with variable and code substitution
(fmt "My name is #{user-full-name}, I am running Emacs #{(if (display-graphic-p) \"with a GUI\" \"in a terminal\")}.")
;; results in
"My name is Jordon Biondo, I am running Emacs with a GUI."
Incluso puedes insertar una fmt
llamada dentro de otra fmt
si estás loco
(fmt "#{(fmt\"#{(fmt\\\"#{user-full-name}\\\")}\")}")
;; =>
"Jordon Biondo"
El código simplemente se expande a una format
llamada para que todas las sustituciones se realicen en orden y se evalúen en tiempo de ejecución.
(cl-prettyexpand '(fmt "Hello, I'm running Emacs #{emacs-version} on a #{system-type} machine with #{(length (window-list))} open windows."))
;; expands to
(format "Hello, I'm running Emacs %s on a %s machine with %s open windows."
emacs-version
system-type
(length (window-list)))
Se podrían hacer mejoras con qué tipo de formato se usa en lugar de usar siempre% s, pero eso tendría que hacerse en tiempo de ejecución y agregaría una sobrecarga, pero podría hacerse rodeando todos los argumentos de formato en una llamada de función que formatea bien las cosas muy bien en tipo, pero en realidad el único escenario en el que desearía que probablemente sea flotante e incluso podría hacer un (formato "% f" flotante) en la sustitución es que estaba desesperado.
Si trabajo más en ello, es más probable que actualice esta esencia en lugar de esta respuesta. https://gist.github.com/jordonbiondo/c4e22b4289be130bc59b