unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#63825: 29.0.90; The header line should be hidden when empty
@ 2023-06-01 13:37 Spencer Baugh
  2023-06-01 16:14 ` Eli Zaretskii
  0 siblings, 1 reply; 16+ messages in thread
From: Spencer Baugh @ 2023-06-01 13:37 UTC (permalink / raw)
  To: 63825


It would be nice if the header line was hidden when it was empty, not
just when header-line-format was nil.  That reduces a bit of visual
noise and gives one more line of text in some buffers.

A concrete use case is with which-func-mode:

1. emacs -Q
2. (setq-default header-line-format
     '((which-func-mode ("" which-func-format " "))))
3. This nicely adds the current function name to the header in code
buffers, but in buffers not supported by which-function-mode (text-mode,
for example) the header line is empty and ugly.

The header-line is rendered by display_mode_line, so we could probably
do this there, wrapping a check around the output from
Fformat_mode_Line.  Then the mode-line would also be hidden if it's
empty, which would also be useful although much more niche.


In GNU Emacs 29.0.90 (build 3, x86_64-pc-linux-gnu, X toolkit, cairo
 version 1.15.12, Xaw scroll bars) of 2023-05-17 built on
 igm-qws-u22796a
Repository revision: 4d08492296c2a6d2910f2b740c2d2508275458fc
Repository branch: emacs-29
Windowing system distributor 'The X.Org Foundation', version 11.0.12011000
System Description: CentOS Linux 7 (Core)

Configured using:
 'configure --with-x-toolkit=lucid --with-gif=ifavailable'

Configured features:
CAIRO DBUS FREETYPE GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG JSON
LIBSELINUX LIBXML2 MODULES NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND
SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS X11 XDBE XIM XINPUT2 XPM LUCID
ZLIB

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: ELisp/d

Minor modes in effect:
  jane-fe-minor-mode: t
  editorconfig-mode: t
  which-function-mode: t
  global-git-commit-mode: t
  magit-auto-revert-mode: t
  shell-dirtrack-mode: t
  server-mode: t
  windmove-mode: t
  savehist-mode: t
  save-place-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tab-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  context-menu-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  line-number-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
/usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/project hides /home/sbaugh/.emacs.d/elpa/project-0.9.8/project
/usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/xref hides /home/sbaugh/.emacs.d/elpa/xref-1.6.3/xref
/usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/csharp-mode hides /home/sbaugh/src/emacs/emacs-29/lisp/progmodes/csharp-mode
/usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/xref hides /home/sbaugh/src/emacs/emacs-29/lisp/progmodes/xref
/usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/project hides /home/sbaugh/src/emacs/emacs-29/lisp/progmodes/project
/usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/eldoc hides /home/sbaugh/src/emacs/emacs-29/lisp/emacs-lisp/eldoc
/usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/auctex/lpath hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/dictionary/lpath
/home/sbaugh/src/emacs/emacs-29/lisp/net/dictionary hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/dictionary/dictionary
/usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/caml-font hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/ocaml/caml-font
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-version hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-version
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-loaddefs hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-loaddefs
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-keys hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-keys
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-perl hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-perl
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-core hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-core
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-rmail hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol-rmail
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-octave hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-octave
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-comint hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-comint
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-w3m hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol-w3m
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-org hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-org
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-texinfo hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox-texinfo
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-inlinetask hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-inlinetask
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-mhe hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol-mhe
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-ocaml hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-ocaml
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-clojure hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-clojure
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-publish hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox-publish
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-irc hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol-irc
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-calc hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-calc
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-odt hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox-odt
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-id hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-id
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-gnus hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol-gnus
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-matlab hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-matlab
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-icalendar hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox-icalendar
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-footnote hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-footnote
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-bibtex hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol-bibtex
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-lisp hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-lisp
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-C hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-C
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-org hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox-org
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-indent hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-indent
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-info hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol-info
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-maxima hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-maxima
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-awk hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-awk
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-man hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox-man
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-goto hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-goto
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-md hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox-md
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-eshell hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol-eshell
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-lua hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-lua
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-habit hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-habit
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-R hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-R
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-eww hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol-eww
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-makefile hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-makefile
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-latex hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox-latex
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-docview hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol-docview
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-lob hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-lob
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-beamer hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox-beamer
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-faces hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-faces
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-html hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox-html
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-feed hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-feed
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-bbdb hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ol-bbdb
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-lilypond hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-lilypond
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-ascii hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ox-ascii
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-latex hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-latex
/home/sbaugh/src/emacs/emacs-29/lisp/org/org hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-tangle hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-tangle
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-tempo hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-tempo
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-duration hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-duration
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-sqlite hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-sqlite
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-entities hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-entities
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-table hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-table
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-js hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-js
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-table hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-table
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-sql hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-sql
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-timer hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-timer
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-element hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-element
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-java hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-java
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-ctags hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-ctags
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-shell hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-shell
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-groovy hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-groovy
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-src hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-src
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-datetree hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-datetree
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-haskell hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-haskell
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-plot hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-plot
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-compat hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-compat
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-screen hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-screen
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-fortran hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-fortran
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-protocol hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-protocol
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-crypt hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-crypt
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-sed hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-sed
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-gnuplot hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-gnuplot
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-pcomplete hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-pcomplete
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-colview hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-colview
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-scheme hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-scheme
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-forth hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-forth
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-num hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-num
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-clock hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-clock
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-exp hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-exp
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-mouse hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-mouse
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-capture hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-capture
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-sass hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-sass
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-eval hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-eval
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-ref hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-ref
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-emacs-lisp hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-emacs-lisp
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-mobile hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-mobile
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-ruby hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-ruby
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-eshell hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-eshell
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-lint hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-lint
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-agenda hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-agenda
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-macro hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-macro
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-attach-git hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-attach-git
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-processing hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-processing
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-css hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-css
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-dot hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-dot
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-list hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-list
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-macs hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-macs
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-attach hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-attach
/home/sbaugh/src/emacs/emacs-29/lisp/org/org-archive hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/org-archive
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-python hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-python
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-plantuml hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-plantuml
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-ditaa hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/lisp/ob-ditaa
/home/sbaugh/src/emacs/emacs-29/lisp/org/ob-julia hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/contrib/lisp/ob-julia
/home/sbaugh/src/emacs/emacs-29/lisp/org/ol-man hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/contrib/lisp/ol-man
/home/sbaugh/src/emacs/emacs-29/lisp/org/ox-koma-letter hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/org/contrib/lisp/ox-koma-letter
/home/sbaugh/.emacs.d/elpa/dash-2.19.1/dash hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/dash/dash
/home/sbaugh/.emacs.d/elpa/dash-2.19.1/dash-functional hides /usr/local/home/sbaugh/workspaces/fe-47828/+share+/app/emacs/elisp/contrib/dash/dash-functional

Features:
(shadow mail-extr emacsbug dabbrev dos-w32 find-cmd tutorial man sort
conf-mode make-mode mule-util completion descr-text cus-start quail
shortdoc cal-iso org-datetree tabify org-capture org-element org-persist
org-id org-refile avl-tree generator oc-basic ol-eww eww xdg url-queue
mm-url ol-rmail ol-mhe ol-irc ol-info ol-gnus nnselect gnus-art mm-uu
mml2015 mm-view mml-smime smime gnutls dig ol-docview doc-view jka-compr
image-mode exif ol-bibtex bibtex ol-bbdb ol-w3m ol-doi org-link-doi misc
pulse find-dired bug-reference magit-imenu git-rebase face-remap vc-bzr
vc-src vc-sccs vc-svn vc-cvs vc-rcs log-view vc-git cl-print dired-aux
help-fns radix-tree misearch multi-isearch vc-fe sh-script treesit
executable goto-addr cus-edit cus-load vc-hg vc-dir vc vc-dispatcher
tramp tramp-cache time-stamp tramp-loaddefs trampver tramp-integration
tramp-compat ls-lisp ffap jane-merlin merlin-imenu merlin-xref
merlin-cap merlin jane-async-merlin jane-completion grep jane-common
jane-fe-project xref jane-fe-menu ecaml_plugin linum view gopcaml
magit-bookmark bookmark image+ advice image-file image-converter
editorconfig editorconfig-core editorconfig-core-handle
editorconfig-fnmatch whitespace jane-auto-modes vba-mode markdown-mode
color jane jane-micro-features jane-diff unified-test-mode shell-file
core core-buffer core-error core-util ert pp ewoc debug backtrace
jane-sexp jane-ocaml jane-tuareg-theme tuareg tuareg-compat tuareg-opam
skeleton flymake-proc flymake warnings thingatpt smie caml-types
caml-help caml-emacs find-file compile jane-cr jane-align
jane-deprecated jane-smerge gnu-elpa-keyring-update jane-ocp-indent
ocp-indent cl jane-util ob-shell page-ext dired-x magit-extras project
magit-submodule magit-obsolete magit-blame magit-stash magit-reflog
magit-bisect magit-push magit-pull magit-fetch magit-clone magit-remote
magit-commit magit-sequence magit-notes magit-worktree magit-tag
magit-merge magit-branch magit-reset magit-files magit-refs magit-status
magit magit-repos magit-apply magit-wip magit-log which-func imenu
magit-diff smerge-mode diff diff-mode git-commit log-edit pcvs-util
add-log magit-core magit-autorevert autorevert filenotify magit-margin
magit-transient magit-process with-editor shell server magit-mode
transient edmacro kmacro magit-git magit-section magit-utils crm dash
cl-extra help-mode windmove org ob ob-tangle ob-ref ob-lob ob-table
ob-exp org-macro org-src ob-comint org-pcomplete pcomplete org-list
org-footnote org-faces org-entities noutline outline icons ob-emacs-lisp
ob-core ob-eval org-cycle org-table ol rx org-fold org-fold-core
org-keys oc org-loaddefs find-func cal-menu calendar cal-loaddefs
gnus-sum shr pixel-fill kinsoku url-file svg dom gnus-group gnus-undo
gnus-start gnus-dbus dbus xml gnus-cloud nnimap nnmail mail-source utf7
nnoo parse-time iso8601 gnus-spec gnus-int gnus-range message sendmail
yank-media puny dired dired-loaddefs rfc822 mml mml-sec epa epg rfc6068
epg-config mm-decode mm-bodies mm-encode mail-parse rfc2231 rfc2047
rfc2045 ietf-drums mailabbrev gmm-utils mailheader gnus-win gnus
nnheader gnus-util text-property-search time-date mail-utils range
mm-util mail-prsvr wid-edit org-version org-compat org-macs format-spec
gdb-mi bindat gud comint easy-mmode files-x derived ansi-osc ansi-color
ring vundo pcase cyberpunk-theme savehist saveplace project-autoloads
vundo-autoloads magit-autoloads xref-autoloads csv-mode-autoloads
magit-section-autoloads cyberpunk-theme-autoloads
url-http-ntlm-autoloads url-auth git-commit-autoloads
with-editor-autoloads finder-inf info dash-autoloads vc-hgcmd-autoloads
package browse-url url url-proxy url-privacy url-expand url-methods
url-history url-cookie generate-lisp-file url-domsuf url-util mailcap
url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs
password-cache json subr-x map byte-opt gv bytecomp byte-compile
url-vars cl-loaddefs cl-lib rmc iso-transl tooltip cconv eldoc paren
electric uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel
term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image
regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode
prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu
timer select scroll-bar mouse jit-lock font-lock syntax font-core
term/tty-colors frame minibuffer nadvice seq simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs
theme-loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads dbusbind inotify
dynamic-setting system-font-setting font-render-setting cairo x-toolkit
xinput2 x multi-tty make-network-process emacs)

Memory information:
((conses 16 1000624 218672)
 (symbols 48 60965 4)
 (strings 32 241531 19923)
 (string-bytes 1 8575945)
 (vectors 16 79618)
 (vector-slots 8 2128035 219488)
 (floats 8 587 496)
 (intervals 56 48581 359)
 (buffers 976 96)
 (heap 1024 603394 253119))





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-01 13:37 bug#63825: 29.0.90; The header line should be hidden when empty Spencer Baugh
@ 2023-06-01 16:14 ` Eli Zaretskii
  2023-06-01 16:45   ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2023-06-01 16:14 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: 63825

