* 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
[parent not found: <8734ql9ppd.fsf@neverwas.me>]
* 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
[parent not found: <87seyj6wgh.fsf@neverwas.me>]
* 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
[parent not found: <87wmnt5bun.fsf@neverwas.me>]
* 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 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).