From 96b62219e43df0585ddfbabaa904342ca0385d22 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Fri, 10 Nov 2023 16:28:33 -0800 Subject: [PATCH 0/6] *** NOT A PATCH *** *** BLURB HERE *** F. Jason Park (6): [5.6] Make ERC error-notice formatting more consistent [5.6] Make ERC's message-sending functions more flexible [5.6] Simplify logic for inserting ERC prompt input [5.6] Slightly simplify text props on echoed ERC input [5.6] Don't output non-modules in erc-modes [5.6] Revive erc-display-command as module command-indicator etc/ERC-NEWS | 15 ++++ lisp/erc/erc-backend.el | 16 ++-- lisp/erc/erc-goodies.el | 113 +++++++++++++++++++++-- lisp/erc/erc-match.el | 14 +-- lisp/erc/erc.el | 177 +++++++++++++++++++++---------------- test/lisp/erc/erc-tests.el | 5 +- 6 files changed, 238 insertions(+), 102 deletions(-) Interdiff: diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index f59023eae62..49b623aa7f0 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -157,6 +157,21 @@ asking users who've customized this option to switch to that some other solution, like automatic migration, is justified, please make that known on the bug list. +** Module 'noncommands' deprecated, replaced by 'command-indicator'. +Command-line echoing has returned to ERC after a near-decade-long +hiatus. This means you can elect to have ERC leave a trail of most +slash-command input submitted at the prompt, in a manner resembling a +shell or a REPL. The particulars are likely of little interest to +most users, but the gist is that this functionality was removed in +5.3.x (Emacs 24.5) under mysterious circumstances, without mention in +this document or any change log. Everything's mostly been restored, +except that the feature is now opt-in. (Add 'command-indicator' to +'erc-modules' to get started.) The only real gotcha is that related +faces and options, like 'erc-command-indicator', have moved to the +'erc-goodies' library, although their Custom groups remain the same. +Hint: once enabled, use 'erc-command-indicator-toggle-hidden' to +dynamically toggle echoed command-line visibility. + ** 'erc-button-alist' and 'erc-nick-popup-alist' have evolved slightly. It's no secret that the 'buttons' module treats potential nicknames specially. This is perhaps most evident in its treatment of the diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el index 4cc81dd9378..93b76c544aa 100644 --- a/lisp/erc/erc-goodies.el +++ b/lisp/erc/erc-goodies.el @@ -471,21 +471,26 @@ erc-noncommands-list erc-cmd-COUNTRY erc-cmd-SV erc-cmd-SM - erc-cmd-SMV + erc-cmd-SAY erc-cmd-LASTLOG) - "List of commands that are aliases for CTCP ACTION or for ERC messages. - -If a command's function symbol is in this list, the typed command -does not appear in the ERC buffer after the user presses ENTER.") + "List of commands that perform their own buffer I/O. +The `command-indicator' module forgoes echoing commands in this +list.") ;;;###autoload(autoload 'erc-noncommands-mode "erc-goodies" nil t) (define-erc-module noncommands nil - "This mode distinguishes non-commands. -Commands listed in `erc-insert-this' know how to display -themselves." + "Treat commands that display themselves specially. +This module has been a no-op since ERC 5.3 and has likely only +ever made sense in the context of `erc-command-indicator'. It +was deprecated in ERC 5.6." ((add-hook 'erc--input-review-functions #'erc-send-distinguish-noncommands)) ((remove-hook 'erc--input-review-functions #'erc-send-distinguish-noncommands))) +(make-obsolete-variable 'erc-noncommand-mode + 'erc-command-indicator-mode "30.1") +(make-obsolete 'erc-noncommand-mode 'erc-command-indicator-mode "30.1") +(make-obsolete 'erc-noncommand-enable 'erc-command-indicator-enable "30.1") +(make-obsolete 'erc-noncommand-disable 'erc-command-indicator-disable "30.1") (defun erc-send-distinguish-noncommands (state) "If STR is an ERC non-command, set `insertp' in STATE to nil." @@ -499,6 +504,98 @@ erc-send-distinguish-noncommands ;; Inhibit sending this string. (setf (erc-input-insertp state) nil)))) + +;;; Command-indicator + +(defface erc-command-indicator-face + '((t :inherit (shadow fixed-pitch-serif))) + "Face for echoed command lines, including the prompt. +See option `erc-command-indicator'." + :package-version '(ERC . "5.6") + :group 'erc-faces) + +(defcustom erc-command-indicator "$>" + "Pseudo prompt for echoed command lines. +An analog of the option `erc-prompt' that replaces the \"speaker +label\" for echoed \"slash\" commands submitted at the prompt. A +value of nil means ERC only inserts the command line portion, +sans pseudo prompt, which may trick certain modules into treating +the slash command itself as the message's \"speaker\"." + :package-version '(ERC . "5.6") + :group 'erc-display + :type '(choice (const "$>") (const nil) string function)) + +;;;###autoload(autoload 'erc-command-indicator-mode "erc-goodies" nil t) +(define-erc-module command-indicator nil + "Echo command lines for \"slash commands,\" like /JOIN, /HELP, etc. +Skip those appearing in `erc-noncommands-list'. + +Users can run \\[erc-command-indicator-toggle-hidden] to hide and +reveal echoed command lines after they've been inserted." + ((add-hook 'erc--input-review-functions + #'erc--command-indicator-permit-insertion 90 t) + (erc-command-indicator-toggle-hidden -1)) + ((remove-hook 'erc--input-review-functions + #'erc--command-indicator-permit-insertion t) + (erc-command-indicator-toggle-hidden +1)) + 'local) + +(defun erc-command-indicator () + "Return the command-indicator prompt as a string. +Do nothing if the variable `erc-command-indicator' is nil." + (and erc-command-indicator + (let ((prompt (if (functionp erc-command-indicator) + (funcall erc-command-indicator) + erc-command-indicator))) + (concat prompt (and (not (string-empty-p prompt)) " "))))) + +(defun erc-command-indicator-toggle-hidden (arg) + "Toggle whether echoed \"slash commands\" are visible." + (interactive "P") + (erc--toggle-hidden 'command-indicator arg)) + +(defun erc--command-indicator-permit-insertion (state) + "Insert `erc-input' STATE's message if it's an echoed command." + (cl-assert erc-command-indicator-mode) + (when (erc--input-split-cmdp state) + (setf (erc--input-split-insertp state) #'erc--command-indicator-display) + (erc-send-distinguish-noncommands state))) + +;; That function used to be called `erc-display-command'. It was +;; neutered in ERC 5.3.x (Emacs 24.5), commented out in 5.4, removed +;; in 5.5, and restored in 5.6. +(defun erc--command-indicator-display (line) + "Insert command LINE as echoed input resembling that of REPLs and shells." + (when erc-insert-this + (save-excursion + (erc--assert-input-bounds) + (let ((insert-position (marker-position (goto-char erc-insert-marker))) + (erc--msg-props (or erc--msg-props + (let ((ovs erc--msg-prop-overrides)) + (map-into `((erc-msg . slash-cmd) + ,@(reverse ovs)) + 'hash-table))))) + (when-let ((string (erc-command-indicator)) + (erc-input-marker (copy-marker erc-input-marker))) + (erc-display-prompt nil nil string 'erc-command-indicator-face) + (set-marker erc-input-marker nil)) + (let ((beg (point))) + (insert line) + (erc-put-text-property beg (point) + 'font-lock-face 'erc-command-indicator-face) + (insert "\n")) + (save-restriction + (narrow-to-region insert-position (point)) + (run-hooks 'erc-send-modify-hook) + (run-hooks 'erc-send-post-hook) + (cl-assert (> (- (point-max) (point-min)) 1)) + (erc--hide-message 'command-indicator) + (add-text-properties (point-min) (1+ (point-min)) + (erc--order-text-properties-from-hash + erc--msg-props)))) + (erc--refresh-prompt)))) + + ;;; IRC control character processing. (defgroup erc-control-characters nil "Dealing with control characters." diff --git a/lisp/erc/erc-match.el b/lisp/erc/erc-match.el index 8644e61106f..6fff54d3cf4 100644 --- a/lisp/erc/erc-match.el +++ b/lisp/erc/erc-match.el @@ -695,19 +695,7 @@ erc-match-toggle-hidden-fools Expect the function `erc-hide-fools' or similar to be present in `erc-text-matched-hook'." (interactive "P") - (erc-match--toggle-hidden 'match-fools arg)) - -(defun erc-match--toggle-hidden (prop arg) - "Toggle invisibility for spec member PROP. -Treat ARG in a manner similar to mode toggles defined by -`define-minor-mode'." - (when arg - (setq arg (prefix-numeric-value arg))) - (if (memq prop (ensure-list buffer-invisibility-spec)) - (unless (natnump arg) - (remove-from-invisibility-spec prop)) - (when (or (not arg) (natnump arg)) - (add-to-invisibility-spec prop)))) + (erc--toggle-hidden 'match-fools arg)) (provide 'erc-match) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 00ee97b7e14..89b3397d8f1 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -346,8 +346,13 @@ erc-hide-prompt "If non-nil, hide input prompt upon disconnecting. To unhide, type something in the input area. Once revealed, a prompt remains unhidden until the next disconnection. Channel -prompts are unhidden upon rejoining. See -`erc-unhide-query-prompt' for behavior concerning query prompts." +prompts are unhidden upon rejoining. For behavior concerning +query prompts, see `erc-unhide-query-prompt'. Longtime ERC users +should note that this option was repurposed in ERC 5.5 because it +had lain dormant for years after being sidelined in 5.3 when its +only use in the interactive client was removed. Before then, its +role was controlling whether `erc-command-indicator' would appear +alongside echoed slash-command lines." :package-version '(ERC . "5.5") :group 'erc-display :type '(choice (const :tag "Always hide prompt" t) @@ -759,28 +764,6 @@ erc-prompt (concat prompt " ") prompt))) -(defcustom erc-command-indicator nil - "Indicator used by ERC for showing commands. - -If non-nil, this will be used in the ERC buffer to indicate -commands (i.e., input starting with a `/'). - -If nil, the prompt will be constructed from the variable `erc-prompt'." - :group 'erc-display - :type '(choice (const nil) string function)) - -(defun erc-command-indicator () - "Return the command indicator prompt as a string. - -This only has any meaning if the variable `erc-command-indicator' is non-nil." - (and erc-command-indicator - (let ((prompt (if (functionp erc-command-indicator) - (funcall erc-command-indicator) - erc-command-indicator))) - (if (> (length prompt) 0) - (concat prompt " ") - prompt)))) - (defcustom erc-notice-prefix "*** " "Prefix for all notices." :group 'erc-display @@ -1364,12 +1347,6 @@ erc-prompt-face "ERC face for the prompt." :group 'erc-faces) -(defface erc-command-indicator-face - '((t :weight bold)) - "ERC face for the command indicator. -See the variable `erc-command-indicator'." - :group 'erc-faces) - (defface erc-notice-face '((default :weight bold) (((class color) (min-colors 88) (supports :weight semi-bold)) @@ -2077,7 +2054,7 @@ erc--sort-modules (defcustom erc-modules '( autojoin button completion fill imenu irccontrols list match menu move-to-prompt netsplit - networks noncommands readonly ring stamp track) + networks readonly ring stamp track) "A list of modules which ERC should enable. If you set the value of this without using `customize' remember to call \(erc-update-modules) after you change it. When using `customize', modules @@ -2127,6 +2104,7 @@ erc-modules (const :tag "button: Buttonize URLs, nicknames, and other text" button) (const :tag "capab: Mark unidentified users on servers supporting CAPAB" capab-identify) + (const :tag "command-indicator: Echo command lines." command-indicator) (const :tag "completion: Complete nicknames and commands (programmable)" completion) (const :tag "dcc: Provide Direct Client-to-Client support" dcc) @@ -2146,7 +2124,7 @@ erc-modules (const :tag "networks: Provide data about IRC networks" networks) (const :tag "nickbar: Show nicknames in a dyamic side window" nickbar) (const :tag "nicks: Uniquely colorize nicknames in target buffers" nicks) - (const :tag "noncommands: Don't display non-IRC commands after evaluation" + (const :tag "noncommands: Deprecated. See module `command-indicator'." noncommands) (const :tag "notifications: Desktop alerts on PRIVMSG or mentions" notifications) @@ -3309,6 +3287,18 @@ erc--hide-message (cl-incf beg)) (erc--merge-prop (1- beg) (1- end) 'invisible value))))) +(defun erc--toggle-hidden (prop arg) + "Toggle invisibility for spec member PROP. +Treat ARG in a manner similar to mode toggles defined by +`define-minor-mode'." + (when arg + (setq arg (prefix-numeric-value arg))) + (if (memq prop (ensure-list buffer-invisibility-spec)) + (unless (natnump arg) + (remove-from-invisibility-spec prop)) + (when (or (not arg) (natnump arg)) + (add-to-invisibility-spec prop)))) + (defun erc--delete-inserted-message (beg-or-point &optional end) "Remove message between BEG and END. Expect BEG and END to match bounds as returned by the macro @@ -7016,7 +7006,9 @@ erc--send-input-lines (when (erc--input-split-sendp lines-obj) (dolist (line (erc--input-split-lines lines-obj)) (when (erc--input-split-insertp lines-obj) - (erc-display-msg line)) + (if (functionp (erc--input-split-insertp lines-obj)) + (funcall (erc--input-split-insertp lines-obj) line) + (erc-display-msg line))) (erc-process-input-line (concat line "\n") (null erc-flood-protect) (not (erc--input-split-cmdp lines-obj)))))) @@ -7522,7 +7514,10 @@ erc-load-irc-script-lines user input." (let* ((cb (current-buffer)) (s "") - (sp (or (erc-command-indicator) (erc-prompt))) + (sp (or (and (bound-and-true-p erc-command-indicator-mode) + (fboundp 'erc-command-indicator) + (erc-command-indicator)) + (erc-prompt))) (args (and (boundp 'erc-script-args) erc-script-args))) (if (and args (string-match "^ " args)) (setq args (substring args 1))) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index 2898ca7be75..e7422d330c0 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -2543,7 +2543,8 @@ erc-handle-irc-url (kill-buffer "#chan"))) (defconst erc-tests--modules - '( autoaway autojoin bufbar button capab-identify completion dcc fill identd + '( autoaway autojoin bufbar button capab-identify + command-indicator completion dcc fill identd imenu irccontrols keep-place list log match menu move-to-prompt netsplit networks nickbar nicks noncommands notifications notify page readonly replace ring sasl scrolltobottom services smiley sound -- 2.41.0