From 1d7e1b82fa36746b5a1ff8d5c9376a4a93ffc090 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Mon, 10 Apr 2023 17:58:05 -0700 Subject: [PATCH 3/4] [5.6] Extend erc-interactive-display to cover /JOINs * lisp/erc/erc.el (erc-display): Mention that buffer-related display options live in the customization group `erc-buffers'. (erc-buffer-display, erc-join-buffer): Swap alias and aliased so that the favored name, `erc-buffer-display', appears in the definition and in the Customize menu. Also note related buffer-display options in the doc string. Remove redundant `t' from list of values. (erc-query-display, erc-interactive-display): Make the former an alias for the latter because their roles were functionally redundant and thus confusing. Inherit the default value from `erc-query-display' because users are more familiar with the pop-up window behavior than a single-window replacement. (erc-reconnect-display): Use preferred name for cross-referencing fallback option `erc-buffer-display' in doc string and explain how /reconnect handling differs. (erc--called-as-input-p): New variable for "slash" commands, like `erc-cmd-FOO', to detect whether they're being called "interactively" as a result of input given at ERC's prompt. (erc-process-input-line): Bind `erc--called-as-input-p' when running slash commands. (erc-cmd-JOIN): When called interactively, schedule a callback to wrap the response handler and control how new buffers are thus displayed. (erc-query): Fix deprecation message. (erc-auto-query, erc-receive-query-display): Swap alias and aliased so the preferred name appears in customization buffers. Mention the nonstandard meaning of nil for this option. * test/lisp/erc/erc-scenarios-base-buffer-display.el: (erc-scenarios-base-buffer-display--interactive-default): New test. * test/lisp/erc/erc-tests.el (erc-process-input-line, erc-select-read-args, erc-tls, erc--interactive): Change expected default value of `erc-interactive-display' from `buffer' to `window'. (Bug#62833) --- etc/ERC-NEWS | 17 ++-- lisp/erc/erc.el | 99 +++++++++++-------- .../erc/erc-scenarios-base-buffer-display.el | 37 +++++++ test/lisp/erc/erc-tests.el | 13 +-- 4 files changed, 110 insertions(+), 56 deletions(-) diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index 31f40e9d0d3..e9de48b2e34 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -37,15 +37,18 @@ decade overdue, this is no longer the case. Other UX improvements in this area aim to make the process of connecting interactively slightly more streamlined and less repetitive, even for veteran users. -** New buffer-display option 'erc-interactive-display'. +** Revised buffer-display handling for interactive commands. A point of friction for new users and one only just introduced with ERC 5.5 has been the lack of visual feedback when first connecting via -M-x erc. As explained below in the news for 5.5, the discovery of a -security issue led to new ERC buffers being "buried" on creation. On -further reflection, this was judged to have been an overcorrection in -the case of interactive invocations, hence the new option -'erc-interactive-display', which is set to 'buffer' (i.e., "take me -there") by default. Accompanying this addition are "display"-suffixed +M-x erc or when issuing a "/JOIN" command at the prompt. As explained +below, in the news for 5.5, the discovery of a security issue led to +most new ERC buffers being "buried" on creation. On further +reflection, this was judged to have been an overcorrection in the case +of interactive invocations, hence the borrowing of an old option, +'erc-query-display', and the bestowing of a new alias, +'erc-interactive-display', which better describes its expanded role as +a more general buffer-display knob for interactive commands ("/QUERY" +still among them). Accompanying this addition are "display"-suffixed aliases for related options 'erc-join-buffer' and 'erc-auto-query', which users have reported as being difficult to discover and remember. diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index b38ef38e9f7..5f1aaaafe49 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -98,7 +98,9 @@ erc-buffers :group 'erc) (defgroup erc-display nil - "Settings for how various things are displayed." + "Settings controlling how various things are displayed. +See the customization group `erc-buffers' for display options +concerning buffers." :group 'erc) (defgroup erc-mode-line-and-header nil @@ -1507,9 +1509,9 @@ erc-default-port-tls "IRC port to use for encrypted connections if it cannot be \ detected otherwise.") -(defvaralias 'erc-buffer-display 'erc-join-buffer) -(defcustom erc-join-buffer 'bury - "Determines how to display a newly created IRC buffer. +(defvaralias 'erc-join-buffer 'erc-buffer-display) +(defcustom erc-buffer-display 'bury + "How to display a newly created or reassociated ERC buffer. The available choices are: @@ -1518,23 +1520,29 @@ erc-join-buffer `frame' - in another frame, `bury' - bury it in a new buffer, `buffer' - in place of the current buffer, - any other value - in place of the current buffer." + +See related options `erc-interactive-display' and +`erc-reconnect-display' as well as `erc-receive-query-display', +which resides in the customization group `erc-query'." :package-version '(ERC . "5.5") :group 'erc-buffers :type '(choice (const :tag "Split window and select" window) (const :tag "Split window, don't select" window-noselect) (const :tag "New frame" frame) (const :tag "Bury in new buffer" bury) - (const :tag "Use current buffer" buffer) - (const :tag "Use current buffer" t))) + (const :tag "Use current buffer" buffer))) -(defcustom erc-interactive-display 'buffer - "How and whether to display server buffers for M-x erc. -See `erc-buffer-display' and friends for a description of -possible values." +(defvaralias 'erc-query-display 'erc-interactive-display) +(defcustom erc-interactive-display 'window + "How to display buffers as a result of user interaction. +This affects commands like /QUERY and /JOIN when issued +interactively at the prompt. It does not apply when calling a +handler for such a command, like `erc-cmd-JOIN', from lisp code. +See `erc-buffer-display' for a full description of available +values." :package-version '(ERC . "5.6") ; FIXME sync on release :group 'erc-buffers - :type '(choice (const :tag "Use value of `erc-join-buffer'" nil) + :type '(choice (const :tag "Use value of `erc-buffer-display'" nil) (const :tag "Split window and select" window) (const :tag "Split window, don't select" window-noselect) (const :tag "New frame" frame) @@ -1542,12 +1550,11 @@ erc-interactive-display (const :tag "Use current buffer" buffer))) (defcustom erc-reconnect-display nil - "How (and whether) to display a channel buffer upon reconnecting. - -This only affects automatic reconnections and is ignored when -issuing a /reconnect command or reinvoking `erc-tls' with the -same args (assuming success, of course). See `erc-join-buffer' -for a description of possible values." + "How and whether to display a channel buffer when auto-reconnecting. +This only affects automatic reconnections and is ignored, like +all other buffer-display options, when issuing a /RECONNECT or +successfully reinvoking `erc-tls' with similar arguments. See +`erc-buffer-display' for a description of possible values." :package-version '(ERC . "5.5") :group 'erc-buffers :type '(choice (const :tag "Use value of `erc-join-buffer'" nil) @@ -3057,6 +3064,10 @@ erc-message-type-member (let ((prop-val (erc-get-parsed-vector position))) (and prop-val (member (erc-response.command prop-val) list)))) +(defvar erc--called-as-input-p nil + "Non-nil when a user types a \"/slash\" command. +Remains bound until `erc-cmd-SLASH' returns.") + (defvar-local erc-send-input-line-function 'erc-send-input-line "Function for sending lines lacking a leading user command. When a line typed into a buffer contains an explicit command, like /msg, @@ -3110,7 +3121,8 @@ erc-process-input-line (if (and command-list (not no-command)) (let* ((cmd (nth 0 command-list)) - (args (nth 1 command-list))) + (args (nth 1 command-list)) + (erc--called-as-input-p t)) (condition-case nil (if (listp args) (apply cmd args) @@ -3584,6 +3596,21 @@ erc-cmd-JOIN (erc-get-channel-user (erc-current-nick))))) (switch-to-buffer existing) (setq erc--server-last-reconnect-count 0) + (when-let* ; bind `erc-join-buffer' when /JOIN issued + ((erc--called-as-input-p) + (fn (lambda (proc parsed) + (when-let* ; `fn' wrapper already removed from hook + (((equal (car (erc-response.command-args parsed)) + channel)) + (sn (erc-extract-nick (erc-response.sender parsed))) + ((erc-nick-equal-p sn (erc-current-nick))) + (erc-join-buffer (or erc-interactive-display + erc-join-buffer))) + (run-hook-with-args-until-success + 'erc-server-JOIN-functions proc parsed) + t)))) + (erc-with-server-buffer + (erc-once-with-server-event "JOIN" fn))) (erc-server-join-channel nil chnl key)))) t) @@ -3947,23 +3974,6 @@ erc-cmd-QUOTE (t nil))) (put 'erc-cmd-QUOTE 'do-not-parse-args t) -(defcustom erc-query-display 'window - "How to display query buffers when using the /QUERY command to talk to someone. - -The default behavior is to display the message in a new window -and bring it to the front. See the documentation for -`erc-join-buffer' for a description of the available choices. - -See also `erc-auto-query' to decide how private messages from -other people should be displayed." - :group 'erc-query - :type '(choice (const :tag "Split window and select" window) - (const :tag "Split window, don't select" window-noselect) - (const :tag "New frame" frame) - (const :tag "Bury in new buffer" bury) - (const :tag "Use current buffer" buffer) - (const :tag "Use current buffer" t))) - (defun erc-cmd-QUERY (&optional user) "Open a query with USER. How the query is displayed (in a new window, frame, etc.) depends @@ -4722,29 +4732,32 @@ erc-query "Open a query buffer on TARGET using SERVER-BUFFER. To change how this query window is displayed, use `let' to bind `erc-join-buffer' before calling this." - (declare (obsolete "bind `erc-cmd-query' and call `erc-cmd-QUERY'" "29.1")) + (declare (obsolete "call `erc-open' in a live server buffer" "29.1")) (unless (buffer-live-p server-buffer) (error "Couldn't switch to server buffer")) (with-current-buffer server-buffer (erc--open-target target))) -(defvaralias 'erc-receive-query-display 'erc-auto-query) -(defcustom erc-auto-query 'window-noselect - "If non-nil, create a query buffer each time you receive a private message. +(defvaralias 'erc-auto-query 'erc-receive-query-display) +(defcustom erc-receive-query-display 'window-noselect + "How to display a query buffer when you receive a private message. If the buffer doesn't already exist, it is created. This can be set to a symbol, to control how the new query window should appear. The default behavior is to display the buffer in a new window, but not to select it. See the documentation for -`erc-join-buffer' for a description of the available choices." +`erc-buffer-display' for a description of available values. Note +that setting this option to nil forgoes buffer creation entirely. +It does not mean \"fall back on `erc-buffer-display'\", like it +does for buffer-display options, like `erc-interactive-display', +that reside in the customization group `erc-buffers'." :group 'erc-query :type '(choice (const :tag "Don't create query window" nil) (const :tag "Split window and select" window) (const :tag "Split window, don't select" window-noselect) (const :tag "New frame" frame) (const :tag "Bury in new buffer" bury) - (const :tag "Use current buffer" buffer) - (const :tag "Use current buffer" t))) + (const :tag "Use current buffer" buffer))) (defcustom erc-query-on-unjoined-chan-privmsg t "If non-nil create query buffer on receiving any PRIVMSG at all. diff --git a/test/lisp/erc/erc-scenarios-base-buffer-display.el b/test/lisp/erc/erc-scenarios-base-buffer-display.el index d511c8ff738..3ed7a83653e 100644 --- a/test/lisp/erc/erc-scenarios-base-buffer-display.el +++ b/test/lisp/erc/erc-scenarios-base-buffer-display.el @@ -118,4 +118,41 @@ erc-scenarios-base-reconnect-options--default (should (eq (window-buffer) (messages-buffer)))))) + +;; This shows that the option `erc-interactive-display' overrides +;; `erc-join-buffer' during cold opens and interactive /JOINs. + +(ert-deftest erc-scenarios-base-buffer-display--interactive-default () + :tags '(:expensive-test) + (should (eq erc-join-buffer 'bury)) + (should (eq erc-interactive-display 'window)) + + (erc-scenarios-common-with-cleanup + ((erc-scenarios-common-dialog "join/legacy") + (dumb-server (erc-d-run "localhost" t 'foonet)) + (port (process-contact dumb-server :service)) + (url (format "tester:changeme@127.0.0.1:%d\r\r" port)) + (expect (erc-d-t-make-expecter)) + (erc-server-flood-penalty 0.1) + (erc-server-auto-reconnect t) + (erc-user-full-name "tester")) + + (ert-info ("Connect to foonet") + (with-current-buffer (let (inhibit-interaction) + (ert-simulate-keys url + (call-interactively #'erc))) + (should (string= (buffer-name) (format "127.0.0.1:%d" port))) + + (erc-d-t-wait-for 10 "Server buffer shown" + (eq (window-buffer) (current-buffer))) + (funcall expect 10 "debug mode") + (erc-scenarios-common-say "/JOIN #chan"))) + + (ert-info ("Wait for output in #chan") + (with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan")) + (funcall expect 10 "welcome") + (erc-d-t-ensure-for 3 "Channel #chan shown" + (eq (window-buffer) (current-buffer))) + (funcall expect 10 "be prosperous"))))) + ;;; erc-scenarios-base-buffer-display.el ends here diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 29bda7e742d..88b9babf206 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -1292,6 +1292,7 @@ erc-process-input-line (cl-letf (((symbol-function 'erc-cmd-MSG) (lambda (line) (push line calls) + (should erc--called-as-input-p) (funcall orig-erc-cmd-MSG line))) ((symbol-function 'erc-server-buffer) (lambda () (current-buffer))) @@ -1469,7 +1470,7 @@ erc-select-read-args :nick (user-login-name) '&interactive-env '((erc-server-connect-function . erc-open-tls-stream) - (erc-join-buffer . buffer)))))) + (erc-join-buffer . window)))))) (ert-info ("Switches to TLS when port matches default TLS port") (should (equal (ert-simulate-keys "irc.gnu.org\r6697\r\r\r" @@ -1479,7 +1480,7 @@ erc-select-read-args :nick (user-login-name) '&interactive-env '((erc-server-connect-function . erc-open-tls-stream) - (erc-join-buffer . buffer)))))) + (erc-join-buffer . window)))))) (ert-info ("Switches to TLS when URL is ircs://") (should (equal (ert-simulate-keys "ircs://irc.gnu.org\r\r\r\r" @@ -1489,7 +1490,7 @@ erc-select-read-args :nick (user-login-name) '&interactive-env '((erc-server-connect-function . erc-open-tls-stream) - (erc-join-buffer . buffer)))))) + (erc-join-buffer . window)))))) (setq-local erc-interactive-display nil) ; cheat to save space @@ -1625,7 +1626,7 @@ erc-tls '("localhost" 6667 "nick" "unknown" t "sesame" nil nil nil nil "user" nil))) (should (equal (pop env) - '((erc-join-buffer buffer) + '((erc-join-buffer window) (erc-server-connect-function erc-open-tls-stream))))) (ert-info ("Custom connect function") @@ -1686,7 +1687,7 @@ erc--interactive '("irc.libera.chat" 6697 "tester" "unknown" t nil nil nil nil nil "user" nil))) (should (equal (pop env) - '((erc-join-buffer buffer) (erc-server-connect-function + '((erc-join-buffer window) (erc-server-connect-function erc-open-tls-stream))))) (ert-info ("Nick supplied, decline TLS upgrade") @@ -1696,7 +1697,7 @@ erc--interactive '("irc.libera.chat" 6667 "dummy" "unknown" t nil nil nil nil nil "user" nil))) (should (equal (pop env) - '((erc-join-buffer buffer) + '((erc-join-buffer window) (erc-server-connect-function erc-open-network-stream)))))))) -- 2.39.2