Subject: 30.1; `pp' expectation of `emacs-lisp-mode-syntax-table' etc.

From: Drew Adams <[email-masked]>
Date: Tue, 17 Jun 2025 00:29:22 +0000

`pp' was redefined in Emacs 30.1, introducing quite a few changes in
behavior, including the _default_ behavior.  As the function is a basic
workhorse, these behavior changes can be widespread.

The new definition:

(defun pp (object &optional stream)
  "..."
  (cond
   ((and (eq (or stream standard-output) (current-buffer))
         ;; Make sure the current buffer is setup sanely.
         (eq (syntax-table) emacs-lisp-mode-syntax-table)
         (eq indent-line-function #'lisp-indent-line))
    ;; Skip the buffer->string->buffer middle man.
    (funcall pp-default-function object)
    ;; Preserve old behavior of (usually) finishing with a newline.
    (unless (bolp) (insert "\n")))
   (t
    (princ (pp-to-string object) (or stream standard-output)))))

The old definition wass just that `cond' else clause:

  (princ (pp-to-string object) (or stream standard-output))

Is the first `cond' clause "sanity" check really a good one for use by
`pp-default-function' - sufficient and necessary?  I wonder...

For one thing, the option value can be _any_ function.  The _doc_ says
the function should accept 0 or 1 arg and that it "can presume that the
buffer is setup for Lisp syntax."  But the defcustom code doesn't
support/ensure either of those things.

For another thing, that check for a "sane" buffer setup precludes using
`pp-default-function' with a buffer whose syntax table isn't exactly
`emacs-lisp-mode-syntax-table', which means it can't be used for buffers
in `lisp-data-mode'.  Is that really TRT?  Is there some reason not to
use `pp-default-function' with that mode's syntax table?

And why the `indent-line-function' requirement?  Does `pp's use of
`pp-default-function' really need its value to be `lisp-indent-line'?
That seems fragile - or else unncessary.

If these constraints are necessary for option `pp-default-function',
then its doc had really better proclaim them as such, no?  The doc (if
not the defcustom code itself) had better tell users that the function
can only be used in a buffer with that syntax table and with that value
of `indent-line-function'.

I can imagine existing pre-30.1 code ending up (after some debugging)
changing some `pp' calls to (insert (pp-to-string...)), to fix problems
created by this `pp' redefinition.  Or as `bookmark.el' did, to bind
`pp-default-function' to `pp-28' around `pp' calls.

And why is the option called `pp-default-function'?  It's a user option,
and it's used unconditionally - not to provide some function by
_default_.  It should be called `pp-printer-function' or `pp-function'
or some such.  (The FIXME comment refers to it as a "pretty printer"
function.)

My sense is that the 30.1 changes to `pp' were misguided (especially
changing the _default_ behavior).  Call me bad for saying that's what I
smell.  I hope I'm very wrong.

In GNU Emacs 30.1 (build 2, x86_64-w64-mingw32) of 2025-02-23 built on
 AVALON
Windowing system distributor 'Microsoft Corp.', version 10.0.26100
System Description: Microsoft Windows 10 Pro (v10.0.2009.26100.4061)

Configured using:
 'configure --with-modules --without-dbus --with-native-compilation=aot
 --without-compress-install --with-tree-sitter CFLAGS=-O2
 prefix=/g/rel/install/emacs-30.1'

Configured features:
ACL GIF GMP GNUTLS HARFBUZZ JPEG LCMS2 LIBXML2 MODULES NATIVE_COMP
NOTIFY W32NOTIFY PDUMPER PNG RSVG SOUND SQLITE3 THREADS TIFF
TOOLKIT_SCROLL_BARS TREE_SITTER WEBP XPM ZLIB

(NATIVE_COMP present but libgccjit not available)

Important settings:
  value of $LANG: ENU
  locale-coding-system: cp1252