Make format-spec accept function substitutions
* lisp/format-spec.el (format-spec): Accept a function producing the substitution for a character. * doc/lispref/strings.texi (Custom Format Strings): Document the above change. * test/lisp/format-spec-tests.el (format-spec/function): New test. Ref. https://lists.gnu.org/r/emacs-devel/2022-09/msg01875.html
This commit is contained in:
parent
423bdd5f7f
commit
5281946fbf
4 changed files with 37 additions and 2 deletions
|
@ -1293,6 +1293,11 @@ The order of specifications in @var{template} need not correspond to
|
|||
the order of associations in @var{spec-alist}.
|
||||
@end itemize
|
||||
|
||||
REPLACEMENT can also be a function taking no arguments, and returning
|
||||
a string to be used for the replacement. It will only be called when
|
||||
the corresponding LETTER is used in the TEMPLATE. This is useful, for
|
||||
example, to avoid prompting for input unless it is needed.
|
||||
|
||||
The optional argument @var{ignore-missing} indicates how to handle
|
||||
specification characters in @var{template} that are not found in
|
||||
@var{spec-alist}. If it is @code{nil} or omitted, the function
|
||||
|
|
6
etc/NEWS
6
etc/NEWS
|
@ -3926,6 +3926,12 @@ the same but works by modifying LIST destructively.
|
|||
---
|
||||
** 'string-split' is now an alias for 'split-string'.
|
||||
|
||||
+++
|
||||
** 'format-spec' now accepts functions in the replacement.
|
||||
The function is called only when used in the format string. This is
|
||||
useful to avoid side-effects such as prompting, when the value is not
|
||||
actually being used for anything.
|
||||
|
||||
+++
|
||||
** The variable 'max-specpdl-size' has been made obsolete.
|
||||
Now 'max-lisp-eval-depth' alone is used for limiting Lisp recursion
|
||||
|
|
|
@ -59,6 +59,18 @@ value associated with ?b in SPECIFICATION, either padding it with
|
|||
leading zeros or truncating leading characters until it's ten
|
||||
characters wide\".
|
||||
|
||||
the substitution for a specification character can also be a
|
||||
function, taking no arguments and returning a string to be used
|
||||
for the replacement. It will only be called if FORMAT uses that
|
||||
character. For example:
|
||||
|
||||
(format-spec \"%n\"
|
||||
\\=`((?n . ,(lambda ()
|
||||
(read-number \"Number: \")))))
|
||||
|
||||
Note that it is best to make sure the function is not quoted,
|
||||
like above, so that it is compiled by the byte-compiler.
|
||||
|
||||
Any text properties of FORMAT are copied to the result, with any
|
||||
text properties of a %-spec itself copied to its substitution.
|
||||
|
||||
|
@ -94,14 +106,15 @@ is returned, where each format spec is its own element."
|
|||
(width (match-string 2))
|
||||
(trunc (match-string 3))
|
||||
(char (string-to-char (match-string 4)))
|
||||
(text (assq char specification)))
|
||||
(text (let ((res (cdr (assq char specification))))
|
||||
(if (functionp res) (funcall res) res))))
|
||||
(when (and split
|
||||
(not (= (1- beg) split-start)))
|
||||
(push (buffer-substring split-start (1- beg)) split-result))
|
||||
(cond (text
|
||||
;; Handle flags.
|
||||
(setq text (format-spec--do-flags
|
||||
(format "%s" (cdr text))
|
||||
(format "%s" text)
|
||||
(format-spec--parse-flags flags)
|
||||
(and width (string-to-number width))
|
||||
(and trunc (car (read-from-string trunc 1)))))
|
||||
|
|
|
@ -148,6 +148,17 @@
|
|||
(format-spec fmt '((?b . "asd") (?a . "fgh")))
|
||||
#("fgh%asdasd" 0 3 (a b) 3 4 (c d) 7 10 (e f))))))
|
||||
|
||||
(ert-deftest format-spec/function ()
|
||||
(let* (called
|
||||
(spec `((?a . "foo")
|
||||
(?f . ,(lambda ()
|
||||
(setq called t)
|
||||
"bar")))))
|
||||
(should (equal (format-spec "%a" spec) "foo"))
|
||||
(should-not called)
|
||||
(should (equal (format-spec "%f" spec) "bar"))
|
||||
(should called)))
|
||||
|
||||
(ert-deftest format-spec-unknown ()
|
||||
(should-error (format-spec "foo %b %z zot" '((?b . "bar"))))
|
||||
(should-error (format-spec "foo %b %%%z zot" '((?b . "bar"))))
|
||||
|
|
Loading…
Add table
Reference in a new issue