GNU bug report logs - #41758
28.0.50; Fix and extend format-spec

Previous Next

Package: emacs;

Reported by: "Basil L. Contovounesios" <contovob <at> tcd.ie>

Date: Sun, 7 Jun 2020 23:51:02 UTC

Severity: normal

Tags: fixed, patch

Found in version 28.0.50

Fixed in version 28.1

Done: "Basil L. Contovounesios" <contovob <at> tcd.ie>

Bug is archived. No further changes may be made.

Full log


Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: "Basil L. Contovounesios" <contovob <at> tcd.ie>
To: bug-gnu-emacs <at> gnu.org
Subject: 28.0.50; Fix and extend format-spec
Date: Mon, 08 Jun 2020 00:50:22 +0100
[Message part 1 (text/plain, inline)]
Tags: patch

I attach a patch which fixes and extends some of the changes made to
format-spec's behaviour in Emacs 27.  Some of the proposed changes were
already alluded to in the discussion of bug#41571.

---

Before Emacs 27, format-spec was implemented in terms of 'format',
allowing e.g.:

  (format-spec "%.2s" '((?s . "שָׁלוֹם"))) ; => "שָׁל"

In Emacs 27, a precision modifier ".N" is still supported (doesn't
signal an error), but is a no-op:

  (format-spec "%.2s" '((?s . "שָׁלוֹם"))) ; => "שָׁלוֹם"

This is arguably a regression (since format-spec's docstring
historically said it supported "'format'-like specs" without explicitly
listing the precision modifier as one of them).  I wouldn't be surprised
if someone misses this feature.

Instead, Emacs 27 added the notion of "padding or truncating" (as a
single operation) to a desired length:

  (format-spec "%>2s" '((?s . "שָׁלוֹם"))) ; => "שָ"

There are two problems with this:
0. Unlike 'format', it truncates to length rather than width.
1. It is impossible to specify separate padding and truncation, e.g.:

  (format "%3.2s" "שָׁלוֹם") ; => " שָׁל"

The attached patch brings back 'format'-like truncation based on string
width, and separate from padding:

  (format-spec "%>2s" '((?s . "שָׁלוֹם")))  ; => "שָׁל"
  (format-spec "%3.2s" '((?s . "שָׁלוֹם"))) ; => " שָׁל"

  (let ((f "%3.2s")
        (s "שָׁלוֹם"))
    (equal (format-spec f `((?s . ,s)))
           (format f s))) ; => t

---

Emacs 27 also added an optional third argument for ignoring the case
when the caller does not provide a particular replacement, e.g.:

  (format-spec "%s" ())   ; => (error "Invalid format character: ‘%s’")
  (format-spec "%s" () t) ; => "%s"

The problem with a non-nil third argument is that it also
unconditionally leaves '%%' verbatim in the output:

  (format-spec "%%%s" () t) ; => "%%%s"

I'm sure this has its uses, but I find it a surprising default since the
replacement of '%%' is always known.  The function battery-format in
lisp/battery.el is an example of where the usual replacement of '%%' is
desirable, even when some replacements are not provided.

The attached patch therefore adds two new special values to the optional
third argument:

  (format-spec "%%%s" () 'ignore) ; => "%%s"
  (format-spec "%%%s" () 'delete) ; => "%"

Together with the Emacs 27 behaviour, I think these should cover most
bases.

WDYT?

Thanks,

-- 
Basil

[0001-Fix-and-extend-format-spec.patch (text/x-diff, attachment)]

This bug report was last modified 4 years and 332 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.