summaryrefslogtreecommitdiff
path: root/lisp/format-spec.el
diff options
context:
space:
mode:
authorLars Ingebrigtsen <larsi@gnus.org>2020-12-29 03:04:51 +0100
committerLars Ingebrigtsen <larsi@gnus.org>2020-12-29 03:04:51 +0100
commit40d16332597d3aa564c9950ae1831faf6867c71a (patch)
treeef7070e55d22a6348beb33594323ca68ae20f36f /lisp/format-spec.el
parent3334dd904157e7b3787f5d32f30b3c31585d047c (diff)
downloademacs-40d16332597d3aa564c9950ae1831faf6867c71a.tar.gz
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).
Diffstat (limited to 'lisp/format-spec.el')
-rw-r--r--lisp/format-spec.el103
1 files changed, 59 insertions, 44 deletions
diff --git a/lisp/format-spec.el b/lisp/format-spec.el
index 6af79a44167..3abcd5183a3 100644
--- a/lisp/format-spec.el
+++ b/lisp/format-spec.el
@@ -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.