]> git.eshelyaron.com Git - emacs.git/commitdiff
Revive erc-command-indicator as new module
authorF. Jason Park <jp@neverwas.me>
Fri, 10 Nov 2023 21:34:31 +0000 (13:34 -0800)
committerF. Jason Park <jp@neverwas.me>
Mon, 13 Nov 2023 04:37:49 +0000 (20:37 -0800)
* doc/misc/erc.texi: Add entry for `command-indicator' to Modules
chapter.
* etc/ERC-NEWS: Mention new module `command-indicator'.
* lisp/erc/erc-goodies.el (erc-noncommands-list): Replace the
nonexistent `erc-cmd-SMV' with function `erc-cmd-SAY'.
(erc-noncommands-mode, erc-noncommands-enable,
erc-noncommands-disable): Deprecate this module because it's a no-op.
(erc-command-indicator-face, erc-command-indicator): Migrate from main
library.
(erc-command-indicator-mode, erc-command-indicator-enable,
erc-command-indicator-disable): New module to take the spiritual place
of `noncommands'.
(erc-command-indicator): Move function here from main library, along
with option namesake mentioned above.
(erc-command-indicator-toggle-hidden): New command to toggle echoed
command-line visibility.
(erc--command-indicator-permit-insertion): New function.
(erc--command-indicator-display): New function, a slightly revised
version of the old `erc-display-command' from the main library.  Its
only call site was removed back in d1036d288de "backport: erc
bugfixes".  However, references were left behind to associated assets,
like `erc-command-indicator', etc.  The function was later commented
out in 0c599ee2e2c "* lisp/erc/erc.el: Use `run-hook-with-args` for
`erc-pre-send-functions`", and then removed by a63ed6f78a6 "Remove
duplicate ERC prompt on reconnect".
* lisp/erc/erc-match.el (erc-match-toggle-hidden-fools): Use new
non-module-specific name for `erc-match--toggle-hidden'.
(erc-match--toggle-hidden): Move to main library for shared use by
other modules.
* lisp/erc/erc.el (erc-hide-prompt): Leave note explaining updated
role.
(erc-command-indicator): Move option and function of same name to
erc-goodies.
(erc-command-indicator-face): Move to erc-goodies.
(erc-modules): Remove module `noncommands' from standard value and
Custom set.  Add `command-indicator' to set.
(erc--toggle-hidden): "New" function, a rebranded version of the
utility `erc-match--toggle-hidden' from erc-match.
(erc--send-input-lines): Accommodate modules wanting alternate
insertion functions.
(erc-load-irc-script-lines): Account for `erc-command-indicator' no
longer being defined in this library.
* test/lisp/erc/erc-scenarios-base-send-message.el
(erc-scenarios-base-send-message--command-indicator): New test.
* test/lisp/erc/erc-tests.el (erc-tests--modules): Remove
deprecated module `noncommands' from manifest.  (Bug#67031)

doc/misc/erc.texi
etc/ERC-NEWS
lisp/erc/erc-goodies.el
lisp/erc/erc-match.el
lisp/erc/erc.el
test/lisp/erc/erc-scenarios-base-send-message.el
test/lisp/erc/erc-tests.el

index 10902eac33fec26b7271c0bc9f344a99423f93c6..44e82084b904b6806606ab219cf698544f11c15f 100644 (file)
@@ -450,6 +450,11 @@ Buttonize URLs, nicknames, and other text
 @item capab-identify
 Mark unidentified users on freenode and other servers supporting CAPAB.
 
+@cindex modules, command-indicator
+@item command-indicator
+Echo command lines for ``slash commands'', like @kbd{/JOIN #erc} and
+@kbd{/HELP join}
+
 @cindex modules, completion
 @cindex modules, pcomplete
 @item completion (aka pcomplete)
index f59023eae6283eac54c3dcc3108a76624b7d6947..cd4a283ef1c4228be90616bc0fa8efab8d4c05a1 100644 (file)
@@ -157,6 +157,19 @@ 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
+that of 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) without mention in this document or a
+change log.  Everything's mostly been restored, except that the
+feature is now opt-in.  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.  Add
+'command-indicator' to 'erc-modules' to get started.
+
 ** '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
index 4cc81dd9378e11df6bb2863755c160e3a68e9569..1482c21e931cbba9e0e906f6628d9b8d99464011 100644 (file)
@@ -471,21 +471,26 @@ For use with `keep-place-indicator' module."
                                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 client \"slash commands\" that perform their own buffer I/O.
