all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* bug#70840: 29.3; ERC 5.5.0.29.1: erc-kill-buffer-on-part kills server buffer
@ 2024-05-08 20:37 Thibaut Meyer via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2024-05-14  0:55 ` J.P.
       [not found] ` <8734ql9ppd.fsf@neverwas.me>
  0 siblings, 2 replies; 5+ messages in thread
From: Thibaut Meyer via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-05-08 20:37 UTC (permalink / raw)
  To: 70840; +Cc: emacs-erc

Hello,
reminiscent of
https://lists.gnu.org/archive/html/emacs-devel/2009-06/msg00064.html,
when `erc-kill-buffer-on-part` is set to t, parting a channel
by killing its buffer, makes erc want to kill the server's buffer. When
parting by issuing the "/part" command, everything is fine.

I reckon that in `define-erc-response-handler` in the erc-backend.el
file, since we kill the buffer ourselves, (erc-get-buffer chnl proc)
returns the server buffer instead of the channel buffer that has already
been killed. So then it tries to kill that instead, which is not wanted.

To reproduce:
- set erc-kill-buffer-on-part to t
- kill a channel buffer
- notice emacs trying to kill the corresponding server buffer (it should
not happen directly thanks to the "buffer has running process. Kill it?"
confirmation though)

Thanks for the great piece of software,
Thibaut


In GNU Emacs 29.3 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.41,
cairo version 1.18.0)
Windowing system distributor 'The X.Org Foundation', version 11.0.12101013
System Description: Arch Linux

Configured using:
 'configure --sysconfdir=/etc --prefix=/usr --libexecdir=/usr/lib
 --with-tree-sitter --localstatedir=/var --with-cairo
 --disable-build-details --with-harfbuzz --with-libsystemd
 --with-modules --with-x-toolkit=gtk3 'CFLAGS=-march=x86-64
 -mtune=generic -O2 -pipe -fno-plt -fexceptions -Wp,-D_FORTIFY_SOURCE=2
 -Wformat -Werror=format-security -fstack-clash-protection
 -fcf-protection -g
 -ffile-prefix-map=/build/emacs/src=/usr/src/debug/emacs -flto=auto'
 'LDFLAGS=-Wl,-O1 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro
 -Wl,-z,now -Wl,-z,pack-relative-relocs -flto=auto''

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG
JSON LCMS2 LIBOTF LIBSYSTEMD LIBXML2 M17N_FLT MODULES NOTIFY INOTIFY
PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS
TREE_SITTER WEBP X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB

Important settings:
  value of $LC_MONETARY: fr_FR.utf8
  value of $LC_NUMERIC: fr_FR.utf8
  value of $LC_TIME: fr_FR.utf8
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: ERC

Minor modes in effect:
  erc-notifications-mode: t
  erc-hl-nicks-mode: t
  erc-list-mode: t
  erc-menu-mode: t
  erc-autojoin-mode: t
  erc-ring-mode: t
  erc-pcomplete-mode: t
  erc-track-mode: t
  erc-track-minor-mode: t
  erc-match-mode: t
  erc-button-mode: t
  erc-fill-mode: t
  erc-stamp-mode: t
  erc-netsplit-mode: t
  erc-spelling-mode: t
  erc-sasl-mode: t
  erc-services-mode: t
  erc-irccontrols-mode: t
  erc-noncommands-mode: t
  erc-move-to-prompt-mode: t
  erc-readonly-mode: t
  erc-networks-mode: t
  global-git-commit-mode: t
  server-mode: t
  windmove-mode: t
  flyspell-mode: t
  TeX-PDF-mode: t
  TeX-source-correlate-mode: t
  diredfl-global-mode: t
  mu4e-modeline-mode: t
  global-company-mode: t
  company-mode: t
  shell-dirtrack-mode: t
  global-display-fill-column-indicator-mode: t
  display-fill-column-indicator-mode: t
  mlscroll-mode: t
  auto-dim-other-buffers-mode: t
  global-hl-todo-mode: t
  global-hl-line-mode: t
  persp-mode: t
  which-key-mode: t
  marginalia-mode: t
  savehist-mode: t
  vertico-multiform-mode: t
  vertico-mode: t
  auto-insert-mode: t
  global-whitespace-mode: t
  delete-selection-mode: t
  global-subword-mode: t
  subword-mode: t
  override-global-mode: t
  global-auto-revert-mode: t
  straight-use-package-mode: t
  straight-package-neutering-mode: t
  global-eldoc-mode: t
  show-paren-mode: t
  mouse-wheel-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  window-divider-mode: t
  column-number-mode: t
  line-number-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  abbrev-mode: t

