diff options
author | Lars Ingebrigtsen <larsi@gnus.org> | 2019-07-11 18:44:30 +0200 |
---|---|---|
committer | Lars Ingebrigtsen <larsi@gnus.org> | 2019-07-11 18:44:30 +0200 |
commit | b44f0c457997af53808218536ebfdf507ddb5995 (patch) | |
tree | c4fc4df143a0e913b8c6d9ea91ac159b4afd102f | |
parent | b41ddb7a8b11c8234e2f010d0db1b13e395468ae (diff) | |
download | emacs-b44f0c457997af53808218536ebfdf507ddb5995.tar.gz |
Allow passing unknown specs to format-spec
* 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.
-rw-r--r-- | lisp/format-spec.el | 69 | ||||
-rw-r--r-- | test/lisp/format-spec-tests.el | 12 |
2 files changed, 53 insertions, 28 deletions
diff --git a/lisp/format-spec.el b/lisp/format-spec.el index 4455c594286..cf2d364bb28 100644 --- a/lisp/format-spec.el +++ b/lisp/format-spec.el @@ -24,40 +24,55 @@ ;;; 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) diff --git a/test/lisp/format-spec-tests.el b/test/lisp/format-spec-tests.el index a5c62ac9ce3..e831657a3e6 100644 --- a/test/lisp/format-spec-tests.el +++ b/test/lisp/format-spec-tests.el @@ -23,11 +23,21 @@ (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 |