s-lex-format s.el benar-benar seperti yang Anda inginkan, tetapi jika Anda ingin benar-benar dapat menempatkan kode di dalam blok substitusi dan bukan hanya nama variabel, saya menulis ini sebagai bukti konsep.
(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."
Anda bahkan dapat menyematkan fmt
panggilan di dalam yang lain fmt
jika Anda gila
(fmt "#{(fmt\"#{(fmt\\\"#{user-full-name}\\\")}\")}")
;; =>
"Jordon Biondo"
Kode hanya mengembang ke format
panggilan sehingga semua pergantian dilakukan secara berurutan dan dievaluasi pada saat dijalankan.
(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)))
Perbaikan dapat dilakukan dengan jenis format apa yang digunakan daripada selalu menggunakan% s, tapi itu harus dilakukan saat runtime dan akan menambah overhead tetapi bisa dilakukan dengan mengelilingi semua format args dalam pemanggilan fungsi yang memformat dengan baik hal-hal berdasarkan pada jenis tetapi sebenarnya satu-satunya skenario di mana Anda ingin yang mungkin mengapung dan Anda bahkan bisa melakukan (format "% f" float) di substitusi adalah Anda putus asa.
Jika saya mengerjakannya lebih banyak, saya lebih cenderung memperbarui inti ini daripada jawaban ini. https://gist.github.com/jordonbiondo/c4e22b4289be130bc59b