Load-path shadows:
/home/thibaut/.emacs.d/straight/build/cmake-mode/cmake-mode hides /usr/share/emacs/site-lisp/cmake-mode
/home/thibaut/.emacs.d/straight/build/external-completion/external-completion hides /usr/share/emacs/29.3/lisp/external-completion
/home/thibaut/.emacs.d/straight/build/jsonrpc/jsonrpc hides /usr/share/emacs/29.3/lisp/jsonrpc
/home/thibaut/.emacs.d/straight/build/transient/transient hides /usr/share/emacs/29.3/lisp/transient
/home/thibaut/.emacs.d/straight/build/use-package/use-package-delight hides /usr/share/emacs/29.3/lisp/use-package/use-package-delight
/home/thibaut/.emacs.d/straight/build/use-package/use-package-diminish hides /usr/share/emacs/29.3/lisp/use-package/use-package-diminish
/home/thibaut/.emacs.d/straight/build/use-package/use-package-core hides /usr/share/emacs/29.3/lisp/use-package/use-package-core
/home/thibaut/.emacs.d/straight/build/use-package/use-package-ensure hides /usr/share/emacs/29.3/lisp/use-package/use-package-ensure
/home/thibaut/.emacs.d/straight/build/use-package/use-package hides /usr/share/emacs/29.3/lisp/use-package/use-package
/home/thibaut/.emacs.d/straight/build/use-package/use-package-lint hides /usr/share/emacs/29.3/lisp/use-package/use-package-lint
/home/thibaut/.emacs.d/straight/build/use-package/use-package-bind-key hides /usr/share/emacs/29.3/lisp/use-package/use-package-bind-key
/home/thibaut/.emacs.d/straight/build/use-package/use-package-jump hides /usr/share/emacs/29.3/lisp/use-package/use-package-jump
/home/thibaut/.emacs.d/straight/build/bind-key/bind-key hides /usr/share/emacs/29.3/lisp/use-package/bind-key
/home/thibaut/.emacs.d/straight/build/project/project hides /usr/share/emacs/29.3/lisp/progmodes/project
/home/thibaut/.emacs.d/straight/build/eglot/eglot hides /usr/share/emacs/29.3/lisp/progmodes/eglot
/home/thibaut/.emacs.d/straight/build/flymake/flymake hides /usr/share/emacs/29.3/lisp/progmodes/flymake
/home/thibaut/.emacs.d/straight/build/org/ob-python hides /usr/share/emacs/29.3/lisp/org/ob-python
/home/thibaut/.emacs.d/straight/build/org/org-protocol hides /usr/share/emacs/29.3/lisp/org/org-protocol
/home/thibaut/.emacs.d/straight/build/org/org-archive hides /usr/share/emacs/29.3/lisp/org/org-archive
/home/thibaut/.emacs.d/straight/build/org/org-duration hides /usr/share/emacs/29.3/lisp/org/org-duration
/home/thibaut/.emacs.d/straight/build/org/org-capture hides /usr/share/emacs/29.3/lisp/org/org-capture
/home/thibaut/.emacs.d/straight/build/org/ol-bbdb hides /usr/share/emacs/29.3/lisp/org/ol-bbdb
/home/thibaut/.emacs.d/straight/build/org/oc-basic hides /usr/share/emacs/29.3/lisp/org/oc-basic
/home/thibaut/.emacs.d/straight/build/org/ob-makefile hides /usr/share/emacs/29.3/lisp/org/ob-makefile
/home/thibaut/.emacs.d/straight/build/org/ob-forth hides /usr/share/emacs/29.3/lisp/org/ob-forth
/home/thibaut/.emacs.d/straight/build/org/ob-comint hides /usr/share/emacs/29.3/lisp/org/ob-comint
/home/thibaut/.emacs.d/straight/build/org/ob-ref hides /usr/share/emacs/29.3/lisp/org/ob-ref
/home/thibaut/.emacs.d/straight/build/org/ob-eshell hides /usr/share/emacs/29.3/lisp/org/ob-eshell
/home/thibaut/.emacs.d/straight/build/org/ob-table hides /usr/share/emacs/29.3/lisp/org/ob-table
/home/thibaut/.emacs.d/straight/build/org/ob-latex hides /usr/share/emacs/29.3/lisp/org/ob-latex
/home/thibaut/.emacs.d/straight/build/org/ox-publish hides /usr/share/emacs/29.3/lisp/org/ox-publish
/home/thibaut/.emacs.d/straight/build/org/org-datetree hides /usr/share/emacs/29.3/lisp/org/org-datetree
/home/thibaut/.emacs.d/straight/build/org/org-clock hides /usr/share/emacs/29.3/lisp/org/org-clock
/home/thibaut/.emacs.d/straight/build/org/ob-ocaml hides /usr/share/emacs/29.3/lisp/org/ob-ocaml
/home/thibaut/.emacs.d/straight/build/org/ol-eww hides /usr/share/emacs/29.3/lisp/org/ol-eww
/home/thibaut/.emacs.d/straight/build/org/ob-sql hides /usr/share/emacs/29.3/lisp/org/ob-sql
/home/thibaut/.emacs.d/straight/build/org/org-tempo hides /usr/share/emacs/29.3/lisp/org/org-tempo
/home/thibaut/.emacs.d/straight/build/org/ob-processing hides /usr/share/emacs/29.3/lisp/org/ob-processing
/home/thibaut/.emacs.d/straight/build/org/ox-latex hides /usr/share/emacs/29.3/lisp/org/ox-latex
/home/thibaut/.emacs.d/straight/build/org/ox-icalendar hides /usr/share/emacs/29.3/lisp/org/ox-icalendar
/home/thibaut/.emacs.d/straight/build/org/org-cycle hides /usr/share/emacs/29.3/lisp/org/org-cycle
/home/thibaut/.emacs.d/straight/build/org/ol-gnus hides /usr/share/emacs/29.3/lisp/org/ol-gnus
/home/thibaut/.emacs.d/straight/build/org/ob-fortran hides /usr/share/emacs/29.3/lisp/org/ob-fortran
/home/thibaut/.emacs.d/straight/build/org/ob-dot hides /usr/share/emacs/29.3/lisp/org/ob-dot
/home/thibaut/.emacs.d/straight/build/org/org-attach hides /usr/share/emacs/29.3/lisp/org/org-attach
/home/thibaut/.emacs.d/straight/build/org/ob-R hides /usr/share/emacs/29.3/lisp/org/ob-R
/home/thibaut/.emacs.d/straight/build/org/ob-emacs-lisp hides /usr/share/emacs/29.3/lisp/org/ob-emacs-lisp
/home/thibaut/.emacs.d/straight/build/org/ob-shell hides /usr/share/emacs/29.3/lisp/org/ob-shell
/home/thibaut/.emacs.d/straight/build/org/org-table hides /usr/share/emacs/29.3/lisp/org/org-table
/home/thibaut/.emacs.d/straight/build/org/org-colview hides /usr/share/emacs/29.3/lisp/org/org-colview
/home/thibaut/.emacs.d/straight/build/org/org-id hides /usr/share/emacs/29.3/lisp/org/org-id
/home/thibaut/.emacs.d/straight/build/org/ob-sed hides /usr/share/emacs/29.3/lisp/org/ob-sed
/home/thibaut/.emacs.d/straight/build/org/ob-eval hides /usr/share/emacs/29.3/lisp/org/ob-eval
/home/thibaut/.emacs.d/straight/build/org/org-agenda hides /usr/share/emacs/29.3/lisp/org/org-agenda
/home/thibaut/.emacs.d/straight/build/org/ol hides /usr/share/emacs/29.3/lisp/org/ol
/home/thibaut/.emacs.d/straight/build/org/org-entities hides /usr/share/emacs/29.3/lisp/org/org-entities
/home/thibaut/.emacs.d/straight/build/org/ob-sass hides /usr/share/emacs/29.3/lisp/org/ob-sass
/home/thibaut/.emacs.d/straight/build/org/ox-beamer hides /usr/share/emacs/29.3/lisp/org/ox-beamer
/home/thibaut/.emacs.d/straight/build/org/org-refile hides /usr/share/emacs/29.3/lisp/org/org-refile
/home/thibaut/.emacs.d/straight/build/org/ob-matlab hides /usr/share/emacs/29.3/lisp/org/ob-matlab
/home/thibaut/.emacs.d/straight/build/org/oc-bibtex hides /usr/share/emacs/29.3/lisp/org/oc-bibtex
/home/thibaut/.emacs.d/straight/build/org/ob-js hides /usr/share/emacs/29.3/lisp/org/ob-js
/home/thibaut/.emacs.d/straight/build/org/ol-mhe hides /usr/share/emacs/29.3/lisp/org/ol-mhe
/home/thibaut/.emacs.d/straight/build/org/ox-odt hides /usr/share/emacs/29.3/lisp/org/ox-odt
/home/thibaut/.emacs.d/straight/build/org/ob-sqlite hides /usr/share/emacs/29.3/lisp/org/ob-sqlite
/home/thibaut/.emacs.d/straight/build/org/ob-awk hides /usr/share/emacs/29.3/lisp/org/ob-awk
/home/thibaut/.emacs.d/straight/build/org/ol-w3m hides /usr/share/emacs/29.3/lisp/org/ol-w3m
/home/thibaut/.emacs.d/straight/build/org/org-loaddefs hides /usr/share/emacs/29.3/lisp/org/org-loaddefs
/home/thibaut/.emacs.d/straight/build/org/ob hides /usr/share/emacs/29.3/lisp/org/ob
/home/thibaut/.emacs.d/straight/build/org/ol-info hides /usr/share/emacs/29.3/lisp/org/ol-info
/home/thibaut/.emacs.d/straight/build/org/ox-html hides /usr/share/emacs/29.3/lisp/org/ox-html
/home/thibaut/.emacs.d/straight/build/org/ox hides /usr/share/emacs/29.3/lisp/org/ox
/home/thibaut/.emacs.d/straight/build/org/org-habit hides /usr/share/emacs/29.3/lisp/org/org-habit
/home/thibaut/.emacs.d/straight/build/org/ob-groovy hides /usr/share/emacs/29.3/lisp/org/ob-groovy
/home/thibaut/.emacs.d/straight/build/org/ox-koma-letter hides /usr/share/emacs/29.3/lisp/org/ox-koma-letter
/home/thibaut/.emacs.d/straight/build/org/org-pcomplete hides /usr/share/emacs/29.3/lisp/org/org-pcomplete
/home/thibaut/.emacs.d/straight/build/org/org-faces hides /usr/share/emacs/29.3/lisp/org/org-faces
/home/thibaut/.emacs.d/straight/build/org/ob-julia hides /usr/share/emacs/29.3/lisp/org/ob-julia
/home/thibaut/.emacs.d/straight/build/org/ol-doi hides /usr/share/emacs/29.3/lisp/org/ol-doi
/home/thibaut/.emacs.d/straight/build/org/ob-org hides /usr/share/emacs/29.3/lisp/org/ob-org
/home/thibaut/.emacs.d/straight/build/org/ol-irc hides /usr/share/emacs/29.3/lisp/org/ol-irc
/home/thibaut/.emacs.d/straight/build/org/org-footnote hides /usr/share/emacs/29.3/lisp/org/org-footnote
/home/thibaut/.emacs.d/straight/build/org/ob-scheme hides /usr/share/emacs/29.3/lisp/org/ob-scheme
/home/thibaut/.emacs.d/straight/build/org/ox-org hides /usr/share/emacs/29.3/lisp/org/ox-org
/home/thibaut/.emacs.d/straight/build/org/org-timer hides /usr/share/emacs/29.3/lisp/org/org-timer
/home/thibaut/.emacs.d/straight/build/org/ol-eshell hides /usr/share/emacs/29.3/lisp/org/ol-eshell
/home/thibaut/.emacs.d/straight/build/org/ob-haskell hides /usr/share/emacs/29.3/lisp/org/ob-haskell
/home/thibaut/.emacs.d/straight/build/org/ol-rmail hides /usr/share/emacs/29.3/lisp/org/ol-rmail
/home/thibaut/.emacs.d/straight/build/org/ob-java hides /usr/share/emacs/29.3/lisp/org/ob-java
/home/thibaut/.emacs.d/straight/build/org/ox-md hides /usr/share/emacs/29.3/lisp/org/ox-md
/home/thibaut/.emacs.d/straight/build/org/oc-biblatex hides /usr/share/emacs/29.3/lisp/org/oc-biblatex
/home/thibaut/.emacs.d/straight/build/org/org-goto hides /usr/share/emacs/29.3/lisp/org/org-goto
/home/thibaut/.emacs.d/straight/build/org/org-fold hides /usr/share/emacs/29.3/lisp/org/org-fold
/home/thibaut/.emacs.d/straight/build/org/org-indent hides /usr/share/emacs/29.3/lisp/org/org-indent
/home/thibaut/.emacs.d/straight/build/org/ob-tangle hides /usr/share/emacs/29.3/lisp/org/ob-tangle
/home/thibaut/.emacs.d/straight/build/org/ob-gnuplot hides /usr/share/emacs/29.3/lisp/org/ob-gnuplot
/home/thibaut/.emacs.d/straight/build/org/org-feed hides /usr/share/emacs/29.3/lisp/org/org-feed
/home/thibaut/.emacs.d/straight/build/org/ob-exp hides /usr/share/emacs/29.3/lisp/org/ob-exp
/home/thibaut/.emacs.d/straight/build/org/ob-lilypond hides /usr/share/emacs/29.3/lisp/org/ob-lilypond
/home/thibaut/.emacs.d/straight/build/org/ob-lua hides /usr/share/emacs/29.3/lisp/org/ob-lua
/home/thibaut/.emacs.d/straight/build/org/ob-clojure hides /usr/share/emacs/29.3/lisp/org/ob-clojure
/home/thibaut/.emacs.d/straight/build/org/ol-man hides /usr/share/emacs/29.3/lisp/org/ol-man
/home/thibaut/.emacs.d/straight/build/org/ob-ruby hides /usr/share/emacs/29.3/lisp/org/ob-ruby
/home/thibaut/.emacs.d/straight/build/org/org-persist hides /usr/share/emacs/29.3/lisp/org/org-persist
/home/thibaut/.emacs.d/straight/build/org/oc-csl hides /usr/share/emacs/29.3/lisp/org/oc-csl
/home/thibaut/.emacs.d/straight/build/org/org-element hides /usr/share/emacs/29.3/lisp/org/org-element
/home/thibaut/.emacs.d/straight/build/org/ob-ditaa hides /usr/share/emacs/29.3/lisp/org/ob-ditaa
/home/thibaut/.emacs.d/straight/build/org/ox-texinfo hides /usr/share/emacs/29.3/lisp/org/ox-texinfo
/home/thibaut/.emacs.d/straight/build/org/org-inlinetask hides /usr/share/emacs/29.3/lisp/org/org-inlinetask
/home/thibaut/.emacs.d/straight/build/org/org-compat hides /usr/share/emacs/29.3/lisp/org/org-compat
/home/thibaut/.emacs.d/straight/build/org/org-macro hides /usr/share/emacs/29.3/lisp/org/org-macro
/home/thibaut/.emacs.d/straight/build/org/ob-calc hides /usr/share/emacs/29.3/lisp/org/ob-calc
/home/thibaut/.emacs.d/straight/build/org/ob-lisp hides /usr/share/emacs/29.3/lisp/org/ob-lisp
/home/thibaut/.emacs.d/straight/build/org/ob-octave hides /usr/share/emacs/29.3/lisp/org/ob-octave
/home/thibaut/.emacs.d/straight/build/org/ox-ascii hides /usr/share/emacs/29.3/lisp/org/ox-ascii
/home/thibaut/.emacs.d/straight/build/org/ob-core hides /usr/share/emacs/29.3/lisp/org/ob-core
/home/thibaut/.emacs.d/straight/build/org/ol-bibtex hides /usr/share/emacs/29.3/lisp/org/ol-bibtex
/home/thibaut/.emacs.d/straight/build/org/oc-natbib hides /usr/share/emacs/29.3/lisp/org/oc-natbib
/home/thibaut/.emacs.d/straight/build/org/org-keys hides /usr/share/emacs/29.3/lisp/org/org-keys
/home/thibaut/.emacs.d/straight/build/org/org-version hides /usr/share/emacs/29.3/lisp/org/org-version
/home/thibaut/.emacs.d/straight/build/org/org-src hides /usr/share/emacs/29.3/lisp/org/org-src
/home/thibaut/.emacs.d/straight/build/org/org-plot hides /usr/share/emacs/29.3/lisp/org/org-plot
/home/thibaut/.emacs.d/straight/build/org/ob-css hides /usr/share/emacs/29.3/lisp/org/ob-css
/home/thibaut/.emacs.d/straight/build/org/ox-man hides /usr/share/emacs/29.3/lisp/org/ox-man
/home/thibaut/.emacs.d/straight/build/org/ol-docview hides /usr/share/emacs/29.3/lisp/org/ol-docview
/home/thibaut/.emacs.d/straight/build/org/org-crypt hides /usr/share/emacs/29.3/lisp/org/org-crypt
/home/thibaut/.emacs.d/straight/build/org/org-fold-core hides /usr/share/emacs/29.3/lisp/org/org-fold-core
/home/thibaut/.emacs.d/straight/build/org/org-mouse hides /usr/share/emacs/29.3/lisp/org/org-mouse
/home/thibaut/.emacs.d/straight/build/org/org-lint hides /usr/share/emacs/29.3/lisp/org/org-lint
/home/thibaut/.emacs.d/straight/build/org/org-mobile hides /usr/share/emacs/29.3/lisp/org/org-mobile
/home/thibaut/.emacs.d/straight/build/org/ob-maxima hides /usr/share/emacs/29.3/lisp/org/ob-maxima
/home/thibaut/.emacs.d/straight/build/org/ob-lob hides /usr/share/emacs/29.3/lisp/org/ob-lob
/home/thibaut/.emacs.d/straight/build/org/ob-C hides /usr/share/emacs/29.3/lisp/org/ob-C
/home/thibaut/.emacs.d/straight/build/org/org-ctags hides /usr/share/emacs/29.3/lisp/org/org-ctags
/home/thibaut/.emacs.d/straight/build/org/org hides /usr/share/emacs/29.3/lisp/org/org
/home/thibaut/.emacs.d/straight/build/org/ob-perl hides /usr/share/emacs/29.3/lisp/org/ob-perl
/home/thibaut/.emacs.d/straight/build/org/oc hides /usr/share/emacs/29.3/lisp/org/oc
/home/thibaut/.emacs.d/straight/build/org/org-attach-git hides /usr/share/emacs/29.3/lisp/org/org-attach-git
/home/thibaut/.emacs.d/straight/build/org/org-macs hides /usr/share/emacs/29.3/lisp/org/org-macs
/home/thibaut/.emacs.d/straight/build/org/org-num hides /usr/share/emacs/29.3/lisp/org/org-num
/home/thibaut/.emacs.d/straight/build/org/org-list hides /usr/share/emacs/29.3/lisp/org/org-list
/home/thibaut/.emacs.d/straight/build/org/ob-screen hides /usr/share/emacs/29.3/lisp/org/ob-screen
/home/thibaut/.emacs.d/straight/build/org/ob-plantuml hides /usr/share/emacs/29.3/lisp/org/ob-plantuml
/home/thibaut/.emacs.d/straight/build/eldoc/eldoc hides /usr/share/emacs/29.3/lisp/emacs-lisp/eldoc
/home/thibaut/.emacs.d/straight/build/let-alist/let-alist hides /usr/share/emacs/29.3/lisp/emacs-lisp/let-alist
/home/thibaut/.emacs.d/straight/build/seq/seq hides /usr/share/emacs/29.3/lisp/emacs-lisp/seq

