bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#41758: 28.0.50; Fix and extend format-spec


From: Basil L. Contovounesios
Subject: bug#41758: 28.0.50; Fix and extend format-spec
Date: Mon, 08 Jun 2020 00:50:22 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

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

Attachment: 0001-Fix-and-extend-format-spec.patch
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]