+The `command-indicator' module forgoes echoing these commands,
+most of which aren't actual interactive lisp commands.")
 
 ;;;###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,106 @@ themselves."
       ;; Inhibit sending this string.
       (setf (erc-input-insertp state) nil))))
 
+
+;;; Command-indicator
+
+(defface erc-command-indicator-face
+  '((t :inherit (erc-input-face fixed-pitch-serif)))
+  "Face for echoed command lines, including the prompt.
+See option `erc-command-indicator'."
+  :package-version '(ERC . "5.6") ; standard value, from bold
+  :group 'erc-faces)
+
+(defcustom erc-command-indicator 'erc-prompt
+  "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
+alone, without the prompt, which may trick certain modules, like
+`fill', into treating the leading slash command itself as the
+message's speaker."
+  :package-version '(ERC . "5.6")
+  :group 'erc-display
+  :type '(choice (const :tag "Defer to `erc-prompt'" erc-prompt)
+                 (const :tag "Print command lines without a prompt" nil)
+                 (string :tag "User-provided string")
+                 (function :tag "User-provided 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 80 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))
+                             (not (string-suffix-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)))
+
+;; This 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)
+          (remove-text-properties insert-position (point)
+                                  '(field nil erc-prompt nil))
+          (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."
index 8644e61106f842cf124f659aa2db859fd7b52a4a..6fff54d3cf430608a6f05d802169eeb4c2e98c1c 100644 (file)
@@ -695,19 +695,7 @@ This function is meant to be called from `erc-text-matched-hook'."
 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)
 
index 6a110f7ca77a7abe963e96838060be19edeb19c4..cd1c925a75729906e891644f412c1c3ed2fef7b5 100644 (file)
@@ -346,8 +346,13 @@ with a value of 2 and means disallow more than 1 line of input."
   "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 @@ See also the variable `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 @@ This will only be used if `erc-header-line-face-method' is non-nil."
   "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 @@ buffer rather than a server buffer.")
 
 (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 @@ removed from the list will be disabled."
     (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 @@ removed from the list will be disabled."
     (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)
@@ -3328,6 +3306,18 @@ don't bother including the preceding newline."
           (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
@@ -7051,7 +7041,9 @@ queue.  Expect LINES-OBJ to be an `erc--input-split' object."
   (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))))))
@@ -7557,7 +7549,10 @@ sequences, process the lines verbatim.  Use this for multiline
 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)))
index 904381abe6a6f33390f51eb610cb321d891d9210..bf9e0f5ae3a8fbccc2f2204f69af7fddab7afb56 100644 (file)
           (funcall expect 10 "<alice> No, not till Thursday;"))))))
 
 
+;; This asserts that the `command-indicator' module only inserts
+;; prompt-like prefixes for normal slash commands, like /JOIN.
+
+(ert-deftest erc-scenarios-base-send-message--command-indicator ()
+  :tags '(:expensive-test)
+  (erc-scenarios-common-with-cleanup
+      ((erc-scenarios-common-dialog "base/send-message")
+       (erc-server-flood-penalty 0.1)
+       (dumb-server (erc-d-run "localhost" t 'noncommands))
+       (erc-modules `(command-indicator fill-wrap ,@erc-modules))
+       (expect (erc-d-t-make-expecter)))
+
+    (ert-info ("Connect to foonet")
+      (with-current-buffer (erc :server "127.0.0.1"
+                                :port (process-contact dumb-server :service)
+                                :nick "tester"
+                                :full-name "tester")
+        (funcall expect 5 "debug mode")
+        (erc-scenarios-common-say "/join #chan")
+        (funcall expect 10 "ERC> /join #chan")))
+
+    (with-current-buffer (erc-d-t-wait-for 5 (get-buffer "#chan"))
+      (ert-info ("Prompt absent for CTCP ACTION")
+        (funcall expect 10 "<bob> alice: For hands, to do Rome")
+        (erc-scenarios-common-say "/me sad")
+        (funcall expect -0.1 "ERC> /me sad")
+        (funcall expect 10 "* tester sad"))
+
+      (ert-info ("Prompt absent for literal command")
+        (funcall expect 10 "<alice> bob: Spotted, detested")
+        (erc-scenarios-common-say "/say /me sad")
+        (funcall expect -0.1 "ERC> /say /me sad")
+        (funcall expect 10 "<tester> /me sad"))
+
+      (ert-info ("Prompt absent for /SV")
+        (funcall expect 10 "<bob> Marcus, my brother!")
+        (erc-scenarios-common-say "/sv")
+        (funcall expect -0.1 "ERC> /sv")
+        (funcall expect 10 "<tester> I'm using ERC"))
+
+      (ert-info ("Prompt absent module list via /SM")
+        (funcall expect 10 "<bob> alice: You still wrangle")
+        (erc-scenarios-common-say "/sm")
+        (funcall expect -0.1 "ERC> /sm")
+        (funcall expect 10 "<tester> I'm using the following modules: ")
+        (funcall expect 10 "<alice> No, not till Thursday;"))
+
+      (ert-info ("Prompt present for /QUIT in issuing buffer")
+        (erc-scenarios-common-say "/quit")
+        (funcall expect 10 "ERC> /quit"))
+
+      (with-current-buffer "foonet"
+        (funcall expect 10 "ERC finished")))))
+
 ;;; erc-scenarios-base-send-message.el ends here
index 2898ca7be757066cc3efbc56bd1ed0e0fe5de408..e7422d330c0b6eae570cd35417476bda13719760 100644 (file)
     (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