Features:
(shadow emacsbug expand-region yaml-mode-expansions
subword-mode-expansions text-mode-expansions cc-mode-expansions
the-org-mode-expansions ruby-mode-expansions
python-el-fgallina-expansions latex-mode-expansions js-mode-expansions
html-mode-expansions css-mode-expansions er-basic-expansions
expand-region-core expand-region-custom erc-status-sidebar url-http
url-auth url-gw erc-desktop-notifications erc-hl-nicks erc-list erc-menu
erc-join erc-ring erc-pcomplete erc-track erc-match erc-button erc-fill
erc-stamp erc-netsplit erc-spelling erc-sasl
erc-sasl-ecdsa-nist256p-challenge erc-sasl-scram-sha-512
erc-sasl-scram-sha-256 erc-sasl-scram-sha-1 erc-sasl-external
erc-sasl-plain sasl-scram-sha256 sasl-scram-rfc sasl-scram-sha-1 rfc2104
hex-util sasl sasl-anonymous sasl-login sasl-plain erc-services
erc-goodies erc erc-backend erc-networks erc-common erc-compat
erc-loaddefs consult-imenu org-datetree org-archive org-capture
yaml-mode ruby-mode windresize cl-print message-view-patch helpful
cc-langs trace edebug debug backtrace info-look elisp-refs
message-view-patch-autoloads loaddefs-gen lisp-mnt consult-register
multi-vterm vterm term disp-table ehelp vterm-module term/xterm xterm
goto-addr tabify man help-fns radix-tree magit-subtree magit-gitignore
magit-ediff ediff ediff-merg ediff-mult ediff-wind ediff-diff ediff-help
ediff-init ediff-util magit-patch markdown-mode mhtml-mode css-mode js
c-ts-common sgml-mode vc bug-reference magit-extras magit-bookmark
magit-submodule 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 magit-diff
smerge-mode diff git-commit log-edit pcvs-util add-log magit-core
magit-autorevert magit-margin magit-transient magit-process magit-mode
transient magit-git magit-base magit-section password-store-otp pass f
dash s password-store with-editor server epa-file network-stream nsm
mailalias qp consult pulse shr-color color sort smiley gnus-cite
mm-archive mail-extr textsec uni-scripts idna-mapping ucs-normalize
uni-confusable textsec-check reftex-parse windmove gdscript-mode
gdscript-ts-mode gdscript-eglot gdscript-hydra gdscript-godot
gdscript-project gdscript-history gdscript-comint gdscript-debug bindat
gdscript-format gdscript-comint-gdformat gdscript-completion
gdscript-fill-paragraph gdscript-imenu gdscript-indent-and-nav
gdscript-rx gdscript-utils gdscript-syntax gdscript-keywords
gdscript-docs gdscript-customization dired-aux dired-x pdf-sync
tramp-cache time-stamp tramp-sh tramp tramp-loaddefs trampver
tramp-integration files-x tramp-compat reftex-dcr reftex-auc reftex
reftex-loaddefs reftex-vars flyspell ispell preview tex-mode font-latex
latexenc latex latex-flymake flymake warnings tex-ispell tex-style tex
crm texmathp vc-git diff-mode vc-dispatcher org-indent org-pdftools
pdf-occur ibuf-ext ibuffer ibuffer-loaddefs pdf-isearch let-alist
pdf-annot tablist tablist-filter semantic/wisent/comp semantic/wisent
semantic/wisent/wisent semantic/util-modes semantic/util semantic
semantic/tag semantic/lex semantic/fw mode-local cedet facemenu pdf-misc
imenu org-noter org-noter-djvu org-noter-nov org-noter-pdf pdf-tools
package url-handlers compile cus-edit cus-load pdf-view pdf-cache
pdf-info tq pdf-util pdf-macs org-noter-core image-file image-converter
oc-basic org-habit ol-eww eww url-queue mm-url ol-rmail ol-mhe ol-irc
ol-info ol-gnus nnselect ol-docview doc-view jka-compr image-mode exif
ol-bibtex bibtex ol-bbdb ol-w3m ol-doi org-link-doi rainbow-delimiters
display-line-numbers vertico-directory orderless cursor-sensor
erc-hl-nicks-autoloads khardel-autoloads gnuplot-autoloads
pass-autoloads password-store-otp-autoloads password-store-autoloads
dired-narrow-autoloads dired-hacks-utils-autoloads diredfl
diredfl-autoloads multi-vterm-autoloads vterm-autoloads mu4e mu4e-org
mu4e-notification notifications mu4e-main mu4e-view gnus-art mm-uu
mml2015 mm-view mml-smime smime gnutls dig gnus-sum gnus-group gnus-undo
gnus-start gnus-dbus dbus gnus-cloud nnimap nnmail mail-source utf7 nnoo
parse-time iso8601 gnus-spec gnus-int gnus-range gnus-win gnus nnheader
range wid-edit mu4e-headers mu4e-compose mu4e-draft mu4e-actions
smtpmail mu4e-search mu4e-lists mu4e-bookmarks mu4e-mark mu4e-message
shr pixel-fill kinsoku url-file svg xml dom browse-url flow-fill
mule-util mu4e-contacts mu4e-update mu4e-folders mu4e-context
mu4e-query-items mu4e-server mu4e-modeline mu4e-vars mu4e-helpers
mu4e-config mu4e-window bookmark pp message sendmail yank-media puny
dired dired-loaddefs rfc822 mml mml-sec epa derived epg rfc6068
epg-config gnus-util text-property-search mm-decode mm-bodies mm-encode
mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr
mailabbrev mail-utils gmm-utils mailheader mu4e-obsolete
markdown-mode-autoloads csv-mode-autoloads consult-bibtex-autoloads
bibtex-completion-autoloads biblio-autoloads biblio-core-autoloads
parsebib-autoloads auctex-autoloads tex-site gdscript-mode-autoloads
web-mode-autoloads rainbow-delimiters-autoloads haskell-mode-autoloads
yaml-mode-autoloads devdocs-autoloads company-oddmuse company-keywords
company-etags etags fileloop xref company-gtags company-dabbrev-code
company-dabbrev company-files company-clang company-capf company-cmake
company-semantic company-template company-bbdb company company-autoloads
eglot-autoloads external-completion-autoloads flymake-autoloads
project-autoloads eldoc-autoloads jsonrpc-autoloads
dockerfile-mode-autoloads nhexl-mode-autoloads cmake-mode-autoloads
magit-autoloads magit-section-autoloads git-commit-autoloads
with-editor-autoloads transient-autoloads ffap ob-mermaid
ob-mermaid-autoloads ox-rss-autoloads org-pdftools-autoloads
org-noter-autoloads pdf-tools-autoloads let-alist-autoloads
tablist-autoloads ob-gnuplot ob-restclient restclient url url-proxy
url-privacy url-expand url-methods url-history url-cookie
generate-lisp-file url-domsuf url-util mailcap ob-shell shell ob-org
ob-C cc-mode cc-fonts cc-guess cc-menus cc-cmds cc-styles cc-align
cc-engine cc-vars cc-defs ob-python python project ob-latex
ob-restclient-autoloads restclient-autoloads ox-odt rng-loc rng-uri
rng-parse rng-match rng-dt rng-util rng-pttrn nxml-parse nxml-ns
nxml-enc xmltok nxml-util ox-latex ox-icalendar ox-html table ox-ascii
ox-publish ox htmlize-autoloads org-attach org-agenda org-element
org-persist xdg org-id org-element-ast inline avl-tree generator
org-refile org ob ob-tangle ob-ref ob-lob ob-table ob-exp org-macro
org-src sh-script smie treesit executable ob-comint org-pcomplete
pcomplete comint ansi-osc ansi-color org-list org-footnote org-faces
org-entities time-date noutline outline icons ob-emacs-lisp ob-core
ob-eval org-cycle org-table org-keys oc org-loaddefs find-func cal-menu
calendar cal-loaddefs ol org-fold org-fold-core org-compat org-version
org-macs format-spec display-fill-column-indicator mlscroll
mlscroll-autoloads auto-dim-other-buffers face-remap
auto-dim-other-buffers-autoloads doom-nord-theme pcase doom-themes
doom-themes-base doom-themes-autoloads hl-todo hl-todo-autoloads hl-line
noccur-autoloads multiple-cursors-autoloads yasnippet-snippets-autoloads
yasnippet-autoloads perspective thingatpt rx ido perspective-autoloads
helpful-autoloads elisp-refs-autoloads f-autoloads s-autoloads
dash-autoloads which-key which-key-autoloads use-package-diminish
marginalia marginalia-autoloads consult-autoloads use-package-ensure
orderless-autoloads savehist vertico-multiform vertico compat
vertico-autoloads compat-autoloads seq-autoloads windresize-autoloads
ace-window avy ring ace-window-autoloads avy-autoloads advice tempo
autoinsert whitespace expand-region-autoloads delsel hi-lock
drag-stuff-autoloads use-package-bind-key cap-words superword subword
edmacro kmacro bind-key easy-mmode autorevert filenotify
auth-source-pass url-parse url-vars auth-source eieio eieio-core
password-cache json map byte-opt exec-path-from-shell
exec-path-from-shell-autoloads finder-inf diminish diminish-autoloads
use-package-core use-package-autoloads info bind-key-autoloads
straight-autoloads cl-seq cl-extra help-mode straight subr-x cl-macs gv
cl-loaddefs cl-lib bytecomp byte-compile 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 lcms2
dynamic-setting system-font-setting font-render-setting cairo
move-toolbar gtk x-toolkit xinput2 x multi-tty make-network-process
emacs)