> From: Spencer Baugh <sbaugh@janestreet.com>
> Date: Thu, 01 Jun 2023 09:37:38 -0400
> 
> It would be nice if the header line was hidden when it was empty, not
> just when header-line-format was nil.  That reduces a bit of visual
> noise and gives one more line of text in some buffers.

We could maybe do this optionally (although I don't yet see why we
should, see below), but we cannot do this unconditionally: it's an
incompatible change in eons-long behavior.

> A concrete use case is with which-func-mode:
> 
> 1. emacs -Q
> 2. (setq-default header-line-format
>      '((which-func-mode ("" which-func-format " "))))
> 3. This nicely adds the current function name to the header in code
> buffers, but in buffers not supported by which-function-mode (text-mode,
> for example) the header line is empty and ugly.

header-line-format supports :eval and :when, so why cannot
which-function-mode use those to yield nil when there's nothing to
show?

IOW, instead of introducing a new and breaking behavior, why not use
the (quite elaborate and flexible) features we already have?

Am I missing something?





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-01 16:14 ` Eli Zaretskii
@ 2023-06-01 16:45   ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-01 17:37     ` Spencer Baugh
  2023-06-01 18:46     ` Eli Zaretskii
  0 siblings, 2 replies; 16+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-01 16:45 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Spencer Baugh, 63825

Eli Zaretskii <eliz@gnu.org> writes:

> header-line-format supports :eval and :when, so why cannot
> which-function-mode use those to yield nil when there's nothing to
> show?

I thought so as well, but it seems that the header line is displayed
even when the value of `header-line-format` yields nil, if it isn't
plain nil.

So this shows an empty header line:

--8<---------------cut here---------------start------------->8---
(setq-default header-line-format '(:eval nil))
--8<---------------cut here---------------end--------------->8---

(In Emacs master with -Q.)






^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-01 16:45   ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-01 17:37     ` Spencer Baugh
  2023-06-01 18:46     ` Eli Zaretskii
  1 sibling, 0 replies; 16+ messages in thread
From: Spencer Baugh @ 2023-06-01 17:37 UTC (permalink / raw)
  To: Eshel Yaron; +Cc: Eli Zaretskii, 63825

Eshel Yaron <me@eshelyaron.com> writes:
> Eli Zaretskii <eliz@gnu.org> writes:
>> header-line-format supports :eval and :when, so why cannot
>> which-function-mode use those to yield nil when there's nothing to
>> show?
>
> I thought so as well, but it seems that the header line is displayed
> even when the value of `header-line-format` yields nil, if it isn't
> plain nil.
>
> So this shows an empty header line:
>
> (setq-default header-line-format '(:eval nil))
>
> (In Emacs master with -Q.)

Yes, this is what I meant.  Sorry, my example was not chosen carefully.
I should have chosen an example which yielded an actually empty string
when processed by format-mode-line, such as '(:eval nil);
(format-mode-line '(:eval nil)) evaluates to "", which I think should
cause the header-line to not appear.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-01 16:45   ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-01 17:37     ` Spencer Baugh
@ 2023-06-01 18:46     ` Eli Zaretskii
  2023-06-01 20:22       ` Spencer Baugh
  1 sibling, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2023-06-01 18:46 UTC (permalink / raw)
  To: Eshel Yaron; +Cc: sbaugh, 63825

> From: Eshel Yaron <me@eshelyaron.com>
> Cc: Spencer Baugh <sbaugh@janestreet.com>,  63825@debbugs.gnu.org
> Date: Thu, 01 Jun 2023 19:45:39 +0300
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > header-line-format supports :eval and :when, so why cannot
> > which-function-mode use those to yield nil when there's nothing to
> > show?
> 
> I thought so as well, but it seems that the header line is displayed
> even when the value of `header-line-format` yields nil, if it isn't
> plain nil.
> 
> So this shows an empty header line:
> 
> --8<---------------cut here---------------start------------->8---
> (setq-default header-line-format '(:eval nil))
> --8<---------------cut here---------------end--------------->8---
> 
> (In Emacs master with -Q.)

It shouldn't be hard to make this special case behave as you want.
Specifically, if the header-line-format is just a single cons cell,
and the car of that cons cell is either :eval or a symbol, and the
result of evaluation those yields nil, don't display the header line.
(I don't really like the idea of not displaying the mode line under
the same conditions.)

Patches welcome.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-01 18:46     ` Eli Zaretskii
@ 2023-06-01 20:22       ` Spencer Baugh
  2023-06-02  6:19         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-02  6:23         ` Eli Zaretskii
  0 siblings, 2 replies; 16+ messages in thread
From: Spencer Baugh @ 2023-06-01 20:22 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 63825, Eshel Yaron

Eli Zaretskii <eliz@gnu.org> writes:
>> From: Eshel Yaron <me@eshelyaron.com>
>> Cc: Spencer Baugh <sbaugh@janestreet.com>,  63825@debbugs.gnu.org
>> Date: Thu, 01 Jun 2023 19:45:39 +0300
>> 
>> Eli Zaretskii <eliz@gnu.org> writes:
>> 
>> > header-line-format supports :eval and :when, so why cannot
>> > which-function-mode use those to yield nil when there's nothing to
>> > show?
>> 
>> I thought so as well, but it seems that the header line is displayed
>> even when the value of `header-line-format` yields nil, if it isn't
>> plain nil.
>> 
>> So this shows an empty header line:
>> 
>> --8<---------------cut here---------------start------------->8---
>> (setq-default header-line-format '(:eval nil))
>> --8<---------------cut here---------------end--------------->8---
>> 
>> (In Emacs master with -Q.)
>
> It shouldn't be hard to make this special case behave as you want.
> Specifically, if the header-line-format is just a single cons cell,
> and the car of that cons cell is either :eval or a symbol, and the
> result of evaluation those yields nil, don't display the header line.
> (I don't really like the idea of not displaying the mode line under
> the same conditions.)
>
> Patches welcome.

Ok, the easy way to achieve that is to run format-mode-line on the
header-line-format and if it evaluates to "", don't display the header
line.  That also ignores the cases where header-line-format is multiple
cons cells, all of which evaluate to nil, and other such scenarios.  Is
that an acceptable approach to you?





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-01 20:22       ` Spencer Baugh
@ 2023-06-02  6:19         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-02 11:36           ` Eli Zaretskii
  2023-06-02  6:23         ` Eli Zaretskii
  1 sibling, 1 reply; 16+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-02  6:19 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: Eli Zaretskii, 63825

Spencer Baugh <sbaugh@janestreet.com> writes:

> Eli Zaretskii <eliz@gnu.org> writes:
>> Specifically, if the header-line-format is just a single cons cell,
>> and the car of that cons cell is either :eval or a symbol, and the
>> result of evaluation those yields nil, don't display the header line.
>> (I don't really like the idea of not displaying the mode line under
>> the same conditions.)
>>
>> Patches welcome.
>
> Ok, the easy way to achieve that is to run format-mode-line on the
> header-line-format and if it evaluates to "", don't display the header
> line.  That also ignores the cases where header-line-format is multiple
> cons cells, all of which evaluate to nil, and other such scenarios.  Is
> that an acceptable approach to you?

This might be a bit too coarse IMO, because it would make it a lot
harder to create an empty header line.  Namely, setting
`header-line-format` to an empty string would no longer create an empty
header line.

I'm far from fluent in Emacs's internals, but AFAIU from skimming
src/xdisp.c there's another issue which is that Emacs checks whether a
window should have a header line in many circumstances, as it affects
the window's effective dimensions.  So formatting the entire header line
each time Emacs just wants to know whether there is or isn't a header
line might not be ideal in terms of efficiency.

The way I read Eli's above message, it boils down to extending the C
function `window_wants_mode_line` with a couple of special cases.
Something like the following (mildly tested):

diff --git a/src/window.c b/src/window.c
index f4e09f49eae..10bccc6df65 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5471,6 +5471,36 @@ window_wants_mode_line (struct window *w)
 }
 
 
+/**
+ * null_header_line_format:
+ *
+ * Return 1 when header line format F indicates that the header line
+ * should not be displayed at all.
+ *
+ * This is when F is nil, or F is a cons cell and either its car is a
+ * symbol whose value as a variable is nil, or its car is the symbol
+ * ':eval' and its cddr evaluates to nil.
+ */
+static bool
+null_header_line_format (Lisp_Object f)
+{
+  Lisp_Object car;
+
+  if (NILP (f))
+    return 1;
+
+  if (CONSP (f)) {
+    car = XCAR (f);
+    return (SYMBOLP (car)
+	    && ((EQ (car, QCeval)
+		 && NILP (Feval (XCAR (XCDR (f)), Qnil)))
+		|| NILP (find_symbol_value (car))));
+  }
+
+  return 0;
+}
+
+
 /**
  * window_wants_header_line:
  *
@@ -5495,8 +5525,8 @@ window_wants_header_line (struct window *w)
 	  && !MINI_WINDOW_P (w)
 	  && !WINDOW_PSEUDO_P (w)
 	  && !EQ (window_header_line_format, Qnone)
-	  && (!NILP (window_header_line_format)
-	      || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
+	  && (!null_header_line_format (window_header_line_format)
+	      || !null_header_line_format (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
 	  && (WINDOW_PIXEL_HEIGHT (w)
 	      > (window_wants_mode_line (w)
 		 ? 2 * WINDOW_FRAME_LINE_HEIGHT (w)





^ permalink raw reply related	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-01 20:22       ` Spencer Baugh
  2023-06-02  6:19         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-02  6:23         ` Eli Zaretskii
  1 sibling, 0 replies; 16+ messages in thread
From: Eli Zaretskii @ 2023-06-02  6:23 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: 63825, me

> From: Spencer Baugh <sbaugh@janestreet.com>
> Cc: Eshel Yaron <me@eshelyaron.com>,  63825@debbugs.gnu.org
> Date: Thu, 01 Jun 2023 16:22:14 -0400
> 
> >> So this shows an empty header line:
> >> 
> >> --8<---------------cut here---------------start------------->8---
> >> (setq-default header-line-format '(:eval nil))
> >> --8<---------------cut here---------------end--------------->8---
> >> 
> >> (In Emacs master with -Q.)
> >
> > It shouldn't be hard to make this special case behave as you want.
> > Specifically, if the header-line-format is just a single cons cell,
> > and the car of that cons cell is either :eval or a symbol, and the
> > result of evaluation those yields nil, don't display the header line.
> > (I don't really like the idea of not displaying the mode line under
> > the same conditions.)
> >
> > Patches welcome.
> 
> Ok, the easy way to achieve that is to run format-mode-line on the
> header-line-format and if it evaluates to "", don't display the header
> line.  That also ignores the cases where header-line-format is multiple
> cons cells, all of which evaluate to nil, and other such scenarios.  Is
> that an acceptable approach to you?

No, using format-mode-line for displaying the mode line is not a good
idea, for several subtle reason which I won't go into.  If you want to
understand the reasons, look at the code of format-mode-line and how
it affects what display_mode_element does.  In particular, there's no
way to distinguish between the special value of header-line-format we
are discussing and the value that really yields an empty string: the
latter we don't want to change.

Why can't you simply copy some of the code from display_mode_element
that handles the :eval and the cons cell with a symbol cases into
display_mode_line, before it calls display_mode_element, and have the
function return zero in case the result is nil?  Then the callers of
display_mode_line should treat the zero value as an indication that
the mode line was not displayed/produced, and act accordingly.

Alternatively, you could do something special in display_mode_element
when these two forms evaluate to nil and DEPTH is 1, and add some
logic in display_mode_line to handle that.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-02  6:19         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-02 11:36           ` Eli Zaretskii
  2023-06-02 18:53             ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2023-06-02 11:36 UTC (permalink / raw)
  To: Eshel Yaron; +Cc: sbaugh, 63825

> From: Eshel Yaron <me@eshelyaron.com>
> Cc: Eli Zaretskii <eliz@gnu.org>,  63825@debbugs.gnu.org
> Date: Fri, 02 Jun 2023 09:19:17 +0300
> 
> This might be a bit too coarse IMO, because it would make it a lot
> harder to create an empty header line.  Namely, setting
> `header-line-format` to an empty string would no longer create an empty
> header line.

Yes.

> I'm far from fluent in Emacs's internals, but AFAIU from skimming
> src/xdisp.c there's another issue which is that Emacs checks whether a
> window should have a header line in many circumstances, as it affects
> the window's effective dimensions.  So formatting the entire header line
> each time Emacs just wants to know whether there is or isn't a header
> line might not be ideal in terms of efficiency.

Right.

> The way I read Eli's above message, it boils down to extending the C
> function `window_wants_mode_line` with a couple of special cases.
> Something like the following (mildly tested):

Thanks, this is an elegant solution.  A few minor comments:

> +/**
> + * null_header_line_format:
> + *
> + * Return 1 when header line format F indicates that the header line
> + * should not be displayed at all.

We usually say "Return non-zero", not 1.

> + * This is when F is nil, or F is a cons cell and either its car is a
> + * symbol whose value as a variable is nil, or its car is the symbol
> + * ':eval' and its cddr evaluates to nil.
> + */
> +static bool
> +null_header_line_format (Lisp_Object f)

The argument should be called fmt or somesuch.  When I see 'f' in the
C sources, I assume it's a pointe to 'struct frame'.

> +  if (NILP (f))
> +    return 1;
       ^^^^^^^^^
This should say "return true;" instead, since the function is declared
as returning a 'bool'.

> +  if (CONSP (f)) {

This is not our style: we put the opening and closing braces on lines
of their own; see the rest of the code around.

> +    car = XCAR (f);
> +    return (SYMBOLP (car)
> +	    && ((EQ (car, QCeval)
> +		 && NILP (Feval (XCAR (XCDR (f)), Qnil)))
> +		|| NILP (find_symbol_value (car))));

find_symbol_value can return Qunbound, which is non-nil, but this
function should treat it as if it were nil (see the documentation of
mode-line-format).

> +  return 0;

"return false;"

> @@ -5495,8 +5525,8 @@ window_wants_header_line (struct window *w)
>  	  && !MINI_WINDOW_P (w)
>  	  && !WINDOW_PSEUDO_P (w)
>  	  && !EQ (window_header_line_format, Qnone)
> -	  && (!NILP (window_header_line_format)
> -	      || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
> +	  && (!null_header_line_format (window_header_line_format)
> +	      || !null_header_line_format (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))

This line is too long, and should be broken, probably before
header_line_format.

And finally, please accompany the change with a suitable commit log
message, an entry in NEWS, and a change for the ELisp manual.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-02 11:36           ` Eli Zaretskii
@ 2023-06-02 18:53             ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-03  5:44               ` Eli Zaretskii
  0 siblings, 1 reply; 16+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-02 18:53 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: sbaugh, 63825

[-- Attachment #1: Type: text/plain, Size: 911 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> The way I read Eli's above message, it boils down to extending the C
>> function `window_wants_mode_line` with a couple of special cases.
>> Something like the following (mildly tested):

> Thanks, this is an elegant solution.  A few minor comments:


Thanks for reviewing, I'm attaching an updated patch below.

Regarding this comment:

>> +/**
>> + * null_header_line_format:
>> + *
>> + * Return 1 when header line format F indicates that the header line
>> + * should not be displayed at all.

> We usually say "Return non-zero", not 1.

I've changed the wording accordingly, note that some other functions
that return `bool` in src/window.c currently say "Return 1",
e.g. `window_wants_header_line`.

> And finally, please accompany the change with a suitable commit log
> message, an entry in NEWS, and a change for the ELisp manual.

Sure, here's the new patch:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Avoid-header-line-with-some-empty-non-nil-formats.patch --]
[-- Type: text/x-patch, Size: 5426 bytes --]

From 5b231a67ef01ec3b0272967ad9eeecc6b689f030 Mon Sep 17 00:00:00 2001
From: Eshel Yaron <me@eshelyaron.com>
Date: Fri, 2 Jun 2023 20:09:43 +0300
Subject: [PATCH] Avoid header line with some empty non-nil formats

Allow the value of 'header-line-format' to indicate that no header
line should be displayed when it trivially yields 'nil', even if it is
not plain 'nil'.  Previously, any non-nil 'header-line-format'
resulted in a (possibly empty) header line.  This change adds some
flexibility by also taking a non-nil value of 'header-line-format' to
mean that no header line should be displayed if it's a list whose
'car' is a symbol and either that symbol is ':eval' and the second
list element evaluates to 'nil', or the symbol's value as a variable
is 'nil' or void.
(Bug#63825)

* src/window.c (null_header_line_format): New function.
(window_wants_header_line): Use it.

* doc/lispref/modes.texi (Header Line): Update to reflect new
conditions for displaying a window's header line.
(Emulating Mode Line): Don't falsely suggest that if
'format-mode-line' yields the empty string then there is no header
line, as there may be an empty header line instead.

* etc/NEWS: Announce updated treatment of 'header-line-format'.
---
 doc/lispref/modes.texi | 18 ++++++++++++-----
 etc/NEWS               |  8 ++++++++
 src/window.c           | 44 ++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index c2698da6d99..c94ad229250 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -2597,6 +2597,15 @@ Header Lines
 line.
 @end defvar
 
+Emacs displays the header line for a window unless
+@code{header-line-format} is either @code{nil}, or it's a list whose
+@sc{car} is a symbol, and either that symbol is @code{:eval} and the
+second list element evaluates to @code{nil} or the symbol's value as a
+variable is @code{nil} or void.  Note that there are other possible
+values @code{header-line-format} that result in an empty header line
+(for example, @code{""}), but all other values tell Emacs to display a
+header line, whether or not it is empty.
+
 If @code{display-line-numbers-mode} is turned on in a buffer
 (@pxref{Display Custom, display-line-numbers-mode,, emacs, The GNU
 Emacs Manual}), the buffer text is indented on display by the amount
@@ -2707,11 +2716,10 @@ Emulating Mode Line
 (Other faces do not cause redisplay.)
 
 For example, @code{(format-mode-line header-line-format)} returns the
-text that would appear in the selected window's header line (@code{""}
-if it has no header line).  @code{(format-mode-line header-line-format
-'header-line)} returns the same text, with each character
-carrying the face that it will have in the header line itself, and also
-redraws the header line.
+text that would appear in the selected window's header line.
+@code{(format-mode-line header-line-format 'header-line)} returns the
+same text, with each character carrying the face that it will have in
+the header line itself, and also redraws the header line.
 @end defun
 
 @node Imenu
diff --git a/etc/NEWS b/etc/NEWS
index 9529282f047..f09e8972bc6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -451,6 +451,14 @@ hooks named after the feature name, like 'esh-mode-unload-hook'.
 +++
 ** 'copy-tree' now copies records when its optional 2nd argument is non-nil.
 
++++
+** Certain values of 'header-line-format' now inhibit empty header line.
+Emacs now avoids displaying a header line, instead of displaying an
+empty one, when 'header-line-format' is a list whose 'car' is a
+symbol, and either that symbol is ':eval' and the second element of
+the list evaluates to 'nil' or the symbol's value as a variable is
+'nil' or void.
+
 \f
 * Lisp Changes in Emacs 30.1
 
diff --git a/src/window.c b/src/window.c
index f4e09f49eae..bfdf33fc1d6 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5471,6 +5471,45 @@ window_wants_mode_line (struct window *w)
 }
 
 
+/**
+ * null_header_line_format:
+ *
+ * Return non-zero when header line format FMT indicates that the
+ * header line should not be displayed at all.
+ *
+ * This is when FMT is nil, or if FMT is a cons cell and either its
+ * car is a symbol whose value as a variable is nil or void, or its
+ * car is the symbol ':eval' and its cadr evaluates to nil.
+ */
+static bool
+null_header_line_format (Lisp_Object fmt)
+{
+  Lisp_Object car;
+  Lisp_Object val;
+
+  if (NILP (fmt))
+    return true;
+
+  if (CONSP (fmt))
+    {
+      car = XCAR (fmt);
+      if (SYMBOLP (car))
+	{
+	  if (EQ (car, QCeval)
+	      && NILP (Feval (XCAR (XCDR (fmt)), Qnil)))
+	      return true;
+
+	  val = find_symbol_value (car);
+	  return (SYMBOLP (car)
+		  && (EQ (val, Qunbound)
+		      || NILP (val)));
+	}
+    }
+
+  return false;
+}
+
+
 /**
  * window_wants_header_line:
  *
@@ -5495,8 +5534,9 @@ window_wants_header_line (struct window *w)
 	  && !MINI_WINDOW_P (w)
 	  && !WINDOW_PSEUDO_P (w)
 	  && !EQ (window_header_line_format, Qnone)
-	  && (!NILP (window_header_line_format)
-	      || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
+	  && (!null_header_line_format (window_header_line_format)
+	      || !null_header_line_format (BVAR (XBUFFER (WINDOW_BUFFER (w)),
+						 header_line_format)))
 	  && (WINDOW_PIXEL_HEIGHT (w)
 	      > (window_wants_mode_line (w)
 		 ? 2 * WINDOW_FRAME_LINE_HEIGHT (w)
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-02 18:53             ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-03  5:44               ` Eli Zaretskii
  2023-06-03  7:28                 ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2023-06-03  5:44 UTC (permalink / raw)
  To: Eshel Yaron; +Cc: sbaugh, 63825

> From: Eshel Yaron <me@eshelyaron.com>
> Cc: sbaugh@janestreet.com,  63825@debbugs.gnu.org
> Date: Fri, 02 Jun 2023 21:53:45 +0300
> 
> Regarding this comment:
> 
> >> +/**
> >> + * null_header_line_format:
> >> + *
> >> + * Return 1 when header line format F indicates that the header line
> >> + * should not be displayed at all.
> 
> > We usually say "Return non-zero", not 1.
> 
> I've changed the wording accordingly, note that some other functions
> that return `bool` in src/window.c currently say "Return 1",
> e.g. `window_wants_header_line`.

Yes, those are leftovers from when those functions returned an 'int',
not a 'bool', i.e. when we didn't require a C99 compiler.

> Sure, here's the new patch:

Thanks.

>  For example, @code{(format-mode-line header-line-format)} returns the
> -text that would appear in the selected window's header line (@code{""}
> -if it has no header line).  @code{(format-mode-line header-line-format
> -'header-line)} returns the same text, with each character
> -carrying the face that it will have in the header line itself, and also
> -redraws the header line.
> +text that would appear in the selected window's header line.
> +@code{(format-mode-line header-line-format 'header-line)} returns the
> +same text, with each character carrying the face that it will have in
> +the header line itself, and also redraws the header line.

I'm not sure why you removed the part about an empty string.  There's
no change in format-mode-line to justify that, AFAICT, and neither
should there be.

> +  if (CONSP (fmt))
> +    {
> +      car = XCAR (fmt);
> +      if (SYMBOLP (car))
> +	{
> +	  if (EQ (car, QCeval)
> +	      && NILP (Feval (XCAR (XCDR (fmt)), Qnil)))
> +	      return true;

This should use safe__eval (or something similar), not Feval, because
it is called as part of redisplay, where we cannot allow any errors to
throw to top-level.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-03  5:44               ` Eli Zaretskii
@ 2023-06-03  7:28                 ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-04  7:03                   ` Eli Zaretskii
  0 siblings, 1 reply; 16+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-03  7:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: sbaugh, 63825

[-- Attachment #1: Type: text/plain, Size: 1768 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>>  For example, @code{(format-mode-line header-line-format)} returns the
>> -text that would appear in the selected window's header line (@code{""}
>> -if it has no header line).  @code{(format-mode-line header-line-format
>> -'header-line)} returns the same text, with each character
>> -carrying the face that it will have in the header line itself, and also
>> -redraws the header line.
>> +text that would appear in the selected window's header line.
>> +@code{(format-mode-line header-line-format 'header-line)} returns the
>> +same text, with each character carrying the face that it will have in
>> +the header line itself, and also redraws the header line.
>
> I'm not sure why you removed the part about an empty string.  There's
> no change in format-mode-line to justify that, AFAICT, and neither
> should there be.

Indeed, my patch doesn't change `format-mode-line`.  I removed this part
because AFAICT it's wrong: it suggests that if `format-mode-line`
returns the empty string with some argument, then using that argument as
the value of `header-line-format` will result in no header line at all.
But that's not the case (and it wasn't before my patch), because
`(format-mode-line header-line-format)` returning an empty string means
that the header line is either absent or empty, not necessarily absent.

>> +  if (CONSP (fmt))
>> +    {
>> +      car = XCAR (fmt);
>> +      if (SYMBOLP (car))
>> +	{
>> +	  if (EQ (car, QCeval)
>> +	      && NILP (Feval (XCAR (XCDR (fmt)), Qnil)))
>> +	      return true;
>
> This should use safe__eval (or something similar), not Feval, because
> it is called as part of redisplay, where we cannot allow any errors to
> throw to top-level.

Got it, here's an updated patch:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v2-0001-Avoid-header-line-with-some-empty-non-nil-formats.patch --]
[-- Type: text/x-patch, Size: 6995 bytes --]

From bb6004521faefdd8936dafe7a64f24b3525fdaff Mon Sep 17 00:00:00 2001
From: Eshel Yaron <me@eshelyaron.com>
Date: Fri, 2 Jun 2023 20:09:43 +0300
Subject: [PATCH v2] Avoid header line with some empty non-nil formats

Allow the value of 'header-line-format' to indicate that no header
line should be displayed when it trivially yields 'nil', even if it is
not plain 'nil'.  Previously, any non-nil 'header-line-format'
resulted in a (possibly empty) header line.  This change adds some
flexibility by also taking a non-nil value of 'header-line-format' to
mean that no header line should be displayed if it's a list whose
'car' is a symbol and either that symbol is ':eval' and the second
list element evaluates to 'nil', or the symbol's value as a variable
is 'nil' or void.
(Bug#63825)

* src/xdisp.c (safe_eval_inhibit_quit): New function.
(display_mode_element): Use it.
* src/lisp.h (safe_eval_inhibit_quit): Declare it.
* src/window.c (null_header_line_format): New function.
(window_wants_header_line): Use it.

* doc/lispref/modes.texi (Header Line): Update to reflect new
conditions for displaying a window's header line.
(Emulating Mode Line): Don't falsely suggest that if
'format-mode-line' yields the empty string then there is no header
line, as there may be an empty header line instead.

* etc/NEWS: Announce updated treatment of 'header-line-format'.
---
 doc/lispref/modes.texi | 18 ++++++++++++-----
 etc/NEWS               |  8 ++++++++
 src/lisp.h             |  1 +
 src/window.c           | 44 ++++++++++++++++++++++++++++++++++++++++--
 src/xdisp.c            |  8 +++++++-
 5 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index c2698da6d99..c94ad229250 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -2597,6 +2597,15 @@ Header Lines
 line.
 @end defvar
 
+Emacs displays the header line for a window unless
+@code{header-line-format} is either @code{nil}, or it's a list whose
+@sc{car} is a symbol, and either that symbol is @code{:eval} and the
+second list element evaluates to @code{nil} or the symbol's value as a
+variable is @code{nil} or void.  Note that there are other possible
+values @code{header-line-format} that result in an empty header line
+(for example, @code{""}), but all other values tell Emacs to display a
+header line, whether or not it is empty.
+
 If @code{display-line-numbers-mode} is turned on in a buffer
 (@pxref{Display Custom, display-line-numbers-mode,, emacs, The GNU
 Emacs Manual}), the buffer text is indented on display by the amount
@@ -2707,11 +2716,10 @@ Emulating Mode Line
 (Other faces do not cause redisplay.)
 
 For example, @code{(format-mode-line header-line-format)} returns the
-text that would appear in the selected window's header line (@code{""}
-if it has no header line).  @code{(format-mode-line header-line-format
-'header-line)} returns the same text, with each character
-carrying the face that it will have in the header line itself, and also
-redraws the header line.
+text that would appear in the selected window's header line.
+@code{(format-mode-line header-line-format 'header-line)} returns the
+same text, with each character carrying the face that it will have in
+the header line itself, and also redraws the header line.
 @end defun
 
 @node Imenu
diff --git a/etc/NEWS b/etc/NEWS
index 9529282f047..f09e8972bc6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -451,6 +451,14 @@ hooks named after the feature name, like 'esh-mode-unload-hook'.
 +++
 ** 'copy-tree' now copies records when its optional 2nd argument is non-nil.
 
++++
+** Certain values of 'header-line-format' now inhibit empty header line.
+Emacs now avoids displaying a header line, instead of displaying an
+empty one, when 'header-line-format' is a list whose 'car' is a
+symbol, and either that symbol is ':eval' and the second element of
+the list evaluates to 'nil' or the symbol's value as a variable is
+'nil' or void.
+
 \f
 * Lisp Changes in Emacs 30.1
 
diff --git a/src/lisp.h b/src/lisp.h
index 2bfcd1a1983..2978de962d9 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4174,6 +4174,7 @@ verify (FLT_RADIX == 2 || FLT_RADIX == 16);
 extern void syms_of_xdisp (void);
 extern void init_xdisp (void);
 extern Lisp_Object safe_eval (Lisp_Object);
+extern Lisp_Object safe_eval_inhibit_quit (Lisp_Object);
 extern bool pos_visible_p (struct window *, ptrdiff_t, int *,
 			   int *, int *, int *, int *, int *);
 
diff --git a/src/window.c b/src/window.c
index f4e09f49eae..fd9d7cbd9d3 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5471,6 +5471,45 @@ window_wants_mode_line (struct window *w)
 }
 
 
+/**
+ * null_header_line_format:
+ *
+ * Return non-zero when header line format FMT indicates that the
+ * header line should not be displayed at all.
+ *
+ * This is when FMT is nil, or if FMT is a cons cell and either its
+ * car is a symbol whose value as a variable is nil or void, or its
+ * car is the symbol ':eval' and its cadr evaluates to nil.
+ */
+static bool
+null_header_line_format (Lisp_Object fmt)
+{
+  Lisp_Object car;
+  Lisp_Object val;
+
+  if (NILP (fmt))
+    return true;
+
+  if (CONSP (fmt))
+    {
+      car = XCAR (fmt);
+      if (SYMBOLP (car))
+	{
+	  if (EQ (car, QCeval)
+	      && NILP (safe_eval_inhibit_quit (XCAR (XCDR (fmt)))))
+	      return true;
+
+	  val = find_symbol_value (car);
+	  return (SYMBOLP (car)
+		  && (EQ (val, Qunbound)
+		      || NILP (val)));
+	}
+    }
+
+  return false;
+}
+
+
 /**
  * window_wants_header_line:
  *
@@ -5495,8 +5534,9 @@ window_wants_header_line (struct window *w)
 	  && !MINI_WINDOW_P (w)
 	  && !WINDOW_PSEUDO_P (w)
 	  && !EQ (window_header_line_format, Qnone)
-	  && (!NILP (window_header_line_format)
-	      || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
+	  && (!null_header_line_format (window_header_line_format)
+	      || !null_header_line_format (BVAR (XBUFFER (WINDOW_BUFFER (w)),
+						 header_line_format)))
 	  && (WINDOW_PIXEL_HEIGHT (w)
 	      > (window_wants_mode_line (w)
 		 ? 2 * WINDOW_FRAME_LINE_HEIGHT (w)
diff --git a/src/xdisp.c b/src/xdisp.c
index a6ec966ea3c..fc7de149d2b 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3074,6 +3074,12 @@ safe__eval (bool inhibit_quit, Lisp_Object sexpr)
   return safe__call1 (inhibit_quit, Qeval, sexpr);
 }
 
+Lisp_Object
+safe_eval_inhibit_quit (Lisp_Object sexpr)
+{
+  return safe__eval (true, sexpr);
+}
+
 /* Call function FN with two arguments ARG1 and ARG2.
    Return the result, or nil if something went wrong.  */
 
@@ -27408,7 +27414,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
 	    if (CONSP (XCDR (elt)))
 	      {
 		Lisp_Object spec;
-		spec = safe__eval (true, XCAR (XCDR (elt)));
+		spec = safe_eval_inhibit_quit (XCAR (XCDR (elt)));
 		/* The :eval form could delete the frame stored in the
 		   iterator, which will cause a crash if we try to
 		   access faces and other fields (e.g., FRAME_KBOARD)
-- 
2.40.1


[-- Attachment #3: Type: text/plain, Size: 18 bytes --]


-- 
Best,

Eshel

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-03  7:28                 ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-04  7:03                   ` Eli Zaretskii
  2023-06-04 16:45                     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2023-06-04  7:03 UTC (permalink / raw)
  To: Eshel Yaron; +Cc: sbaugh, 63825

> From: Eshel Yaron <me@eshelyaron.com>
> Cc: sbaugh@janestreet.com,  63825@debbugs.gnu.org
> Date: Sat, 03 Jun 2023 10:28:20 +0300
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> >>  For example, @code{(format-mode-line header-line-format)} returns the
> >> -text that would appear in the selected window's header line (@code{""}
> >> -if it has no header line).  @code{(format-mode-line header-line-format
> >> -'header-line)} returns the same text, with each character
> >> -carrying the face that it will have in the header line itself, and also
> >> -redraws the header line.
> >> +text that would appear in the selected window's header line.
> >> +@code{(format-mode-line header-line-format 'header-line)} returns the
> >> +same text, with each character carrying the face that it will have in
> >> +the header line itself, and also redraws the header line.
> >
> > I'm not sure why you removed the part about an empty string.  There's
> > no change in format-mode-line to justify that, AFAICT, and neither
> > should there be.
> 
> Indeed, my patch doesn't change `format-mode-line`.  I removed this part
> because AFAICT it's wrong: it suggests that if `format-mode-line`
> returns the empty string with some argument, then using that argument as
> the value of `header-line-format` will result in no header line at all.
> But that's not the case (and it wasn't before my patch), because
> `(format-mode-line header-line-format)` returning an empty string means
> that the header line is either absent or empty, not necessarily absent.

This is not what the text wants to convey.  It wants to say that if a
window has no header-line, i.e. header-line-format is nil,
format-mode-line returns an empty string.  This is true, before and
after your changes.

> >> +  if (CONSP (fmt))
> >> +    {
> >> +      car = XCAR (fmt);
> >> +      if (SYMBOLP (car))
> >> +	{
> >> +	  if (EQ (car, QCeval)
> >> +	      && NILP (Feval (XCAR (XCDR (fmt)), Qnil)))
> >> +	      return true;
> >
> > This should use safe__eval (or something similar), not Feval, because
> > it is called as part of redisplay, where we cannot allow any errors to
> > throw to top-level.
> 
> Got it, here's an updated patch:

Thanks.

> +  if (CONSP (fmt))
> +    {
> +      car = XCAR (fmt);
> +      if (SYMBOLP (car))
> +	{
> +	  if (EQ (car, QCeval)
> +	      && NILP (safe_eval_inhibit_quit (XCAR (XCDR (fmt)))))
> +	      return true;

The indentation of "return true;" seems incorrect here.  Are you using
a non-default setup of C indentation levels?

> @@ -5495,8 +5534,9 @@ window_wants_header_line (struct window *w)
>  	  && !MINI_WINDOW_P (w)
>  	  && !WINDOW_PSEUDO_P (w)
>  	  && !EQ (window_header_line_format, Qnone)
> -	  && (!NILP (window_header_line_format)
> -	      || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
> +	  && (!null_header_line_format (window_header_line_format)
> +	      || !null_header_line_format (BVAR (XBUFFER (WINDOW_BUFFER (w)),
> +						 header_line_format)))
>  	  && (WINDOW_PIXEL_HEIGHT (w)
>  	      > (window_wants_mode_line (w)
>  		 ? 2 * WINDOW_FRAME_LINE_HEIGHT (w)

One more issue (sorry I didn't notice it before): the :eval form can
potentially delete the window's frame.  See this part of
display_mode_element:

	    if (CONSP (XCDR (elt)))
	      {
		Lisp_Object spec;
		spec = safe__eval (true, XCAR (XCDR (elt)));
		/* The :eval form could delete the frame stored in the
		   iterator, which will cause a crash if we try to
		   access faces and other fields (e.g., FRAME_KBOARD)
		   on that frame.  This is a nonsensical thing to do,
		   and signaling an error from redisplay might be
		   dangerous, but we cannot continue with an invalid frame.  */
		if (!FRAME_LIVE_P (it->f))
		  signal_error (":eval deleted the frame being displayed", elt);
		n += display_mode_element (it, depth, field_width - n,
					   precision - n, spec, props,
					   risky);
	      }

So I think we need to add to null_header_line_format a test for the
window's frame to be live, to be on the safe side.  For that to work,
the function should accept an additional argument: a pointer to the
frame of the window whose header-line we are considering.

> @@ -27408,7 +27414,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
>  	    if (CONSP (XCDR (elt)))
>  	      {
>  		Lisp_Object spec;
> -		spec = safe__eval (true, XCAR (XCDR (elt)));
> +		spec = safe_eval_inhibit_quit (XCAR (XCDR (elt)));
>  		/* The :eval form could delete the frame stored in the
>  		   iterator, which will cause a crash if we try to
>  		   access faces and other fields (e.g., FRAME_KBOARD)

I see no reason to make this replacement.  Calling a static function
lets the compiler optimize more aggressively than calling an
non-static one.

Thanks.





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-04  7:03                   ` Eli Zaretskii
@ 2023-06-04 16:45                     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-06-06 12:18                       ` Eli Zaretskii
  0 siblings, 1 reply; 16+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-04 16:45 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: sbaugh, 63825

[-- Attachment #1: Type: text/plain, Size: 4184 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Eshel Yaron <me@eshelyaron.com>
>>
>> Indeed, my patch doesn't change `format-mode-line`.  I removed this part
>> because AFAICT it's wrong: it suggests that if `format-mode-line`
>> returns the empty string with some argument, then using that argument as
>> the value of `header-line-format` will result in no header line at all.
>> But that's not the case (and it wasn't before my patch), because
>> `(format-mode-line header-line-format)` returning an empty string means
>> that the header line is either absent or empty, not necessarily absent.
>
> This is not what the text wants to convey.  It wants to say that if a
> window has no header-line, i.e. header-line-format is nil,
> format-mode-line returns an empty string.  This is true, before and
> after your changes.
>

Okay, I'm removing this change.  FTR I still find the remark that I
proposed removing slightly misleading.  Another option would be changing
the current "@code{""} if it has no header line" to "@code{""} if it has
an empty or no header line" instead of removing it.

>> +  if (CONSP (fmt))
>> +    {
>> +      car = XCAR (fmt);
>> +      if (SYMBOLP (car))
>> +	{
>> +	  if (EQ (car, QCeval)
>> +	      && NILP (safe_eval_inhibit_quit (XCAR (XCDR (fmt)))))
>> +	      return true;

> The indentation of "return true;" seems incorrect here.

Fixed.  Thanks for spotting it.

> Are you using a non-default setup of C indentation levels?

I don't think so, this one just slipped by I guess.

>> @@ -5495,8 +5534,9 @@ window_wants_header_line (struct window *w)
>>        && !MINI_WINDOW_P (w)
>>        && !WINDOW_PSEUDO_P (w)
>>        && !EQ (window_header_line_format, Qnone)
>> -	  && (!NILP (window_header_line_format)
>> -	      || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
>> +	  && (!null_header_line_format (window_header_line_format)
>> +	      || !null_header_line_format (BVAR (XBUFFER (WINDOW_BUFFER (w)),
>> +						 header_line_format)))
>>        && (WINDOW_PIXEL_HEIGHT (w)
>>            > (window_wants_mode_line (w)
>>               ? 2 * WINDOW_FRAME_LINE_HEIGHT (w)
>
> One more issue (sorry I didn't notice it before): the :eval form can
> potentially delete the window's frame.  See this part of
> display_mode_element:
>
>           if (CONSP (XCDR (elt)))
>             {
>               Lisp_Object spec;
>               spec = safe__eval (true, XCAR (XCDR (elt)));
>               /* The :eval form could delete the frame stored in the
>                  iterator, which will cause a crash if we try to
>                  access faces and other fields (e.g., FRAME_KBOARD)
>                  on that frame.  This is a nonsensical thing to do,
>                  and signaling an error from redisplay might be
>                  dangerous, but we cannot continue with an invalid frame.  */
>               if (!FRAME_LIVE_P (it->f))
>                 signal_error (":eval deleted the frame being displayed", elt);
>               n += display_mode_element (it, depth, field_width - n,
>                                          precision - n, spec, props,
>                                          risky);
>             }
>
> So I think we need to add to null_header_line_format a test for the
> window's frame to be live, to be on the safe side.  For that to work,
> the function should accept an additional argument: a pointer to the
> frame of the window whose header-line we are considering.
>

I see, done.

>> @@ -27408,7 +27414,7 @@ display_mode_element (struct it *it, int depth, int field_width, int precision,
>>          if (CONSP (XCDR (elt)))
>>            {
>>              Lisp_Object spec;
>> -		spec = safe__eval (true, XCAR (XCDR (elt)));
>> +		spec = safe_eval_inhibit_quit (XCAR (XCDR (elt)));
>>              /* The :eval form could delete the frame stored in the
>>                 iterator, which will cause a crash if we try to
>>                 access faces and other fields (e.g., FRAME_KBOARD)
>
> I see no reason to make this replacement.  Calling a static function
> lets the compiler optimize more aggressively than calling an
> non-static one.

Alright.  Here's an updated patch:


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v3-0001-Avoid-header-line-with-some-empty-non-nil-formats.patch --]
[-- Type: text/x-patch, Size: 5931 bytes --]

From 98d0722d1e6e5d9d5b877f7df7e8ccd624ca9bd5 Mon Sep 17 00:00:00 2001
From: Eshel Yaron <eshelyaron@dazzs-mbp.home>
Date: Sun, 4 Jun 2023 19:41:20 +0300
Subject: [PATCH v3] Avoid header line with some empty non-nil formats

Allow the value of 'header-line-format' to indicate that no header
line should be displayed when it trivially yields 'nil', even if it is
not plain 'nil'.  Previously, any non-nil 'header-line-format'
resulted in a (possibly empty) header line.  This change adds some
flexibility by also taking a non-nil value of 'header-line-format' to
mean that no header line should be displayed if it's a list whose
'car' is a symbol and either that symbol is ':eval' and the second
list element evaluates to 'nil', or the symbol's value as a variable
is 'nil' or void.
(Bug#63825)

* src/xdisp.c (safe_eval_inhibit_quit): New function.
* src/lisp.h (safe_eval_inhibit_quit): Declare it.
* src/window.c (null_header_line_format): New function.
(window_wants_header_line): Use it.

* doc/lispref/modes.texi (Header Line): Update to reflect new
conditions for displaying a window's header line.

* etc/NEWS: Announce updated treatment of 'header-line-format'.
---
 doc/lispref/modes.texi |  9 ++++++++
 etc/NEWS               |  8 +++++++
 src/lisp.h             |  1 +
 src/window.c           | 50 ++++++++++++++++++++++++++++++++++++++++--
 src/xdisp.c            |  6 +++++
 5 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index c2698da6d99..d2a05fe29e4 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -2597,6 +2597,15 @@ Header Lines
 line.
 @end defvar
 
+Emacs displays the header line for a window unless
+@code{header-line-format} is either @code{nil}, or it's a list whose
+@sc{car} is a symbol, and either that symbol is @code{:eval} and the
+second list element evaluates to @code{nil} or the symbol's value as a
+variable is @code{nil} or void.  Note that there are other possible
+values @code{header-line-format} that result in an empty header line
+(for example, @code{""}), but all other values tell Emacs to display a
+header line, whether or not it is empty.
+
 If @code{display-line-numbers-mode} is turned on in a buffer
 (@pxref{Display Custom, display-line-numbers-mode,, emacs, The GNU
 Emacs Manual}), the buffer text is indented on display by the amount
diff --git a/etc/NEWS b/etc/NEWS
index 9529282f047..f09e8972bc6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -451,6 +451,14 @@ hooks named after the feature name, like 'esh-mode-unload-hook'.
 +++
 ** 'copy-tree' now copies records when its optional 2nd argument is non-nil.
 
++++
+** Certain values of 'header-line-format' now inhibit empty header line.
+Emacs now avoids displaying a header line, instead of displaying an
+empty one, when 'header-line-format' is a list whose 'car' is a
+symbol, and either that symbol is ':eval' and the second element of
+the list evaluates to 'nil' or the symbol's value as a variable is
+'nil' or void.
+
 \f
 * Lisp Changes in Emacs 30.1
 
diff --git a/src/lisp.h b/src/lisp.h
index 2bfcd1a1983..2978de962d9 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4174,6 +4174,7 @@ verify (FLT_RADIX == 2 || FLT_RADIX == 16);
 extern void syms_of_xdisp (void);
 extern void init_xdisp (void);
 extern Lisp_Object safe_eval (Lisp_Object);
+extern Lisp_Object safe_eval_inhibit_quit (Lisp_Object);
 extern bool pos_visible_p (struct window *, ptrdiff_t, int *,
 			   int *, int *, int *, int *, int *);
 
diff --git a/src/window.c b/src/window.c
index f4e09f49eae..9429679061e 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5471,6 +5471,48 @@ window_wants_mode_line (struct window *w)
 }
 
 
+/**
+ * null_header_line_format:
+ *
+ * Return non-zero when header line format FMT indicates that the
+ * header line should not be displayed at all.
+ *
+ * This is when FMT is nil, or if FMT is a cons cell and either its
+ * car is a symbol whose value as a variable is nil or void, or its
+ * car is the symbol ':eval' and its cadr evaluates to nil.
+ */
+static bool
+null_header_line_format (Lisp_Object fmt, struct frame * f)
+{
+  Lisp_Object car;
+  Lisp_Object val;
+
+  if (NILP (fmt))
+    return true;
+
+  if (CONSP (fmt))
+    {
+      car = XCAR (fmt);
+      if (SYMBOLP (car))
+	{
+	  if (EQ (car, QCeval))
+	    {
+	      val = safe_eval_inhibit_quit (XCAR (XCDR (fmt)));
+	      if (!FRAME_LIVE_P (f))
+		signal_error (":eval deleted the frame being displayed", fmt);
+	      return NILP (val);
+	    }
+	  val = find_symbol_value (car);
+	  return (SYMBOLP (car)
+		  && (EQ (val, Qunbound)
+		      || NILP (val)));
+	}
+    }
+
+  return false;
+}
+
+
 /**
  * window_wants_header_line:
  *
@@ -5491,12 +5533,16 @@ window_wants_header_line (struct window *w)
   Lisp_Object window_header_line_format =
     window_parameter (w, Qheader_line_format);
 
+  struct frame * f = WINDOW_XFRAME(w);
+
   return (WINDOW_LEAF_P (w)
 	  && !MINI_WINDOW_P (w)
 	  && !WINDOW_PSEUDO_P (w)
 	  && !EQ (window_header_line_format, Qnone)
-	  && (!NILP (window_header_line_format)
-	      || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
+	  && (!null_header_line_format (window_header_line_format, f)
+	      || !null_header_line_format (BVAR (XBUFFER (WINDOW_BUFFER (w)),
+						 header_line_format),
+					   f))
 	  && (WINDOW_PIXEL_HEIGHT (w)
 	      > (window_wants_mode_line (w)
 		 ? 2 * WINDOW_FRAME_LINE_HEIGHT (w)
diff --git a/src/xdisp.c b/src/xdisp.c
index a6ec966ea3c..5e25857322f 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3074,6 +3074,12 @@ safe__eval (bool inhibit_quit, Lisp_Object sexpr)
   return safe__call1 (inhibit_quit, Qeval, sexpr);
 }
 
+Lisp_Object
+safe_eval_inhibit_quit (Lisp_Object sexpr)
+{
+  return safe__eval (true, sexpr);
+}
+
 /* Call function FN with two arguments ARG1 and ARG2.
    Return the result, or nil if something went wrong.  */
 
-- 
2.39.2 (Apple Git-143)


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-04 16:45                     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-06-06 12:18                       ` Eli Zaretskii
  2023-06-06 12:28                         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 16+ messages in thread
From: Eli Zaretskii @ 2023-06-06 12:18 UTC (permalink / raw)
  To: Eshel Yaron; +Cc: sbaugh, 63825-done

> From: Eshel Yaron <me@eshelyaron.com>
> Cc: sbaugh@janestreet.com,  63825@debbugs.gnu.org
> Date: Sun, 04 Jun 2023 19:45:23 +0300
> 
> Alright.  Here's an updated patch:

Thanks, installed on the master branch, and closing the bug.

One nit: we don't leave whitespace between '*' and the identifier in
the likes of

   struct frame *f ...

(I fixed this for you this time.)





^ permalink raw reply	[flat|nested] 16+ messages in thread

* bug#63825: 29.0.90; The header line should be hidden when empty
  2023-06-06 12:18                       ` Eli Zaretskii
@ 2023-06-06 12:28                         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 16+ messages in thread
From: Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-06-06 12:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: sbaugh, 63825-done

Eli Zaretskii <eliz@gnu.org> writes:

> One nit: we don't leave whitespace between '*' and the identifier in
> the likes of
>
>    struct frame *f ...
>
> (I fixed this for you this time.)

Got it, thanks.





^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2023-06-06 12:28 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-01 13:37 bug#63825: 29.0.90; The header line should be hidden when empty Spencer Baugh
2023-06-01 16:14 ` Eli Zaretskii
2023-06-01 16:45   ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-01 17:37     ` Spencer Baugh
2023-06-01 18:46     ` Eli Zaretskii
2023-06-01 20:22       ` Spencer Baugh
2023-06-02  6:19         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-02 11:36           ` Eli Zaretskii
2023-06-02 18:53             ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-03  5:44               ` Eli Zaretskii
2023-06-03  7:28                 ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-04  7:03                   ` Eli Zaretskii
2023-06-04 16:45                     ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-06 12:18                       ` Eli Zaretskii
2023-06-06 12:28                         ` Eshel Yaron via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-06-02  6:23         ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).