mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-13 09:32:47 +00:00
Add a SPLIT parameter to `format-spec'
* doc/lispref/strings.texi (Custom Format Strings): Document it. * lisp/format-spec.el (format-spec): Add an optional parameter to return a list of strings (bug#33740).
This commit is contained in:
parent
3334dd9041
commit
40d1633259
@ -1216,7 +1216,7 @@ The function @code{format-spec} described in this section performs a
|
||||
similar function to @code{format}, except it operates on format
|
||||
control strings that use arbitrary specification characters.
|
||||
|
||||
@defun format-spec template spec-alist &optional ignore-missing
|
||||
@defun format-spec template spec-alist &optional ignore-missing split
|
||||
This function returns a string produced from the format string
|
||||
@var{template} according to conversions specified in @var{spec-alist},
|
||||
which is an alist (@pxref{Association Lists}) of the form
|
||||
@ -1258,6 +1258,16 @@ any; if it is @code{delete}, those format specifications are removed
|
||||
from the output; any other non-@code{nil} value is handled like
|
||||
@code{ignore}, but any occurrences of @samp{%%} are also left verbatim
|
||||
in the output.
|
||||
|
||||
If the optional argument @var{split} is non-@code{nil}, instead of
|
||||
returning a single string, @code{format-spec} will split the result
|
||||
into a list of strings, based on where the substitutions were
|
||||
performed. For instance:
|
||||
|
||||
@example
|
||||
(format-spec "foo %b bar" '((?b . "zot")) nil t)
|
||||
@result{} ("foo " "zot" " bar")
|
||||
@end example
|
||||
@end defun
|
||||
|
||||
The syntax of format specifications accepted by @code{format-spec} is
|
||||
|
5
etc/NEWS
5
etc/NEWS
@ -2179,6 +2179,11 @@ In order for the two functions to behave more consistently,
|
||||
length, and also supports format specifications that include a
|
||||
truncating precision field, such as "%.2a".
|
||||
|
||||
+++
|
||||
** 'format-spec' now takes an optional SPLIT parameter.
|
||||
If non-nil, 'format-spec' will split the resulting string into a list
|
||||
of strings, based on where the format specs (and expansions) were.
|
||||
|
||||
---
|
||||
** New function 'color-values-from-color-spec'.
|
||||
This can be used to parse RGB color specs in several formats and
|
||||
|
@ -25,7 +25,7 @@
|
||||
;;; Code:
|
||||
|
||||
;;;###autoload
|
||||
(defun format-spec (format specification &optional ignore-missing)
|
||||
(defun format-spec (format specification &optional ignore-missing split)
|
||||
"Return a string based on FORMAT and SPECIFICATION.
|
||||
FORMAT is a string containing `format'-like specs like \"su - %u %k\".
|
||||
SPECIFICATION is an alist mapping format specification characters
|
||||
@ -68,50 +68,65 @@ error; if it is the symbol `ignore', leave those %-specs verbatim
|
||||
in the result, including their text properties, if any; if it is
|
||||
the symbol `delete', remove those %-specs from the result;
|
||||
otherwise do the same as for the symbol `ignore', but also leave
|
||||
any occurrences of \"%%\" in FORMAT verbatim in the result."
|
||||
any occurrences of \"%%\" in FORMAT verbatim in the result.
|
||||
|
||||
If SPLIT, instead of returning a single string, a list of strings
|
||||
is returned, where each format spec is its own element."
|
||||
(with-temp-buffer
|
||||
(insert format)
|
||||
(goto-char (point-min))
|
||||
(while (search-forward "%" nil t)
|
||||
(cond
|
||||
;; Quoted percent sign.
|
||||
((= (following-char) ?%)
|
||||
(when (memq ignore-missing '(nil ignore delete))
|
||||
(delete-char 1)))
|
||||
;; Valid format spec.
|
||||
((looking-at (rx (? (group (+ (in " 0<>^_-"))))
|
||||
(? (group (+ digit)))
|
||||
(? (group ?. (+ digit)))
|
||||
(group alpha)))
|
||||
(let* ((beg (point))
|
||||
(end (match-end 0))
|
||||
(flags (match-string 1))
|
||||
(width (match-string 2))
|
||||
(trunc (match-string 3))
|
||||
(char (string-to-char (match-string 4)))
|
||||
(text (assq char specification)))
|
||||
(cond (text
|
||||
;; Handle flags.
|
||||
(setq text (format-spec--do-flags
|
||||
(format "%s" (cdr text))
|
||||
(format-spec--parse-flags flags)
|
||||
(and width (string-to-number width))
|
||||
(and trunc (car (read-from-string trunc 1)))))
|
||||
;; Insert first, to preserve text properties.
|
||||
(insert-and-inherit text)
|
||||
;; Delete the specifier body.
|
||||
(delete-region (point) (+ end (length text)))
|
||||
;; Delete the percent sign.
|
||||
(delete-region (1- beg) beg))
|
||||
((eq ignore-missing 'delete)
|
||||
;; Delete the whole format spec.
|
||||
(delete-region (1- beg) end))
|
||||
((not ignore-missing)
|
||||
(error "Invalid format character: `%%%c'" char)))))
|
||||
;; Signal an error on bogus format strings.
|
||||
((not ignore-missing)
|
||||
(error "Invalid format string"))))
|
||||
(buffer-string)))
|
||||
(let ((split-start (point-min))
|
||||
(split-result nil))
|
||||
(insert format)
|
||||
(goto-char (point-min))
|
||||
(while (search-forward "%" nil t)
|
||||
(cond
|
||||
;; Quoted percent sign.
|
||||
((= (following-char) ?%)
|
||||
(when (memq ignore-missing '(nil ignore delete))
|
||||
(delete-char 1)))
|
||||
;; Valid format spec.
|
||||
((looking-at (rx (? (group (+ (in " 0<>^_-"))))
|
||||
(? (group (+ digit)))
|
||||
(? (group ?. (+ digit)))
|
||||
(group alpha)))
|
||||
(let* ((beg (point))
|
||||
(end (match-end 0))
|
||||
(flags (match-string 1))
|
||||
(width (match-string 2))
|
||||
(trunc (match-string 3))
|
||||
(char (string-to-char (match-string 4)))
|
||||
(text (assq char specification)))
|
||||
(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-spec--parse-flags flags)
|
||||
(and width (string-to-number width))
|
||||
(and trunc (car (read-from-string trunc 1)))))
|
||||
;; Insert first, to preserve text properties.
|
||||
(insert-and-inherit text)
|
||||
;; Delete the specifier body.
|
||||
(delete-region (point) (+ end (length text)))
|
||||
;; Delete the percent sign.
|
||||
(delete-region (1- beg) beg))
|
||||
((eq ignore-missing 'delete)
|
||||
;; Delete the whole format spec.
|
||||
(delete-region (1- beg) end))
|
||||
((not ignore-missing)
|
||||
(error "Invalid format character: `%%%c'" char)))
|
||||
(when split
|
||||
(push (buffer-substring (1- beg) (point)) split-result)
|
||||
(setq split-start (point)))))
|
||||
;; Signal an error on bogus format strings.
|
||||
((not ignore-missing)
|
||||
(error "Invalid format string"))))
|
||||
(if (not split)
|
||||
(buffer-string)
|
||||
(unless (= split-start (point-max))
|
||||
(push (buffer-substring split-start (point-max)) split-result))
|
||||
(nreverse split-result)))))
|
||||
|
||||
(defun format-spec--do-flags (str flags width trunc)
|
||||
"Return STR formatted according to FLAGS, WIDTH, and TRUNC.
|
||||
|
@ -178,4 +178,14 @@
|
||||
(should (equal (format-spec "foo %>4b zot" '((?b . "longbar")))
|
||||
"foo long zot")))
|
||||
|
||||
(ert-deftest format-spec-split ()
|
||||
(should (equal (format-spec "foo %b bar" '((?b . "zot")) nil t)
|
||||
'("foo " "zot" " bar")))
|
||||
(should (equal (format-spec "%b bar" '((?b . "zot")) nil t)
|
||||
'("zot" " bar")))
|
||||
(should (equal (format-spec "%b" '((?b . "zot")) nil t)
|
||||
'("zot")))
|
||||
(should (equal (format-spec "foo %b" '((?b . "zot")) nil t)
|
||||
'("foo " "zot"))))
|
||||
|
||||
;;; format-spec-tests.el ends here
|
||||
|
Loading…
Reference in New Issue
Block a user