Memory information:
((conses 16 1838825 385858)
 (symbols 48 90878 0)
 (strings 32 364408 83387)
 (string-bytes 1 18474482)
 (vectors 16 168749)
 (vector-slots 8 3101587 335458)
 (floats 8 10719 2795)
 (intervals 56 117893 6593)
 (buffers 984 188))





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

* bug#70840: 29.3; ERC 5.5.0.29.1: erc-kill-buffer-on-part kills server buffer
  2024-05-08 20:37 bug#70840: 29.3; ERC 5.5.0.29.1: erc-kill-buffer-on-part kills server buffer Thibaut Meyer via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2024-05-14  0:55 ` J.P.
       [not found] ` <8734ql9ppd.fsf@neverwas.me>
  1 sibling, 0 replies; 5+ messages in thread
From: J.P. @ 2024-05-14  0:55 UTC (permalink / raw)
  To: Thibaut Meyer; +Cc: emacs-erc, 70840

Hi Thibaut,

Thibaut Meyer writes:

> Hello,
> reminiscent of
> https://lists.gnu.org/archive/html/emacs-devel/2009-06/msg00064.html,
> when `erc-kill-buffer-on-part` is set to t, parting a channel
> by killing its buffer, makes erc want to kill the server's buffer. When
> parting by issuing the "/part" command, everything is fine.
>
> I reckon that in `define-erc-response-handler` in the erc-backend.el
> file, since we kill the buffer ourselves, (erc-get-buffer chnl proc)
> returns the server buffer instead of the channel buffer that has already
> been killed. So then it tries to kill that instead, which is not wanted.

I believe calling `erc-get-buffer' with a nonexistent target returns
nil, which has a similar effect to what you describe. For example, it
causes `erc-display-message' to fall back on routing its output to the
server buffer. Likewise, in terms of user bookkeeping, the calls to
`erc-remove-channel-users' and `erc-remove-channel-member' are
effectively suppressed by `buffer' being nil. This is fine because the
parted buffer has already been killed, so its `erc-channel-users' table
no longer exists, and the buffer has already been removed from the
`buffers' slot of the user's `erc-server-users' entry via

  kill-buffer-hook
  -> erc-kill-buffer-function
   -> erc-remove-channel-users
    -> erc-remove-channel-user
     -> erc-remove-server-user

> To reproduce:
> - set erc-kill-buffer-on-part to t
> - kill a channel buffer
> - notice emacs trying to kill the corresponding server buffer (it should
> not happen directly thanks to the "buffer has running process. Kill it?"
> confirmation though)

Yes, I can confirm this to be the case. Thanks.

So, without thinking about this too seriously, I'm guessing the main
challenge to overcome when fixing this will likely be `erc-part-hook'
and whether to gate it behind the parted buffer being non-nil. Since the
corner case of it being called with a nil buffer has been around
forever, some users may already account for the possibility. Others who
don't may have code that simply doesn't care and yet still needs to run
whenever an incoming (self-issued) PART response arrives. However, since
this is a clear bug, we're justified in changing the behavior. The
question is whether improving it for new users will cause more harm
overall.

If we do elect to only run the hook in the response handler when the
parted buffer still exists, we may want to compensate by running it
elsewhere in the code path triggered by the killing of a channel buffer.
One way to do this would be via a new function running just before
`erc-kill-channel' on `erc-kill-channel-hook'. We'd run `erc-part-hook'
there, in the server buffer, passing it the still-live target buffer
that's slated to be killed.

Such an addition would require us checking how `erc-kill-channel-hook'
is used in erc-log.el and erc-status-sidebar.el, etc., and confirming
that running `erc-part-hook' in this fashion (within another hook) won't
cause any problems. It's probably also worth doing the same with popular
third-party packages and configs. We'd of course also have to announce
the change in etc/ERC-NEWS.

