commit 01b80a6f0e40a4390717a79a73c61899e2ec2968 (HEAD, refs/remotes/origin/master) Author: Paul Eggert Date: Thu Jul 13 23:55:50 2023 -0700 Reorder NaN, INF paras * doc/lispref/numbers.texi (Float Basics): Reorder paragraphs so that examples follow defns. diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi index a49afb73539..071ec0f518d 100644 --- a/doc/lispref/numbers.texi +++ b/doc/lispref/numbers.texi @@ -279,12 +279,6 @@ Float Basics conversely, @code{(equal 0.0 -0.0)} returns @code{nil} whereas @code{(= 0.0 -0.0)} returns @code{t}. - Infinities and NaNs are not available on legacy systems that lack -IEEE floating-point arithmetic. On a circa 1980 VAX, for example, -Lisp reads @samp{1.0e+INF} as a large but finite floating-point number, -and @samp{0.0e+NaN} as some other non-numeric Lisp object that provokes an -error if used numerically. - Here are read syntaxes for these special floating-point values: @table @asis @@ -294,6 +288,12 @@ Float Basics @samp{0.0e+NaN} and @samp{-0.0e+NaN} @end table + Infinities and NaNs are not available on legacy systems that lack +IEEE floating-point arithmetic. On a circa 1980 VAX, for example, +Lisp reads @samp{1.0e+INF} as a large but finite floating-point number, +and @samp{0.0e+NaN} as some other non-numeric Lisp object that provokes an +error if used numerically. + The following functions are specialized for handling floating-point numbers: commit be501f468ed36cddf01305b88bab44366b447c03 Author: Paul Eggert Date: Thu Jul 13 23:36:33 2023 -0700 Improve doc for VAX reading NaN, INF * doc/lispref/numbers.texi (Float Basics): Improve description of how Lisp reads infinities and NaNs on a VAX. diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi index bcf89fc9ab1..a49afb73539 100644 --- a/doc/lispref/numbers.texi +++ b/doc/lispref/numbers.texi @@ -280,9 +280,9 @@ Float Basics @code{(= 0.0 -0.0)} returns @code{t}. Infinities and NaNs are not available on legacy systems that lack -IEEE floating-point arithmetic. On a circa 1980 VAX, for example, the -Lisp reader approximates an infinity with the nearest finite value, -and a NaN with some other non-numeric Lisp object that provokes an +IEEE floating-point arithmetic. On a circa 1980 VAX, for example, +Lisp reads @samp{1.0e+INF} as a large but finite floating-point number, +and @samp{0.0e+NaN} as some other non-numeric Lisp object that provokes an error if used numerically. Here are read syntaxes for these special floating-point values: commit 47c2da092a0288c50a0ed7974d2a3427382f2fd5 Author: Stefan Monnier Date: Thu Jul 13 22:26:19 2023 -0400 cl-print: Allow expanding the contents of hash-tables * lisp/emacs-lisp/cl-print.el (cl-print-object) : Add an ellipsis. (cl-print-object-contents) : New method. diff --git a/etc/NEWS b/etc/NEWS index 3e56fbb973c..d7f5fdc4cbb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -92,10 +92,13 @@ plus, minus, check-mark, start, etc. The 'tool-bar-position' frame parameter can be set to 'bottom' on all window systems other than Nextstep. -** You can expand the "..." truncation everywhere. +** cl-print +*** You can expand the "..." truncation everywhere. The code that allowed "..." to be expanded in the *Backtrace* should now work anywhere the data is generated by `cl-print`. +*** hash-tables' contents can be expanded via the ellipsis + ** Modeline elements can now be right-aligned. Anything following the symbol 'mode-line-format-right-align' in 'mode-line-format' will be right-aligned. Exactly where it is diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el index 905c2bc9f09..71929caabb8 100644 --- a/lisp/emacs-lisp/cl-print.el +++ b/lisp/emacs-lisp/cl-print.el @@ -57,7 +57,7 @@ cl-print-object-contents "Dispatcher to print partial contents of OBJECT on STREAM. This is used when replacing an ellipsis with the contents it represents. OBJECT is the object that has been partially printed -and START represents the place at which the contents where +and START represents the place at which the contents were replaced with an ellipsis. Print the contents hidden by the ellipsis to STREAM." ;; Every cl-print-object method which can print an ellipsis should @@ -132,17 +132,30 @@ cl-print-object-contents (cl-print--vector-contents object start stream)) ;FIXME: η-redex! (cl-defmethod cl-print-object ((object hash-table) stream) - ;; FIXME: Make it possible to see the contents, like `prin1' does, - ;; e.g. using ellipsis. Make sure `cl-fill' can pretty print the result! + ;; Make sure `pp-fill' can pretty print the result! (princ "#" stream)) +(cl-defmethod cl-print-object-contents ((object hash-table) _start stream) + ;; If we want to obey `print-length' here, it's not completely obvious + ;; what we should use as marker of "where we are" within the hash-table. + ;; We could use here a simple number or a set of keys already printed, + ;; but it still breaks down if elements get added/removed. + ;; Instead here we convert the hash-table to an alist once and for all. + (let ((alist nil)) + (maphash (lambda (k v) (push (cons k v) alist)) object) + ;; While the order of elements seen by `maphash' is "arbitrary" + ;; it tends to be in the order objects have been added, which is + ;; sometimes handy, so it's nice to preserve this order here. + (cl-print-object (nreverse alist) stream))) + (define-button-type 'help-byte-code 'follow-link t 'action (lambda (button) @@ -475,7 +488,6 @@ cl-print-propertize-ellipsis `cl-print-insert-ellipsis'." (let ((value (list object start cl-print--number-table cl-print--currently-printing))) - ;; FIXME: Make it into a button! (with-current-buffer stream (put-text-property beg end 'cl-print-ellipsis value stream) (make-text-button beg end :type 'cl-print-ellipsis)))) commit badbfd57cdaf9ea22aa9b64ff6bdc55da18b864c Author: Stefan Monnier Date: Thu Jul 13 21:51:03 2023 -0400 * lisp/emacs-lisp/backtrace.el (backtrace--change-button-skip): Typo) diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el index af06577fe56..1beeb523f08 100644 --- a/lisp/emacs-lisp/backtrace.el +++ b/lisp/emacs-lisp/backtrace.el @@ -413,12 +413,12 @@ backtrace--set-locals-visible-overlay (overlay-put o 'evaporate t)))) (defun backtrace--change-button-skip (beg end value) - "Change the skip property on all buttons between BEG and END. + "Change the `skip' property on all buttons between BEG and END. Set it to VALUE unless the button is a `cl-print-ellipsis' button." (let ((inhibit-read-only t)) (setq beg (next-button beg)) (while (and beg (< beg end)) - (unless (eq (button-type beg) cl-print-ellipsis) + (unless (eq (button-type beg) 'cl-print-ellipsis) (button-put beg 'skip value)) (setq beg (next-button beg))))) commit 2716dd13cedb41f677be6481414a9710dfcc1857 Author: F. Jason Park Date: Wed Jul 12 23:53:06 2023 -0700 Decouple keep-place-indicator from global ERC module * etc/ERC-NEWS: Let users know that `keep-place-indicator' is a wholly separate module from `keep-place'. * lisp/erc/erc-goodies.el (erc-keep-place-indicator-setup): Perform some housekeeping on `erc-keep-place-mode'. (erc-keep-place-indicator-mode, erc-keep-place-indicator-enable, erc-keep-place-indicator-disable): Take precautions to work around the activation state of global module `keep-place', but no longer depend on it. (erc--keep-place-indicator-on-global-module): New function to ensure `erc-keep-place' runs exactly once on `erc-insert-pre-hook', regardless of whether module `keep-place' is active. * test/lisp/erc/erc-goodies-tests.el (erc-goodies-tests--assert-kp-indicator-on, erc-goodies-tests--assert-kp-indicator-off, erc-goodies-tests--kp-indicator-populate, erc-goodies-tests--keep-place-indicator): New helper functions. (erc-keep-place-indicator-mode, erc-keep-place-indicator-mode--no-global): Factor out some common logic and rename former to latter. (erc-keep-place-indicator-mode--global): New test. (Bug#59943) diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index 65fee9e05cd..cd0b8e5f823 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -14,13 +14,12 @@ GNU Emacs since Emacs version 22.1. * Changes in ERC 5.6 -** Module 'keep-place' now offers a visual indicator. +** Module 'keep-place' has gained a more flamboyant cousin. Remember your place in ERC buffers a bit more easily while retaining the freedom to look around. Optionally sync the indicator to any progress made when you haven't yet caught up to the live stream. See -options 'erc-keep-place-indicator-style' and friends and new module -'keep-place-indicator', which for now must be added manually to -'erc-modules'. +options 'erc-keep-place-indicator-style' and friends, and try M-x +keep-place-indicator-mode to see it in action. ** Module 'fill' now offers a style based on 'visual-line-mode'. This fill style mimics the "hanging indent" look of 'erc-fill-static' diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el index 96083de2c22..d9ededa8e68 100644 --- a/lisp/erc/erc-goodies.el +++ b/lisp/erc/erc-goodies.el @@ -208,6 +208,8 @@ erc--keep-place-indicator-setup (require 'fringe) (erc--restore-initialize-priors erc-keep-place-indicator-mode erc--keep-place-indicator-overlay (make-overlay 0 0)) + (add-hook 'erc-keep-place-mode-hook + #'erc--keep-place-indicator-on-global-module nil t) (add-hook 'window-configuration-change-hook #'erc--keep-place-indicator-on-window-configuration-change nil t) (when-let* (((memq erc-keep-place-indicator-style '(t arrow))) @@ -223,27 +225,39 @@ erc--keep-place-indicator-setup ;;;###autoload(put 'keep-place-indicator 'erc--feature 'erc-goodies) (define-erc-module keep-place-indicator nil - "`keep-place' with a fringe arrow and/or highlighted face." - ((unless erc-keep-place-mode - (unless (memq 'keep-place erc-modules) - (erc--warn-once-before-connect 'erc-keep-place-mode - "Local module `keep-place-indicator' needs module `keep-place'." - " Enabling now. This will affect \C-]all\C-] ERC sessions." - " Add `keep-place' to `erc-modules' to silence this message.")) - (erc-keep-place-mode +1)) + "Buffer-local `keep-place' with fringe arrow and/or highlighted face. +Play nice with global module `keep-place' but don't depend on it. +Expect that users may want different combinations of `keep-place' +and `keep-place-indicator' in different buffers." + ((cond (erc-keep-place-mode) + ((memq 'keep-place erc-modules) + (erc-keep-place-mode +1)) + ;; Enable a local version of `keep-place-mode'. + (t (add-hook 'erc-insert-pre-hook #'erc-keep-place 90 t))) (if (pcase erc-keep-place-indicator-buffer-type ('target erc--target) ('server (not erc--target)) ('t t)) (erc--keep-place-indicator-setup) - (setq erc-keep-place-indicator-mode nil))) + (erc-keep-place-indicator-mode -1))) ((when erc--keep-place-indicator-overlay - (delete-overlay erc--keep-place-indicator-overlay) - (remove-hook 'window-configuration-change-hook - #'erc--keep-place-indicator-on-window-configuration-change t) - (kill-local-variable 'erc--keep-place-indicator-overlay))) + (delete-overlay erc--keep-place-indicator-overlay)) + (remove-hook 'window-configuration-change-hook + #'erc--keep-place-indicator-on-window-configuration-change t) + (remove-hook 'erc-keep-place-mode-hook + #'erc--keep-place-indicator-on-global-module t) + (remove-hook 'erc-insert-pre-hook #'erc-keep-place t) + (kill-local-variable 'erc--keep-place-indicator-overlay)) 'local) +(defun erc--keep-place-indicator-on-global-module () + "Ensure `keep-place-indicator' can cope with `erc-keep-place-mode'. +That is, ensure the local module can survive a user toggling the +global one." + (if erc-keep-place-mode + (remove-hook 'erc-insert-pre-hook #'erc-keep-place t) + (add-hook 'erc-insert-pre-hook #'erc-keep-place 90 t))) + (defun erc-keep-place-move (pos) "Move keep-place indicator to current line or POS. For use with `keep-place-indicator' module. When called diff --git a/test/lisp/erc/erc-goodies-tests.el b/test/lisp/erc/erc-goodies-tests.el index 7acacb319f1..cdf861e2018 100644 --- a/test/lisp/erc/erc-goodies-tests.el +++ b/test/lisp/erc/erc-goodies-tests.el @@ -245,81 +245,179 @@ erc-controls-highlight--motd ;; minor-mode toggle is allowed to disable its mode variable as ;; needed. -(ert-deftest erc-keep-place-indicator-mode () +(defun erc-goodies-tests--assert-kp-indicator-on () + (should erc--keep-place-indicator-overlay) + (should (local-variable-p 'window-configuration-change-hook)) + (should window-configuration-change-hook) + (should (memq 'erc-keep-place erc-insert-pre-hook)) + (should (eq erc-keep-place-mode + (not (local-variable-p 'erc-insert-pre-hook))))) + +(defun erc-goodies-tests--assert-kp-indicator-off () + (should-not (local-variable-p 'erc-insert-pre-hook)) + (should-not (local-variable-p 'window-configuration-change-hook)) + (should-not erc--keep-place-indicator-overlay)) + +(defun erc-goodies-tests--kp-indicator-populate () + (erc-display-message nil 'notice (current-buffer) + "This buffer is for text that is not saved") + (erc-display-message nil 'notice (current-buffer) + "and for lisp evaluation") + (should (search-forward "saved" nil t)) + (erc-keep-place-move nil) + (goto-char erc-input-marker)) + +(defun erc-goodies-tests--keep-place-indicator (test) (with-current-buffer (get-buffer-create "*erc-keep-place-indicator-mode*") (erc-mode) (erc--initialize-markers (point) nil) (setq erc-server-process (start-process "sleep" (current-buffer) "sleep" "1")) (set-process-query-on-exit-flag erc-server-process nil) - (let ((assert-off - (lambda () - (should-not erc-keep-place-indicator-mode) - (should-not (local-variable-p 'window-configuration-change-hook)) - (should-not erc--keep-place-indicator-overlay))) - (assert-on - (lambda () - (should erc--keep-place-indicator-overlay) - (should (local-variable-p 'window-configuration-change-hook)) - (should window-configuration-change-hook) - (should erc-keep-place-mode))) - ;; - erc-insert-pre-hook - erc-connect-pre-hook + (let (erc-connect-pre-hook erc-modules) - (funcall assert-off) + (ert-info ("Clean slate") + (erc-goodies-tests--assert-kp-indicator-off) + (should-not erc-keep-place-mode) + (should-not (memq 'keep-place erc-modules))) - (ert-info ("Value t") - (should (eq erc-keep-place-indicator-buffer-type t)) - (erc-keep-place-indicator-mode +1) - (funcall assert-on) - (goto-char (point-min)) - (should (search-forward "Enabling" nil t)) - (should (memq 'keep-place erc-modules))) - - (erc-keep-place-indicator-mode -1) - (funcall assert-off) - - (ert-info ("Value `target'") - (let ((erc-keep-place-indicator-buffer-type 'target)) - (erc-keep-place-indicator-mode +1) - (funcall assert-off) - (setq erc--target (erc--target-from-string "#chan")) - (erc-keep-place-indicator-mode +1) - (funcall assert-on))) - - (erc-keep-place-indicator-mode -1) - (funcall assert-off) - - (ert-info ("Value `server'") - (let ((erc-keep-place-indicator-buffer-type 'server)) - (erc-keep-place-indicator-mode +1) - (funcall assert-off) - (setq erc--target nil) - (erc-keep-place-indicator-mode +1) - (funcall assert-on))) - - ;; Populate buffer - (erc-display-message nil 'notice (current-buffer) - "This buffer is for text that is not saved") - (erc-display-message nil 'notice (current-buffer) - "and for lisp evaluation") - (should (search-forward "saved" nil t)) - (erc-keep-place-move nil) - (goto-char erc-input-marker) - - (ert-info ("Indicator survives reconnect") - (let ((erc--server-reconnecting (buffer-local-variables))) - (cl-letf (((symbol-function 'erc-server-connect) #'ignore)) - (erc-open "localhost" 6667 "tester" "Tester" 'connect - nil nil nil nil nil "tester" nil))) - (funcall assert-on) - (should (= (point) erc-input-marker)) - (goto-char (overlay-start erc--keep-place-indicator-overlay)) - (should (looking-at (rx "*** This buffer is for text"))))) + (funcall test)) (when noninteractive + (erc-keep-place-indicator-mode -1) + (erc-keep-place-mode -1) + (should-not (member 'erc-keep-place + (default-value 'erc-insert-pre-hook))) + (should-not (local-variable-p 'erc-insert-pre-hook)) (kill-buffer)))) +(ert-deftest erc-keep-place-indicator-mode--no-global () + (erc-goodies-tests--keep-place-indicator + (lambda () + + (ert-info ("Value t") + (should (eq erc-keep-place-indicator-buffer-type t)) + (erc-keep-place-indicator-mode +1) + (erc-goodies-tests--assert-kp-indicator-on) + (goto-char (point-min))) + + (erc-keep-place-indicator-mode -1) + (erc-goodies-tests--assert-kp-indicator-off) + + (ert-info ("Value `target'") + (let ((erc-keep-place-indicator-buffer-type 'target)) + ;; No-op because server buffer. + (erc-keep-place-indicator-mode +1) + (erc-goodies-tests--assert-kp-indicator-off) + ;; Spoof target buffer (no longer no-op). + (setq erc--target (erc--target-from-string "#chan")) + (erc-keep-place-indicator-mode +1) + (erc-goodies-tests--assert-kp-indicator-on))) + + (erc-keep-place-indicator-mode -1) + (erc-goodies-tests--assert-kp-indicator-off) + + (ert-info ("Value `server'") + (let ((erc-keep-place-indicator-buffer-type 'server)) + (erc-keep-place-indicator-mode +1) + (erc-goodies-tests--assert-kp-indicator-off) + (setq erc--target nil) + (erc-keep-place-indicator-mode +1) + (erc-goodies-tests--assert-kp-indicator-on))) + + ;; Populate buffer + (erc-goodies-tests--kp-indicator-populate) + + (ert-info ("Indicator survives reconnect") + (let ((erc--server-reconnecting (buffer-local-variables))) + (cl-letf (((symbol-function 'erc-server-connect) #'ignore)) + (erc-open "localhost" 6667 "tester" "Tester" 'connect + nil nil nil nil nil "tester" nil))) + (erc-goodies-tests--assert-kp-indicator-on) + (should (= (point) erc-input-marker)) + (goto-char (overlay-start erc--keep-place-indicator-overlay)) + (should (looking-at (rx "*** This buffer is for text"))))))) + +(ert-deftest erc-keep-place-indicator-mode--global () + (erc-goodies-tests--keep-place-indicator + (lambda () + + (push 'keep-place erc-modules) + + (ert-info ("Value t") + (should (eq erc-keep-place-indicator-buffer-type t)) + (erc-keep-place-indicator-mode +1) + (erc-goodies-tests--assert-kp-indicator-on) + ;; Local module activates global `keep-place'. + (should erc-keep-place-mode) + ;; Does not register local version of hook (otherwise would run + ;; twice). + (should-not (local-variable-p 'erc-insert-pre-hook)) + (goto-char (point-min))) + + (erc-keep-place-indicator-mode -1) + (erc-goodies-tests--assert-kp-indicator-off) + (should erc-keep-place-mode) + (should (member 'erc-keep-place erc-insert-pre-hook)) + + (ert-info ("Value `target'") + (let ((erc-keep-place-indicator-buffer-type 'target)) + ;; No-op because server buffer. + (erc-keep-place-indicator-mode +1) + (erc-goodies-tests--assert-kp-indicator-off) + ;; Does not interfere with global activation state. + (should erc-keep-place-mode) + (should (member 'erc-keep-place erc-insert-pre-hook)) + ;; Morph into a target buffer (no longer no-op). + (setq erc--target (erc--target-from-string "#chan")) + (erc-keep-place-indicator-mode +1) + (erc-goodies-tests--assert-kp-indicator-on) + ;; Does not register local version of hook. + (should-not (local-variable-p 'erc-insert-pre-hook)))) + + (erc-keep-place-indicator-mode -1) + (erc-goodies-tests--assert-kp-indicator-off) + (should erc-keep-place-mode) + (should (member 'erc-keep-place erc-insert-pre-hook)) + + (ert-info ("Value `server'") + (let ((erc-keep-place-indicator-buffer-type 'server)) + ;; No-op because we're now a target buffer. + (erc-keep-place-indicator-mode +1) + (erc-goodies-tests--assert-kp-indicator-off) + (should erc-keep-place-mode) + (should (member 'erc-keep-place erc-insert-pre-hook)) + ;; Back to server. + (setq erc--target nil) + (erc-keep-place-indicator-mode +1) + (erc-goodies-tests--assert-kp-indicator-on) + (should-not (local-variable-p 'erc-insert-pre-hook)))) + + (ert-info ("Local adapts to global toggle") + (erc-keep-place-mode -1) + (should-not (member 'erc-keep-place + (default-value 'erc-insert-pre-hook))) + (should (member 'erc-keep-place erc-insert-pre-hook)) + (erc-goodies-tests--assert-kp-indicator-on) + (erc-keep-place-mode +1) + (should (member 'erc-keep-place (default-value 'erc-insert-pre-hook))) + (should-not (local-variable-p 'erc-insert-pre-hook)) + (erc-goodies-tests--assert-kp-indicator-on)) + + ;; Populate buffer + (erc-goodies-tests--kp-indicator-populate) + + (ert-info ("Indicator survives reconnect") + (let ((erc--server-reconnecting (buffer-local-variables))) + (cl-letf (((symbol-function 'erc-server-connect) #'ignore)) + (erc-open "localhost" 6667 "tester" "Tester" 'connect + nil nil nil nil nil "tester" nil))) + (erc-goodies-tests--assert-kp-indicator-on) + (should erc-keep-place-mode) + (should (member 'erc-keep-place erc-insert-pre-hook)) + (should (= (point) erc-input-marker)) + (goto-char (overlay-start erc--keep-place-indicator-overlay)) + (should (looking-at (rx "*** This buffer is for text"))))))) + ;;; erc-goodies-tests.el ends here commit 80e5e9ddc8d76993fa44a659307174b778aa60b7 Author: F. Jason Park Date: Thu Jun 29 07:12:46 2023 -0700 Improve walkthrough and sample config in ERC manual * doc/misc/erc.texi: Improve "Sample Session" and "Sample Configuration" sections. Move introductory paragraph detailing the history of official GNU IRC channels to the "History" chapter (from "Sample Sessoin"), and leave a link in its place. Silence strange warning in "Getting Help and Reporting Bugs" about lack of punctuation after xref. diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index d59c6d8a6c6..63ea94d9b2e 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi @@ -144,11 +144,11 @@ Getting Started and if you're having trouble with ERC, you can join the @samp{#erc} channel and ask for help there. -If you want to place ERC settings in their own file, you can place them -in @file{~/.emacs.d/.ercrc.el}, creating it if necessary. - -If you would rather use the Customize interface to change how ERC -works, do @kbd{M-x customize-group @key{RET} erc @key{RET}}. In +At some point in your ERC journey, you'll inevitably want to change +how the client looks and behaves. As with other Emacs applications, +the typical place to store your settings is your @file{init.el}. If +you would rather use the Customize interface, a good place to start is +by running @kbd{M-x customize-group @key{RET} erc @key{RET}}. In particular, ERC comes with lots of modules that may be enabled or disabled; to select which ones you want, do @kbd{M-x customize-variable @key{RET} erc-modules @key{RET}}. @@ -161,69 +161,90 @@ Getting Started @node Sample Session @section Sample Session -This is an example ERC session which shows how to connect to the -@samp{#emacs} channel on Libera.Chat. Another IRC channel on -Libera.Chat that may be of interest is @samp{#erc}, which is a channel -where ERC users and developers hang out. These channels used to live -on the Freenode IRC network until June 2021, when they---along with -the official IRC channels of the GNU Project, the Free Software -Foundation, and many other free software communities---relocated to -the Libera.Chat network in the aftermath of changes in governance and -policies of Freenode in May and June 2021. GNU and FSF's -announcements about this are at -@uref{https://lists.gnu.org/archive/html/info-gnu/2021-06/msg00005.html}, -@uref{https://lists.gnu.org/archive/html/info-gnu/2021-06/msg00007.html}, -and -@uref{https://lists.gnu.org/archive/html/info-gnu-emacs/2021-06/msg00000.html}. +This example ERC session describes how to connect to the @samp{#emacs} +channel on Libera.Chat. Also worth checking out is Libera's own +introductory guide to IRC, @uref{https://libera.chat/guides/basics}, +which presents a more comprehensive overview without instructions +specific to ERC. @itemize @bullet @item Connect to Libera.Chat -Run @kbd{M-x erc}. Use ``irc.libera.chat'' as the IRC server, ``6667'' -as the port, and choose a nickname. +Run @kbd{M-x erc @key{RET}}. Use @samp{irc.libera.chat} for the +server and @samp{6667} for the port. Choose a nickname, and hit +@key{y} when asked if you'd prefer to connect over @acronym{TLS}. @item Get used to the interface -Switch to the ``irc.libera.chat:6667'' buffer, if you're not already -there. You will see first some messages about checking for ident, and -then a bunch of other messages that describe the current IRC server. +Switch to the @file{Libera.Chat} buffer if you're not already there. +ERC calls this a @dfn{server buffer}, and it must exist for the +duration of the session. You will likely see some messages about +``ident'', authentication, and the like, followed by information +describing the current server and the network. @item Join the #emacs channel -In that buffer, type ``/join @key{SPC} #emacs'' and hit @kbd{RET}. Depending -on how you've set up ERC, either a new buffer for ``#emacs'' will be -displayed, or a new buffer called ``#emacs'' will be created in the -background. If the latter, switch to the ``#emacs'' buffer. You will -see the channel topic and a list of the people who are currently on the -channel. +In the server buffer, type @kbd{/join #emacs @key{RET}} at the prompt. +ERC will create a new buffer called @file{#emacs}. If you've already +configured ERC, you may need to switch to it manually. Once there, +you will see the channel's ``topic'' in the buffer's header line +(@pxref{Header Lines,,,elisp,}) and a list of people currently in the +channel. If you can't see the full topic, mouse over it or type +@kbd{/topic @key{RET}} at the prompt. @item Register your nickname with Libera.Chat -If you would like to be able to talk with people privately on the -Libera.Chat network, you will have to ``register'' your nickname. -To do so, switch to the ``irc.libera.chat:6667'' buffer and type -``/msg NickServ register '', replacing ``'' with -your desired password. It should tell you that the operation was -successful. +In order to access essential network features, like speaking in +certain channels and participating in private conversations, you'll +likely have to ``register'' your nickname. To do so, switch to the +@file{Libera.Chat} buffer and type @kbd{/msg NickServ register +@samp{} @samp{} @key{RET}}, replacing +@samp{} and @samp{} with your desired account +password and contact email (both sans quotes). The server should tell +you that the operation was successful. See the official Libera.Chat +docs if you encounter problems. + +In addition to creating an account, this process also +``authenticates'' you to the network's ``account services'' system for +the duration of the session. In other words, you're now logged in. +However, when you connect in the future, you'll need to authenticate +again by providing the same credentials somehow. When you're finished +with this walk through, see ``Next Steps'', below, to learn some ways +to do that. @item Talk to people in the channel -If you switch back to the ``#emacs'' buffer, you can type a message, and -everyone on the channel will see it. +Switch back to the @file{#emacs} buffer and type a message at the +prompt, hitting @kbd{RET} once satisfied. Everyone in the channel +will now see your message. @item Open a query buffer to talk to someone -If you want to talk with someone in private (this should usually not be -done for technical help, only for personal questions), type ``/query -'', replacing ``'' with the nickname of the person you would -like to talk to. Depending on how ERC is set up, you will either see a -new buffer with the name of the person, or such a buffer will be created -in the background and you will have to switch to it. Begin typing -messages, and you will be able to have a conversation. - -Note that if the other person is not registered, you will not be able to -talk with them. +If you want to talk with someone in private, type @kbd{/query +@samp{} @key{RET}}, replacing @samp{} with the their +nickname. As before, with the server buffer, if this new @dfn{query +buffer} doesn't appear in the current window, you may have to switch +to it. Regardless, its name should match @samp{}. Once there, +type something at the prompt and hit @kbd{RET}, and the other party +will see it. + +Keep in mind that if either party isn't authenticated, you may not be +able to converse at all. Also, depending on the network, certain +social conventions may apply to the practice of direct messaging. As +a general rule, queries should usually be reserved for personal +matters rather than technical help, which can often benefit (and +benefit @emph{from}) a larger audience. + +@item Next steps + +Try joining another channel, such as @samp{#erc}, where ERC users and +developers hang out (@pxref{Official IRC channels} for more on the +history of @samp{#emacs}). For ideas on various options to customize, +@pxref{Sample Configuration}. To learn how ERC can authenticate you +to the network automatically whenever you connect, @pxref{SASL}. As +always, if you encounter problems, @pxref{Getting Help and Reporting +Bugs}. @end itemize @@ -1192,76 +1213,277 @@ Sample Configuration @section Sample Configuration @cindex configuration, sample -Here is an example of configuration settings for ERC@. This can go into -your Emacs configuration file. Everything after the @code{(require -'erc)} command can optionally go into @file{~/.emacs.d/.ercrc.el}. +Here is an example configuration for ERC@. @strong{Don't panic} if +you aren't familiar with @samp{use-package} or have no interest in +learning it. For our purposes, it's just a means of presenting +configuration details in a tidy, standardized format. If it helps, +just pretend it's some make-believe, pseudo configuration language. +Although the syntax below is easy enough to intuit and adapt to your +setup, you may wish to keep the following in mind (or @pxref{Top,,, +use-package,}): + +@itemize @bullet +@item +Each @code{use-package} ``declaration'' focuses on a library +``feature'', which is just a symbol you'd normally @code{require} in +your config @pxref{Named Features,,, elisp,}). + +@item +Emacs loads anything in a @code{:config} section @emph{after} loading +whatever library @code{provide}s the declaration's feature. + +@item +Everything in a @code{:custom} or @code{:custom-face} section is +basically something you'd find in your @code{custom-file}. +@end itemize + +@noindent +The following would typically go in your init file. Experienced users +may opt to keep any non-settings, like commands and functions, in a +dedicated @file{~/.emacs.d/.ercrc.el}. Whatever the case, please keep +in mind that you can replace nearly all of the following with Custom +settings (@pxref{Sample configuration via Customize}). + +@lisp +;;; My ERC configuration -*- lexical-binding: t -*- + +(use-package erc + :config + ;; Prefer SASL to NickServ, colorize nicknames, interpret mIRC colors, + ;; and list buffers and channel members in separate side panels. + (setopt erc-modules + (seq-union '(sasl nicks irccontrols bufbar nickbar scrolltobottom) + erc-modules)) + + :custom + ;; Protect me from accidentally sending excess lines. + (erc-inhibit-multiline-input t) + (erc-send-whitespace-lines t) + (erc-ask-about-multiline-input t) + + ;; Reconnect automatically using a fancy strategy. + (erc-server-reconnect-function #'erc-server-delayed-check-reconnect) + (erc-server-reconnect-timeout 30) + + ;; Insert a newline when I hit at the prompt, and prefer + ;; something more deliberate for actually sending messages. + :bind (:map erc-mode-map + ("RET" . nil) + ("C-c C-c" . #'erc-send-current-line)) + + ;; Emphasize buttonized text in notices. + :custom-face (erc-notice-face ((t (:slant italic :weight unspecified))))) + +(use-package erc-sasl + ;; Since my account name is the same as my nick, free me from having + ;; to hit C-u before M-x erc to trigger a username prompt. + :custom (erc-sasl-user :nick)) + +(use-package erc-join + ;; Join #emacs and #erc whenever I connect to Libera.Chat. + :custom (erc-autojoin-channels-alist '((Libera.Chat "#emacs" "#erc")))) + +(use-package erc-fill + :custom + ;; Prefer one message per line without continuation indicators. + (erc-fill-function #'erc-fill-wrap) + (erc-fill-static-center 18) + + :bind (:map erc-fill-wrap-mode-map ("C-c =" . #'erc-fill-wrap-nudge))) + +(use-package erc-track + ;; Prevent JOINs and PARTs from lighting up the mode-line. + :config (setopt erc-track-faces-priority-list + (remq 'erc-notice-face erc-track-faces-priority-list)) + + :custom (erc-track-priority-faces-only 'all)) + +(use-package erc-goodies + ;; Turn on read indicators when joining channels. + :hook (erc-join . my-erc-enable-read-indicator-on-join)) + +(defvar my-erc-read-indicator-channels '("#emacs") + "Channels in which to show a `keep-place-indicator'.") + +(defun my-erc-enable-read-indicator-on-join () + "Enable read indicators for certain queries or channels." + (when (member (erc-default-target) my-erc-read-indicator-channels) + (erc-keep-place-indicator-mode +1))) + +;; Handy commands from the Emacs Wiki. +(defun erc-cmd-TRACK (&optional target) + "Start tracking TARGET or that of current buffer." + (setq erc-track-exclude (delete (or target (erc-default-target)) + erc-track-exclude))) + +(defun erc-cmd-UNTRACK (&optional target) + "Stop tracking TARGET or that of current buffer." + (setq erc-track-exclude (cl-pushnew (or target (erc-default-target)) + erc-track-exclude + :test #'equal))) + +@end lisp + +@noindent +Those familiar with @code{use-package} may have noticed the lack of +@code{:defer} keyword args. This was done to conserve space, but you +can just pretend that this user has enabled +@code{use-package-always-defer} elsewhere. + +@anchor{Sample configuration via Customize} +@subheading Via Customize +@cindex configuration, via customize + +As mentioned, Customize users can accomplish nearly all of the above +via the Customize interface. Start by running @kbd{M-x +customize-group @key{RET} erc @key{RET}}, and search for ``Modules'' +with @kbd{C-s modules @key{RET}}. Toggle open the flyout menu to +reveal the full ``widget'' panel, a web-form-like interface for ``Erc +Modules''. Tick the boxes for @samp{bufbar}, @samp{irccontrols}, +@samp{nickbar}, @samp{nicks}, @samp{sasl}, and @samp{scrolltobottom}. + +Next, search for the phrases ``Erc Ask About Multiline Input'', ``Erc +Inhibit Mulitline Input'', and ``Erc Send Whitespace Lines''. These +are the print names of three Boolean options that control how ERC +treats prompt input containing line breaks. When visiting each +option's section, twirl open its triangle icon to reveal its widget +UI, and click its @samp{[Toggle]} button to set its value to @code{t}. +While going about this, you may find it helpful to glance at the +descriptions just in case you want to disable them later. When +finished, hit @kbd{C-x C-s} or click @samp{[Apply and Save]} atop the +buffer. + +Now do the same for another couple options, this time having to do +with automatic reconnection. But instead of searching for their print +names, try running @kbd{M-x customize-option @key{RET} @samp{