]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow passing unknown specs to format-spec
authorLars Ingebrigtsen <larsi@gnus.org>
Thu, 11 Jul 2019 16:44:30 +0000 (18:44 +0200)
committerLars Ingebrigtsen <larsi@gnus.org>
Thu, 11 Jul 2019 16:44:30 +0000 (18:44 +0200)
* lisp/format-spec.el (format-spec): Allow passing through format
strings that have no specs (to be able to act as a filter).  Also
add an example.
* test/lisp/format-spec-tests.el (test-format-spec): Add tests for
the new functionality.

lisp/format-spec.el
test/lisp/format-spec-tests.el

index 4455c5942866cb1889c98790e5371565954ea922..cf2d364bb28dbf60dc14e62e75d8c277ac374043 100644 (file)
 
 ;;; Code:
 
-(defun format-spec (format specification)
+(defun format-spec (format specification &optional only-present)
   "Return a string based on FORMAT and SPECIFICATION.
-FORMAT is a string containing `format'-like specs like \"bash %u %k\",
+FORMAT is a string containing `format'-like specs like \"su - %u %k\",
 while SPECIFICATION is an alist mapping from format spec characters
-to values.  Any text properties on a %-spec itself are propagated to
-the text that it generates."
+to values.
+
+For instance:
+
+  (format-spec \"su - %u %k\"
+               `((?u . ,(user-login-name))
+                 (?k . \"ls\")))
+
+Any text properties on a %-spec itself are propagated to the text
+that it generates.
+
+If ONLY-PRESENT, format spec characters not present in
+SPECIFICATION are ignored, and the \"%\" characters are left
+where they are, including \"%%\" strings."
   (with-temp-buffer
     (insert format)
     (goto-char (point-min))
     (while (search-forward "%" nil t)
       (cond
-       ;; Quoted percent sign.
-       ((eq (char-after) ?%)
-       (delete-char 1))
-       ;; Valid format spec.
-       ((looking-at "\\([-0-9.]*\\)\\([a-zA-Z]\\)")
-       (let* ((num (match-string 1))
-              (spec (string-to-char (match-string 2)))
-              (val (assq spec specification)))
-         (unless val
-           (error "Invalid format character: `%%%c'" spec))
-         (setq val (cdr val))
-         ;; Pad result to desired length.
-         (let ((text (format (concat "%" num "s") val)))
-           ;; Insert first, to preserve text properties.
-           (insert-and-inherit text)
-           ;; Delete the specifier body.
-            (delete-region (+ (match-beginning 0) (length text))
-                           (+ (match-end 0) (length text)))
-            ;; Delete the percent sign.
-            (delete-region (1- (match-beginning 0)) (match-beginning 0)))))
-       ;; Signal an error on bogus format strings.
-       (t
-       (error "Invalid format string"))))
+        ;; Quoted percent sign.
+        ((eq (char-after) ?%)
+         (unless only-present
+          (delete-char 1)))
+        ;; Valid format spec.
+        ((looking-at "\\([-0-9.]*\\)\\([a-zA-Z]\\)")
+        (let* ((num (match-string 1))
+               (spec (string-to-char (match-string 2)))
+               (val (assq spec specification)))
+          (if (not val)
+               (unless only-present
+                (error "Invalid format character: `%%%c'" spec))
+            (setq val (cdr val))
+            ;; Pad result to desired length.
+            (let ((text (format (concat "%" num "s") val)))
+              ;; Insert first, to preserve text properties.
+              (insert-and-inherit text)
+              ;; Delete the specifier body.
+               (delete-region (+ (match-beginning 0) (length text))
+                              (+ (match-end 0) (length text)))
+               ;; Delete the percent sign.
+               (delete-region (1- (match-beginning 0)) (match-beginning 0))))))
+        ;; Signal an error on bogus format strings.
+        (t
+          (unless only-present
+           (error "Invalid format string")))))
     (buffer-string)))
 
 (defun format-spec-make (&rest pairs)
index a5c62ac9ce375e08bea3d2c631af45dd522420f1..e831657a3e65b161c3b387620586fd5fc75ce58d 100644 (file)
 (require 'format-spec)
 
 (ert-deftest test-format-spec ()
-  (should (equal (format-spec "foo %b zot" '((?b . "bar")))
+  (should (equal (format-spec "foo %b zot" `((?b . "bar")))
                  "foo bar zot"))
   (should (equal (format-spec "foo %-10b zot" '((?b . "bar")))
                  "foo bar        zot"))
   (should (equal (format-spec "foo %10b zot" '((?b . "bar")))
                  "foo        bar zot")))
 
+(ert-deftest test-format-unknown ()
+  (should (eq (condition-case _
+                  (format-spec "foo %b %z zot" '((?b . "bar")))
+                (error :error))
+              :error))
+  (should (equal (format-spec "foo %b %z zot" '((?b . "bar")) t)
+                 "foo bar %z zot"))
+  (should (equal (format-spec "foo %b %z %% zot" '((?b . "bar")) t)
+                 "foo bar %z %% zot")))
+
 ;;; format-spec-tests.el ends here