One approach to cutting down on any associated churn would be to add an
escape hatch, such as an "internal" compatibility switch in the form of
a global variable, like an `erc--run-part-hook-with-nil-buffer-p' or
similar. Basically, we'd condition both hook sites on its value. For
example, in `erc-server-PART', we'd have something like

  (when (or buffer erc--run-part-hook-with-nil-buffer-p)
    (run-hook-with-args 'erc-part-hook buffer)) 

And in the new `erc-kill-channel-hook' member, we'd have

  (unless erc--run-part-hook-with-nil-buffer-p
    (let ((buffer (current-buffer)))
      (erc-with-server-buffer
        (run-hook-with-args 'erc-part-hook buffer))))

This would grant a temporary reprieve to users transitioning to the
latest version. They could just set the variable to put off dealing with
it immediately. BTW, if going this route, the doc string for the hook
should probably mention the second call site and possibly the existence
of an escape hatch.

There may well be other issues here I've not yet considered, so if you
can think of any, please share. Also, if you're up for taking this on
(not necessarily in the way I've described), please feel free to send a
patch. The same goes for anyone else out there. I can definitely help
with the leg work and test coverage if that makes things easier.
Otherwise, I may not be able to get to this in time for the next release
(not that there's any rush).

Thanks,
J.P.






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

* bug#70840: 29.3; ERC 5.5.0.29.1: erc-kill-buffer-on-part kills server buffer
       [not found] ` <8734ql9ppd.fsf@neverwas.me>
@ 2024-05-15 13:22   ` J.P.
       [not found]   ` <87seyj6wgh.fsf@neverwas.me>
  1 sibling, 0 replies; 5+ messages in thread
From: J.P. @ 2024-05-15 13:22 UTC (permalink / raw)
  To: Thibaut Meyer; +Cc: emacs-erc, 70840

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

"J.P." <jp@neverwas.me> writes:

> Such an addition would require us checking how `erc-kill-channel-hook'
> is used in erc-log.el and erc-status-sidebar.el, etc., and confirming
> that running `erc-part-hook' in this fashion (within another hook) won't
> cause any problems.

I've checked `erc-log', and it indeed requires a tweak in order to
prevent a double save. The use case in `erc-status-sidebar' is that the
module wants `erc-status-sidebar-refresh' to run when parting. Luckily,
it doesn't care about the current buffer, so I'm somewhat confident that
it's safe to run whenever the user kills a live channel buffer.

> It's probably also worth doing the same with popular third-party
> packages and configs.

I've found a couple packages that operate in the affected areas. The
first one, sauron, uses `erc-server-PART-functions' instead of
`erc-part-hook', so that should be safe. The second, ZNC.el, adds advice
around `erc-kill-channel', inhibiting it when its own option is non-nil.
This too should be fine, since it also conditionally suppresses our
running `erc-part-hook'.

> There may well be other issues here I've not yet considered, so if you
> can think of any, please share. Also, if you're up for taking this on
> (not necessarily in the way I've described), please feel free to send a
> patch. The same goes for anyone else out there. I can definitely help
> with the leg work and test coverage if that makes things easier.
> Otherwise, I may not be able to get to this in time for the next release
> (not that there's any rush).

I've gone ahead with a provisional patch (attached) that incorporates
the points raised so far. Anyone interested, please take a look.

Thanks.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-5.6-Don-t-kill-server-buffer-with-erc-kill-buffer-on.patch --]
[-- Type: text/x-patch, Size: 13569 bytes --]

From 98d16ec15baeb4803014033de6b1c1d3a488ad87 Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@neverwas.me>
Date: Tue, 14 May 2024 21:09:55 -0700
Subject: [PATCH] [5.6] Don't kill server buffer with erc-kill-buffer-on-part

* etc/ERC-NEWS: Mention running `erc-part-hook' on
`erc-kill-channel-hook'.
* lisp/erc/erc-backend.el (erc-server-PART): When buffer doesn't
exist, only run hook when `erc--run-part-hook-with-nil-buffer-p' is
non-nil.  Bind that same variable to t when killing the buffer.
* lisp/erc/erc-log.el (erc-conditional-save-buffer): Don't save logs
when killing the channel buffer because this module already subscribes
to `erc-kill-channel-hook'.
* lisp/erc/erc.el (erc-part-hook): Redo doc string.
(erc--run-part-hook-with-nil-buffer-p): New variable, an escape hatch
to regain pre ERC 5.6 behavior regarding nil buffer arguments passed
to `erc-part-hook' members.
(erc-kill-channel-hook): Use new name for `erc-kill-channel'.
(erc--inhibit-part-channel-on-kill-p): New variable.
(erc-kill-channel, erc-part-channel-on-kill): Rename former to latter.
Run `erc-part-hook' when compat switch is nil.
* test/lisp/erc/erc-scenarios-base-kill-on-part.el: New file.
---
 etc/ERC-NEWS                                  |  10 ++
 lisp/erc/erc-backend.el                       |  13 +-
 lisp/erc/erc-log.el                           |   5 +-
 lisp/erc/erc.el                               |  36 +++--
 .../erc/erc-scenarios-base-kill-on-part.el    | 132 ++++++++++++++++++
 5 files changed, 183 insertions(+), 13 deletions(-)
 create mode 100644 test/lisp/erc/erc-scenarios-base-kill-on-part.el

diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index b66ea6a7a02..9d5a26595be 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -648,6 +648,16 @@ release lacks a similar solution for detecting "joinedness" directly,
 but users can turn to 'xor'-ing 'erc-default-target' and 'erc-target'
 as a makeshift kludge.
 
+*** The function 'erc-kill-channel' may run the hook 'erc-part-hook'.
+Previously, when a user killed a channel buffer, 'erc-part-hook' would
+run in the response handler upon receipt of the corresponding 'PART'
+response, meaning hook members would receive a nil channel-buffer
+argument.  ERC now runs this hook immediately when a user kills a
+channel, just before sending the 'PART' command to the server.  Those
+disrupted by this change should see the definition of 'erc-part-hook'
+for a temporary escape hatch.  Also, for clarity, the function
+'erc-kill-channel' has been renamed 'erc-part-channel-on-kill'.
+
 *** Channel-mode handling has become stricter and more predictable.
 ERC has always processed channel modes using "standardized" letters
 and popular status prefixes.  Starting with this release, ERC will
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index ab419d2b018..7e8e597da46 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -1883,12 +1883,17 @@ erc--server-determine-join-display-context
          (buffer (erc-get-buffer chnl proc)))
     (pcase-let ((`(,nick ,login ,host)
                  (erc-parse-user (erc-response.sender parsed))))
+      ;; When `buffer' is nil, `erc-remove-channel-member',
+      ;; `erc-remove-channel-users', and `erc-part-hook', don't run or
+      ;; do nothing, and the message is printed in the server buffer.
       (erc-remove-channel-member buffer nick)
       (erc-display-message parsed 'notice buffer
                            'PART ?n nick ?u login
                            ?h host ?c chnl ?r (or reason ""))
       (when (string= nick (erc-current-nick))
-        (run-hook-with-args 'erc-part-hook buffer)
+        (defvar erc--run-part-hook-with-nil-buffer-p)
+        (when (or buffer erc--run-part-hook-with-nil-buffer-p)
+          (run-hook-with-args 'erc-part-hook buffer))
         (erc-with-buffer
             (buffer)
           (erc-remove-channel-users))
@@ -1896,8 +1901,10 @@ erc--server-determine-join-display-context
           (erc-delete-default-channel chnl buffer))
         (erc-update-mode-line buffer)
         (defvar erc-kill-buffer-on-part)
-        (when erc-kill-buffer-on-part
-          (kill-buffer buffer))))))
+        (when (and erc-kill-buffer-on-part buffer)
+          (defvar erc--inhibit-part-channel-on-kill-p)
+          (let ((erc--inhibit-part-channel-on-kill-p t))
+            (kill-buffer buffer)))))))
 
 (define-erc-response-handler (PING)
   "Handle ping messages." nil
diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el
index d5c56bcc2b3..f0bd1b45e7c 100644
--- a/lisp/erc/erc-log.el
+++ b/lisp/erc/erc-log.el
@@ -290,7 +290,10 @@ erc-save-query-buffers
 
 (defun erc-conditional-save-buffer (buffer)
   "Save Query BUFFER if `erc-save-queries-on-quit' is t."
-  (when erc-save-buffer-on-part
+  (when (and erc-save-buffer-on-part
+             ;; Don't run this from `erc-part-channel-on-kill' because
+             ;; `erc-save-buffer-in-logs' aready has it covered.
+             (not erc--inhibit-part-channel-on-kill-p))
     (erc-save-buffer-in-logs buffer)))
 
 (defun erc-conditional-save-queries (process)
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index c92fd42322a..a1c94288e8d 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -470,13 +470,23 @@ erc-quit-hook
 
 (defcustom erc-part-hook nil
   "Hook run when processing a PART message directed at our nick.
-
-The hook receives one argument, the current BUFFER.
-See also `erc-server-QUIT-functions', `erc-quit-hook' and
-`erc-disconnected-hook'."
+Called in the server buffer with one argument: the BUFFER being parted.
+Also runs via `erc-part-channel-on-kill' on `erc-kill-channel-hook' if
+killing BUFFER initiated the \"PART\".  Note that beginning with ERC
+5.6, this hook doesn't run upon receiving a \"PART\" from the server if
+BUFFER has already been killed.  See code near this option's definition
+for a possible escape hatch."
   :group 'erc-hooks
   :type 'hook)
 
+(defvar erc--run-part-hook-with-nil-buffer-p nil
+  "When non-nil, allow running `erc-part-hook' with a nil buffer argument.
+Moreover, forgo running the hook before sending a \"PART\" when the user
+kills a channel buffer.  This compat-oriented escape hatch exists for
+third-party code that expects to run unconditionally in the default
+response handler `erc-server-PART' when ERC receives a self-directed
+\"PART\" from the server.")
+
 (defcustom erc-kick-hook nil
   "Hook run when processing a KICK message directed at our nick.
 
@@ -9598,7 +9608,7 @@ erc-kill-server-hook
   :type 'hook)
 
 (defcustom erc-kill-channel-hook
-  '(erc-kill-channel
+  '(erc-part-channel-on-kill
     erc-networks-shrink-ids-and-buffer-names
     erc-networks-rename-surviving-target-buffer)
   "Invoked whenever a channel-buffer is killed via `kill-buffer'."
@@ -9659,10 +9669,18 @@ erc-kill-server
     (setq erc-server-quitting t)
     (erc-server-send (format "QUIT :%s" (funcall erc-quit-reason nil)))))
 
-(defun erc-kill-channel ()
-  "Sends a PART command to the server when the channel buffer is killed.
-This function should be on `erc-kill-channel-hook'."
-  (when (erc-server-process-alive)
+(defvar erc--inhibit-part-channel-on-kill-p nil)
+(define-obsolete-function-alias 'erc-kill-channel #'erc-part-channel-on-kill
+  "30.1")
+(defun erc-part-channel-on-kill ()
+  "Run `erc-part-hook' and send a \"PART\" when killing a channel buffer."
+  (when (and (erc-server-process-alive)
+             (not erc--inhibit-part-channel-on-kill-p))
+    (unless erc--run-part-hook-with-nil-buffer-p
+      (let ((buffer (current-buffer))
+            (erc--inhibit-part-channel-on-kill-p t))
+        (erc-with-server-buffer
+          (run-hook-with-args 'erc-part-hook buffer))))
     (let ((tgt (erc-default-target)))
       (if tgt
          (erc-server-send (format "PART %s :%s" tgt
diff --git a/test/lisp/erc/erc-scenarios-base-kill-on-part.el b/test/lisp/erc/erc-scenarios-base-kill-on-part.el
new file mode 100644
index 00000000000..109cf27b01a
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-kill-on-part.el
@@ -0,0 +1,132 @@
+;;; erc-scenarios-base-kill-on-part.el --- killing buffers on part -*- lexical-binding: t -*-
+
+;; Copyright (C) 2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-scenarios-common)))
+
+;; Assert channel buffer is killed when `erc-kill-buffer-on-part' is
+;; enabled and a user issues a /part.
+(ert-deftest erc-scenarios-base-kill-on-part--enabled ()
+  :tags '(:expensive-test)
+  (should-not erc-kill-buffer-on-part)
+
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/reuse-buffers/channel")
+       (erc-server-flood-penalty 0.1)
+       (dumb-server (erc-d-run "localhost" t 'foonet))
+       (port (process-contact dumb-server :service))
+       (erc-kill-buffer-on-part t)
+       (calls nil)
+       (erc-part-hook (lambda (b) (push (buffer-name b) calls)))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to foonet")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "This server is in debug mode")))
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#chan"))
+      (funcall expect 10 "<alice> bob: Whilst I can shake")
+      (erc-scenarios-common-say "/part"))
+
+    (erc-d-t-wait-for 20 (null (get-buffer "#chan")))
+    (should (equal calls '("#chan")))))
+
+;; When `erc-kill-buffer-on-part' is non-nil, and the parted buffer has
+;; already been killed, don't kill the server buffer.  Bug#70840
+(ert-deftest erc-scenarios-base-kill-on-part--enabled/killed ()
+  :tags '(:expensive-test)
+  (should-not erc-kill-buffer-on-part)
+
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/reuse-buffers/channel")
+       (erc-server-flood-penalty 0.1)
+       (dumb-server (erc-d-run "localhost" t 'foonet))
+       (port (process-contact dumb-server :service))
+       (erc-kill-buffer-on-part t)
+       (killingp nil)
+       (calls nil)
+       (erc-part-hook (lambda (b) (push (cons (buffer-name b) killingp)
+                                        calls)))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to foonet")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "This server is in debug mode")))
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#chan"))
+      (funcall expect 10 "<alice> bob: Whilst I can shake")
+      ;; There's a race here because the response handler may run
+      ;; before `killingp' is nil, but at least false negatives aren't
+      ;; possible.  Shadowing `erc-server-send-queue' temporarily
+      ;; would fix it, but that's too leaky for this style of test.
+      (setq killingp 'kill)
+      (kill-buffer)
+      (setq killingp nil))
+
+    (erc-d-t-wait-for 20 (null (get-buffer "#chan")))
+    (should (equal calls '(("#chan" . kill))))
+    (erc-d-t-ensure-for 0.1 (get-buffer "foonet"))))
+
+(ert-deftest erc-scenarios-base-kill-on-part--enabled/killed/compat ()
+  :tags '(:expensive-test)
+  (should-not erc-kill-buffer-on-part)
+
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/reuse-buffers/channel")
+       (erc-server-flood-penalty 0.1)
+       (dumb-server (erc-d-run "localhost" t 'foonet))
+       (port (process-contact dumb-server :service))
+       (erc-kill-buffer-on-part t)
+       (erc--run-part-hook-with-nil-buffer-p t) ; option under test
+       (killingp nil)
+       (calls nil)
+       (erc-part-hook (lambda (b) (push (cons b killingp) calls)))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to foonet")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "This server is in debug mode")))
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#chan"))
+      (funcall expect 10 "<alice> bob: Whilst I can shake")
+      (setq killingp 'kill)
+      (kill-buffer)
+      (setq killingp nil))
+
+    (erc-d-t-wait-for 20 (null (get-buffer "#chan")))
+    (erc-d-t-wait-for 20 (equal calls '((nil . nil))))
+    (should (get-buffer "foonet"))))
+
+;;; erc-scenarios-base-kill-on-part.el ends here
-- 
2.44.0


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

* bug#70840: 29.3; ERC 5.5.0.29.1: erc-kill-buffer-on-part kills server buffer
       [not found]   ` <87seyj6wgh.fsf@neverwas.me>
@ 2024-05-17  3:57     ` J.P.
       [not found]     ` <87wmnt5bun.fsf@neverwas.me>
  1 sibling, 0 replies; 5+ messages in thread
From: J.P. @ 2024-05-17  3:57 UTC (permalink / raw)
  To: Thibaut Meyer; +Cc: emacs-erc, 70840

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

"J.P." <jp@neverwas.me> writes:

> "J.P." <jp@neverwas.me> writes:
>
>> There may well be other issues here I've not yet considered, so if you
>> can think of any, please share. Also, if you're up for taking this on
>> (not necessarily in the way I've described), please feel free to send a
>> patch. The same goes for anyone else out there. I can definitely help
>> with the leg work and test coverage if that makes things easier.
>> Otherwise, I may not be able to get to this in time for the next release
>> (not that there's any rush).
>
> I've gone ahead with a provisional patch (attached) that incorporates
> the points raised so far. Anyone interested, please take a look.

After thinking a bit more on this, I've flip-flopped entirely on the
notion of running `erc-part-hook' in `erc-kill-channel' and inhibiting
it in `erc-server-PART' with a would-be null buffer argument. Basically,
I've come to believe the current faulty behavior has been around too
long to justify such a change in the name of fixing a bug that's only
tangentially related. Instead, I think we should introduce a flag that
`erc-kill-channel-hook' members can use to detect when `erc-server-PART'
is killing a buffer on behalf of the option `erc-kill-buffer-on-part'.
Updated patch attached. Thanks.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0000-v1-v2.diff --]
[-- Type: text/x-patch, Size: 11688 bytes --]

From d4d766438cf2f059af20e695dd20a65dcf646c2e Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@neverwas.me>
Date: Thu, 16 May 2024 20:33:06 -0700
Subject: [PATCH 0/1] *** NOT A PATCH ***

*** BLURB HERE ***

F. Jason Park (1):
  [5.6] Don't kill server buffer with erc-kill-buffer-on-part

 etc/ERC-NEWS                                  |  8 ++
 lisp/erc/erc-backend.el                       |  9 +-
 lisp/erc/erc-log.el                           |  2 +-
 lisp/erc/erc.el                               | 32 ++++---
 .../erc/erc-scenarios-base-kill-on-part.el    | 95 +++++++++++++++++++
 5 files changed, 132 insertions(+), 14 deletions(-)
 create mode 100644 test/lisp/erc/erc-scenarios-base-kill-on-part.el

Interdiff:
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index 9d5a26595be..9c536636a04 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -648,15 +648,13 @@ release lacks a similar solution for detecting "joinedness" directly,
 but users can turn to 'xor'-ing 'erc-default-target' and 'erc-target'
 as a makeshift kludge.
 
-*** The function 'erc-kill-channel' may run the hook 'erc-part-hook'.
-Previously, when a user killed a channel buffer, 'erc-part-hook' would
-run in the response handler upon receipt of the corresponding 'PART'
-response, meaning hook members would receive a nil channel-buffer
-argument.  ERC now runs this hook immediately when a user kills a
-channel, just before sending the 'PART' command to the server.  Those
-disrupted by this change should see the definition of 'erc-part-hook'
-for a temporary escape hatch.  Also, for clarity, the function
-'erc-kill-channel' has been renamed 'erc-part-channel-on-kill'.
+*** Killing on behalf of 'erc-kill-buffer-on-part' made detectable.
+Members of 'erc-kill-channel-hook' can use the variable
+'erc-killing-buffer-on-part-p' to detect when 'erc-server-PART' is
+killing a buffer on account of the option 'erc-kill-buffer-on-part'
+being non-nil.  Also, for clarity, the function 'erc-kill-channel',
+which normally emits a 'PART' when channel buffers are killed, has
+been renamed to 'erc-part-channel-on-kill'.
 
 *** Channel-mode handling has become stricter and more predictable.
 ERC has always processed channel modes using "standardized" letters
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index 7e8e597da46..7d6a3499d06 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -1891,9 +1891,7 @@ erc--server-determine-join-display-context
                            'PART ?n nick ?u login
                            ?h host ?c chnl ?r (or reason ""))
       (when (string= nick (erc-current-nick))
-        (defvar erc--run-part-hook-with-nil-buffer-p)
-        (when (or buffer erc--run-part-hook-with-nil-buffer-p)
-          (run-hook-with-args 'erc-part-hook buffer))
+        (run-hook-with-args 'erc-part-hook buffer)
         (erc-with-buffer
             (buffer)
           (erc-remove-channel-users))
@@ -1902,8 +1900,8 @@ erc--server-determine-join-display-context
         (erc-update-mode-line buffer)
         (defvar erc-kill-buffer-on-part)
         (when (and erc-kill-buffer-on-part buffer)
-          (defvar erc--inhibit-part-channel-on-kill-p)
-          (let ((erc--inhibit-part-channel-on-kill-p t))
+          (defvar erc-killing-buffer-on-part-p)
+          (let ((erc-killing-buffer-on-part-p t))
             (kill-buffer buffer)))))))
 
 (define-erc-response-handler (PING)
diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el
index f0bd1b45e7c..019ac6c1612 100644
--- a/lisp/erc/erc-log.el
+++ b/lisp/erc/erc-log.el
@@ -290,10 +290,7 @@ erc-save-query-buffers
 
 (defun erc-conditional-save-buffer (buffer)
   "Save Query BUFFER if `erc-save-queries-on-quit' is t."
-  (when (and erc-save-buffer-on-part
-             ;; Don't run this from `erc-part-channel-on-kill' because
-             ;; `erc-save-buffer-in-logs' aready has it covered.
-             (not erc--inhibit-part-channel-on-kill-p))
+  (when (and buffer erc-save-buffer-on-part)
     (erc-save-buffer-in-logs buffer)))
 
 (defun erc-conditional-save-queries (process)
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index a1c94288e8d..c174ca4b30e 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -470,22 +470,21 @@ erc-quit-hook
 
 (defcustom erc-part-hook nil
   "Hook run when processing a PART message directed at our nick.
-Called in the server buffer with one argument: the BUFFER being parted.
-Also runs via `erc-part-channel-on-kill' on `erc-kill-channel-hook' if
-killing BUFFER initiated the \"PART\".  Note that beginning with ERC
-5.6, this hook doesn't run upon receiving a \"PART\" from the server if
-BUFFER has already been killed.  See code near this option's definition
-for a possible escape hatch."
+Called in the server buffer with a single argument: the channel buffer
+being parted.  For historical reasons, the buffer argument may be nil if
+it's been killed or otherwise no longer exists.  This typically happens
+when the \"PART\" response being handled comes by way of a channel
+buffer being killed, which, by default, tells `erc-part-channel-on-kill'
+to emit a \"PART\".  Users needing to operate on a parted channel buffer
+before it's killed in this fashion should use `erc-kill-channel-hook'
+and condition their code on `erc-killing-buffer-on-part-p' being nil."
   :group 'erc-hooks
   :type 'hook)
 
-(defvar erc--run-part-hook-with-nil-buffer-p nil
-  "When non-nil, allow running `erc-part-hook' with a nil buffer argument.
-Moreover, forgo running the hook before sending a \"PART\" when the user
-kills a channel buffer.  This compat-oriented escape hatch exists for
-third-party code that expects to run unconditionally in the default
-response handler `erc-server-PART' when ERC receives a self-directed
-\"PART\" from the server.")
+(defvar erc-killing-buffer-on-part-p nil
+  "Non-nil when killing a target buffer while handling a \"PART\" response.
+Useful for preventing the redundant execution of code designed to run
+once when parting a channel.")
 
 (defcustom erc-kick-hook nil
   "Hook run when processing a KICK message directed at our nick.
@@ -1124,8 +1123,7 @@ erc-last-saved-position
 
 (defcustom erc-kill-buffer-on-part nil
   "Kill the channel buffer on PART.
-This variable should probably stay nil, as ERC can reuse buffers if
-you rejoin them later."
+Nil by default because ERC can reuse buffers later re-joined."
   :group 'erc-quit-and-part
   :type 'boolean)
 
@@ -9669,18 +9667,12 @@ erc-kill-server
     (setq erc-server-quitting t)
     (erc-server-send (format "QUIT :%s" (funcall erc-quit-reason nil)))))
 
-(defvar erc--inhibit-part-channel-on-kill-p nil)
 (define-obsolete-function-alias 'erc-kill-channel #'erc-part-channel-on-kill
   "30.1")
 (defun erc-part-channel-on-kill ()
-  "Run `erc-part-hook' and send a \"PART\" when killing a channel buffer."
-  (when (and (erc-server-process-alive)
-             (not erc--inhibit-part-channel-on-kill-p))
-    (unless erc--run-part-hook-with-nil-buffer-p
-      (let ((buffer (current-buffer))
-            (erc--inhibit-part-channel-on-kill-p t))
-        (erc-with-server-buffer
-          (run-hook-with-args 'erc-part-hook buffer))))
+  "Send a \"PART\" when killing a channel buffer."
+  (when (and (not erc-killing-buffer-on-part-p)
+             (erc-server-process-alive))
     (let ((tgt (erc-default-target)))
       (if tgt
          (erc-server-send (format "PART %s :%s" tgt
diff --git a/test/lisp/erc/erc-scenarios-base-kill-on-part.el b/test/lisp/erc/erc-scenarios-base-kill-on-part.el
index 109cf27b01a..0ca0b1ae054 100644
--- a/test/lisp/erc/erc-scenarios-base-kill-on-part.el
+++ b/test/lisp/erc/erc-scenarios-base-kill-on-part.el
@@ -25,7 +25,9 @@
     (require 'erc-scenarios-common)))
 
 ;; Assert channel buffer is killed when `erc-kill-buffer-on-part' is
-;; enabled and a user issues a /part.
+;; enabled and a user issues a /part.  Also assert that code in
+;; `erc-kill-channel-hook' can detect when `erc-response-PART' is
+;; killing a buffer on behalf of that option.
 (ert-deftest erc-scenarios-base-kill-on-part--enabled ()
   :tags '(:expensive-test)
   (should-not erc-kill-buffer-on-part)
@@ -38,6 +40,9 @@ erc-scenarios-base-kill-on-part--enabled
        (erc-kill-buffer-on-part t)
        (calls nil)
        (erc-part-hook (lambda (b) (push (buffer-name b) calls)))
+       (erc-kill-channel-hook
+        (cons (lambda () (push erc-killing-buffer-on-part-p calls))
+              erc-kill-channel-hook))
        (expect (erc-d-t-make-expecter)))
 
     (ert-info ("Connect to foonet")
@@ -53,7 +58,7 @@ erc-scenarios-base-kill-on-part--enabled
       (erc-scenarios-common-say "/part"))
 
     (erc-d-t-wait-for 20 (null (get-buffer "#chan")))
-    (should (equal calls '("#chan")))))
+    (should (equal calls '(t "#chan")))))
 
 ;; When `erc-kill-buffer-on-part' is non-nil, and the parted buffer has
 ;; already been killed, don't kill the server buffer.  Bug#70840
@@ -67,10 +72,8 @@ erc-scenarios-base-kill-on-part--enabled/killed
        (dumb-server (erc-d-run "localhost" t 'foonet))
        (port (process-contact dumb-server :service))
        (erc-kill-buffer-on-part t)
-       (killingp nil)
        (calls nil)
-       (erc-part-hook (lambda (b) (push (cons (buffer-name b) killingp)
-                                        calls)))
+       (erc-part-hook (lambda (b) (push b calls)))
        (expect (erc-d-t-make-expecter)))
 
     (ert-info ("Connect to foonet")
@@ -83,50 +86,10 @@ erc-scenarios-base-kill-on-part--enabled/killed
 
     (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#chan"))
       (funcall expect 10 "<alice> bob: Whilst I can shake")
-      ;; There's a race here because the response handler may run
-      ;; before `killingp' is nil, but at least false negatives aren't
-      ;; possible.  Shadowing `erc-server-send-queue' temporarily
-      ;; would fix it, but that's too leaky for this style of test.
-      (setq killingp 'kill)
-      (kill-buffer)
-      (setq killingp nil))
+      (kill-buffer))
 
     (erc-d-t-wait-for 20 (null (get-buffer "#chan")))
-    (should (equal calls '(("#chan" . kill))))
+    (erc-d-t-wait-for 10 (equal calls '(nil)))
     (erc-d-t-ensure-for 0.1 (get-buffer "foonet"))))
 
-(ert-deftest erc-scenarios-base-kill-on-part--enabled/killed/compat ()
-  :tags '(:expensive-test)
-  (should-not erc-kill-buffer-on-part)
-
-  (erc-scenarios-common-with-cleanup
-      ((erc-scenarios-common-dialog "base/reuse-buffers/channel")
-       (erc-server-flood-penalty 0.1)
-       (dumb-server (erc-d-run "localhost" t 'foonet))
-       (port (process-contact dumb-server :service))
-       (erc-kill-buffer-on-part t)
-       (erc--run-part-hook-with-nil-buffer-p t) ; option under test
-       (killingp nil)
-       (calls nil)
-       (erc-part-hook (lambda (b) (push (cons b killingp) calls)))
-       (expect (erc-d-t-make-expecter)))
-
-    (ert-info ("Connect to foonet")
-      (with-current-buffer (erc :server "127.0.0.1"
-                                :port port
-                                :nick "tester"
-                                :password "foonet:changeme"
-                                :full-name "tester")
-        (funcall expect 10 "This server is in debug mode")))
-
-    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#chan"))
-      (funcall expect 10 "<alice> bob: Whilst I can shake")
-      (setq killingp 'kill)
-      (kill-buffer)
-      (setq killingp nil))
-
-    (erc-d-t-wait-for 20 (null (get-buffer "#chan")))
-    (erc-d-t-wait-for 20 (equal calls '((nil . nil))))
-    (should (get-buffer "foonet"))))
-
 ;;; erc-scenarios-base-kill-on-part.el ends here
-- 
2.45.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0001-5.6-Don-t-kill-server-buffer-with-erc-kill-buffer-on.patch --]
[-- Type: text/x-patch, Size: 11285 bytes --]

From d4d766438cf2f059af20e695dd20a65dcf646c2e Mon Sep 17 00:00:00 2001
From: "F. Jason Park" <jp@neverwas.me>
Date: Tue, 14 May 2024 21:09:55 -0700
Subject: [PATCH 1/1] [5.6] Don't kill server buffer with
 erc-kill-buffer-on-part

* etc/ERC-NEWS: Mention flag variable `erc-killing-buffer-on-part-p'
and renaming of function `erc-kill-channel'.
* lisp/erc/erc-backend.el (erc-server-PART): Only kill a buffer on
behalf of `erc-kill-buffer-on-part' when the buffer hasn't already
been killed, and bind `erc-killing-buffer-on-part-p' to t when doing
so.
* lisp/erc/erc-log.el (erc-conditional-save-buffer): Don't save logs
when the buffer parameter is nil because that causes the server buffer
to be saved out.
* lisp/erc/erc.el (erc-part-hook): Redo doc string.
(erc-killing-buffer-on-part-p): New variable, a flag to prevent
redundant execution of `erc-kill-channel-hook' members concerned with
parted channels.
(erc-kill-buffer-on-part): Tweak doc string.
(erc-kill-channel-hook): Use new name for `erc-kill-channel'.
(erc-kill-channel, erc-part-channel-on-kill): Rename former to latter,
and inhibit execution when `erc-killing-buffer-on-part-p' is non-nil.
* test/lisp/erc/erc-scenarios-base-kill-on-part.el: New file.
(Bug#70840)
---
 etc/ERC-NEWS                                  |  8 ++
 lisp/erc/erc-backend.el                       |  9 +-
 lisp/erc/erc-log.el                           |  2 +-
 lisp/erc/erc.el                               | 32 ++++---
 .../erc/erc-scenarios-base-kill-on-part.el    | 95 +++++++++++++++++++
 5 files changed, 132 insertions(+), 14 deletions(-)
 create mode 100644 test/lisp/erc/erc-scenarios-base-kill-on-part.el

diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS
index b66ea6a7a02..9c536636a04 100644
--- a/etc/ERC-NEWS
+++ b/etc/ERC-NEWS
@@ -648,6 +648,14 @@ release lacks a similar solution for detecting "joinedness" directly,
 but users can turn to 'xor'-ing 'erc-default-target' and 'erc-target'
 as a makeshift kludge.
 
+*** Killing on behalf of 'erc-kill-buffer-on-part' made detectable.
+Members of 'erc-kill-channel-hook' can use the variable
+'erc-killing-buffer-on-part-p' to detect when 'erc-server-PART' is
+killing a buffer on account of the option 'erc-kill-buffer-on-part'
+being non-nil.  Also, for clarity, the function 'erc-kill-channel',
+which normally emits a 'PART' when channel buffers are killed, has
+been renamed to 'erc-part-channel-on-kill'.
+
 *** Channel-mode handling has become stricter and more predictable.
 ERC has always processed channel modes using "standardized" letters
 and popular status prefixes.  Starting with this release, ERC will
diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el
index ab419d2b018..7d6a3499d06 100644
--- a/lisp/erc/erc-backend.el
+++ b/lisp/erc/erc-backend.el
@@ -1883,6 +1883,9 @@ erc--server-determine-join-display-context
          (buffer (erc-get-buffer chnl proc)))
     (pcase-let ((`(,nick ,login ,host)
                  (erc-parse-user (erc-response.sender parsed))))
+      ;; When `buffer' is nil, `erc-remove-channel-member',
+      ;; `erc-remove-channel-users', and `erc-part-hook', don't run or
+      ;; do nothing, and the message is printed in the server buffer.
       (erc-remove-channel-member buffer nick)
       (erc-display-message parsed 'notice buffer
                            'PART ?n nick ?u login
@@ -1896,8 +1899,10 @@ erc--server-determine-join-display-context
           (erc-delete-default-channel chnl buffer))
         (erc-update-mode-line buffer)
         (defvar erc-kill-buffer-on-part)
-        (when erc-kill-buffer-on-part
-          (kill-buffer buffer))))))
+        (when (and erc-kill-buffer-on-part buffer)
+          (defvar erc-killing-buffer-on-part-p)
+          (let ((erc-killing-buffer-on-part-p t))
+            (kill-buffer buffer)))))))
 
 (define-erc-response-handler (PING)
   "Handle ping messages." nil
diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el
index d5c56bcc2b3..019ac6c1612 100644
--- a/lisp/erc/erc-log.el
+++ b/lisp/erc/erc-log.el
@@ -290,7 +290,7 @@ erc-save-query-buffers
 
 (defun erc-conditional-save-buffer (buffer)
   "Save Query BUFFER if `erc-save-queries-on-quit' is t."
-  (when erc-save-buffer-on-part
+  (when (and buffer erc-save-buffer-on-part)
     (erc-save-buffer-in-logs buffer)))
 
 (defun erc-conditional-save-queries (process)
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index c92fd42322a..c174ca4b30e 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -470,13 +470,22 @@ erc-quit-hook
 
 (defcustom erc-part-hook nil
   "Hook run when processing a PART message directed at our nick.
-
-The hook receives one argument, the current BUFFER.
-See also `erc-server-QUIT-functions', `erc-quit-hook' and
-`erc-disconnected-hook'."
+Called in the server buffer with a single argument: the channel buffer
+being parted.  For historical reasons, the buffer argument may be nil if
+it's been killed or otherwise no longer exists.  This typically happens
+when the \"PART\" response being handled comes by way of a channel
+buffer being killed, which, by default, tells `erc-part-channel-on-kill'
+to emit a \"PART\".  Users needing to operate on a parted channel buffer
+before it's killed in this fashion should use `erc-kill-channel-hook'
+and condition their code on `erc-killing-buffer-on-part-p' being nil."
   :group 'erc-hooks
   :type 'hook)
 
+(defvar erc-killing-buffer-on-part-p nil
+  "Non-nil when killing a target buffer while handling a \"PART\" response.
+Useful for preventing the redundant execution of code designed to run
+once when parting a channel.")
+
 (defcustom erc-kick-hook nil
   "Hook run when processing a KICK message directed at our nick.
 
@@ -1114,8 +1123,7 @@ erc-last-saved-position
 
 (defcustom erc-kill-buffer-on-part nil
   "Kill the channel buffer on PART.
-This variable should probably stay nil, as ERC can reuse buffers if
-you rejoin them later."
+Nil by default because ERC can reuse buffers later re-joined."
   :group 'erc-quit-and-part
   :type 'boolean)
 
@@ -9598,7 +9606,7 @@ erc-kill-server-hook
   :type 'hook)
 
 (defcustom erc-kill-channel-hook
-  '(erc-kill-channel
+  '(erc-part-channel-on-kill
     erc-networks-shrink-ids-and-buffer-names
     erc-networks-rename-surviving-target-buffer)
   "Invoked whenever a channel-buffer is killed via `kill-buffer'."
@@ -9659,10 +9667,12 @@ erc-kill-server
     (setq erc-server-quitting t)
     (erc-server-send (format "QUIT :%s" (funcall erc-quit-reason nil)))))
 
-(defun erc-kill-channel ()
-  "Sends a PART command to the server when the channel buffer is killed.
-This function should be on `erc-kill-channel-hook'."
-  (when (erc-server-process-alive)
+(define-obsolete-function-alias 'erc-kill-channel #'erc-part-channel-on-kill
+  "30.1")
+(defun erc-part-channel-on-kill ()
+  "Send a \"PART\" when killing a channel buffer."
+  (when (and (not erc-killing-buffer-on-part-p)
+             (erc-server-process-alive))
     (let ((tgt (erc-default-target)))
       (if tgt
          (erc-server-send (format "PART %s :%s" tgt
diff --git a/test/lisp/erc/erc-scenarios-base-kill-on-part.el b/test/lisp/erc/erc-scenarios-base-kill-on-part.el
new file mode 100644
index 00000000000..0ca0b1ae054
--- /dev/null
+++ b/test/lisp/erc/erc-scenarios-base-kill-on-part.el
@@ -0,0 +1,95 @@
+;;; erc-scenarios-base-kill-on-part.el --- killing buffers on part -*- lexical-binding: t -*-
+
+;; Copyright (C) 2024 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert-x)
+(eval-and-compile
+  (let ((load-path (cons (ert-resource-directory) load-path)))
+    (require 'erc-scenarios-common)))
+
+;; Assert channel buffer is killed when `erc-kill-buffer-on-part' is
+;; enabled and a user issues a /part.  Also assert that code in
+;; `erc-kill-channel-hook' can detect when `erc-response-PART' is
+;; killing a buffer on behalf of that option.
+(ert-deftest erc-scenarios-base-kill-on-part--enabled ()
+  :tags '(:expensive-test)
+  (should-not erc-kill-buffer-on-part)
+
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/reuse-buffers/channel")
+       (erc-server-flood-penalty 0.1)
+       (dumb-server (erc-d-run "localhost" t 'foonet))
+       (port (process-contact dumb-server :service))
+       (erc-kill-buffer-on-part t)
+       (calls nil)
+       (erc-part-hook (lambda (b) (push (buffer-name b) calls)))
+       (erc-kill-channel-hook
+        (cons (lambda () (push erc-killing-buffer-on-part-p calls))
+              erc-kill-channel-hook))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to foonet")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "This server is in debug mode")))
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#chan"))
+      (funcall expect 10 "<alice> bob: Whilst I can shake")
+      (erc-scenarios-common-say "/part"))
+
+    (erc-d-t-wait-for 20 (null (get-buffer "#chan")))
+    (should (equal calls '(t "#chan")))))
+
+;; When `erc-kill-buffer-on-part' is non-nil, and the parted buffer has
+;; already been killed, don't kill the server buffer.  Bug#70840
+(ert-deftest erc-scenarios-base-kill-on-part--enabled/killed ()
+  :tags '(:expensive-test)
+  (should-not erc-kill-buffer-on-part)
+
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/reuse-buffers/channel")
+       (erc-server-flood-penalty 0.1)
+       (dumb-server (erc-d-run "localhost" t 'foonet))
+       (port (process-contact dumb-server :service))
+       (erc-kill-buffer-on-part t)
+       (calls nil)
+       (erc-part-hook (lambda (b) (push b calls)))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to foonet")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port port
+                                :nick "tester"
+                                :password "foonet:changeme"
+                                :full-name "tester")
+        (funcall expect 10 "This server is in debug mode")))
+
+    (with-current-buffer (erc-d-t-wait-for 20 (get-buffer "#chan"))
+      (funcall expect 10 "<alice> bob: Whilst I can shake")
+      (kill-buffer))
+
+    (erc-d-t-wait-for 20 (null (get-buffer "#chan")))
+    (erc-d-t-wait-for 10 (equal calls '(nil)))
+    (erc-d-t-ensure-for 0.1 (get-buffer "foonet"))))
+
+;;; erc-scenarios-base-kill-on-part.el ends here
-- 
2.45.0


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

* bug#70840: 29.3; ERC 5.5.0.29.1: erc-kill-buffer-on-part kills server buffer
       [not found]     ` <87wmnt5bun.fsf@neverwas.me>
@ 2024-05-28 13:36       ` J.P.
  0 siblings, 0 replies; 5+ messages in thread
From: J.P. @ 2024-05-28 13:36 UTC (permalink / raw)
  To: 70840-done; +Cc: Thibaut Meyer, emacs-erc

"J.P." <jp@neverwas.me> writes:

> After thinking a bit more on this, I've flip-flopped entirely on the
> notion of running `erc-part-hook' in `erc-kill-channel' and inhibiting
> it in `erc-server-PART' with a would-be null buffer argument. Basically,
> I've come to believe the current faulty behavior has been around too
> long to justify such a change in the name of fixing a bug that's only
> tangentially related. Instead, I think we should introduce a flag that
> `erc-kill-channel-hook' members can use to detect when `erc-server-PART'
> is killing a buffer on behalf of the option `erc-kill-buffer-on-part'.
> Updated patch attached. Thanks.

I've installed something similar as

  cf7cc4c630a Don't kill server buffer with erc-kill-buffer-on-part

Thanks and closing.





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

end of thread, other threads:[~2024-05-28 13:36 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-08 20:37 bug#70840: 29.3; ERC 5.5.0.29.1: erc-kill-buffer-on-part kills server buffer Thibaut Meyer via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-05-14  0:55 ` J.P.
     [not found] ` <8734ql9ppd.fsf@neverwas.me>
2024-05-15 13:22   ` J.P.
     [not found]   ` <87seyj6wgh.fsf@neverwas.me>
2024-05-17  3:57     ` J.P.
     [not found]     ` <87wmnt5bun.fsf@neverwas.me>
2024-05-28 13:36       ` J.P.

Code repositories for project(s) associated with this external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.