aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/erc
diff options
context:
space:
mode:
authorF. Jason Park2021-10-07 14:26:36 +0200
committerF. Jason Park2023-11-24 13:38:52 -0800
commit2ed9c9f1b3230bb99b60646fe1cf46664453f693 (patch)
tree00fbb23f7283648d87e598bd6d98cec51f3629ab /lisp/erc
parent7cbe6ae7124cade32bce1268212e2279dcb6df20 (diff)
downloademacs-2ed9c9f1b3230bb99b60646fe1cf46664453f693.tar.gz
emacs-2ed9c9f1b3230bb99b60646fe1cf46664453f693.zip
Optionally allow substitution patterns in erc-prompt
* etc/ERC-NEWS: Add entry for `erc-prompt-format'. * lisp/erc/erc-compat.el (erc-compat--defer-format-spec-in-buffer): New macro to wrap `format-spec' specification values in functions that run in the current buffer and fall back to the empty string. * lisp/erc/erc.el (erc-prompt): Add predefined Custom choice for function type in `erc-prompt-format'. (erc--prompt-format-face-example): New "pre-propertized" value for option `erc-prompt-format'. (erc-prompt-format): New companion option for `erc-prompt' choice `erc-prompt-format'. New function of the same name to perform format substitutions and serve as a Custom choice value for `erc-prompt'. Based on work and ideas originally proposed by Stefan Kangas. (erc--away-indicator, erc-away-status-indicator, erc--format-away-indicator): New formatting function and helper variables for displaying short away status. (erc--user-modes-indicator): New variable. (erc--format-user-modes): New function. (erc--format-channel-status-prefix): New function. (erc--format-modes): New function. * test/lisp/erc/erc-scenarios-prompt-format.el: New file. (Bug#51082) Co-authored-by: Stefan Kangas <stefankangas@gmail.com>
Diffstat (limited to 'lisp/erc')
-rw-r--r--lisp/erc/erc-compat.el20
-rw-r--r--lisp/erc/erc.el125
2 files changed, 144 insertions, 1 deletions
diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el
index 4c376cfbc22..e0f6e9b5134 100644
--- a/lisp/erc/erc-compat.el
+++ b/lisp/erc/erc-compat.el
@@ -459,6 +459,26 @@ If START or END is negative, it counts from the end."
459 '(let (current-time-list) (current-time)) 459 '(let (current-time-list) (current-time))
460 '(current-time))) 460 '(current-time)))
461 461
462(defmacro erc-compat--defer-format-spec-in-buffer (&rest spec)
463 "Transform SPEC forms into functions that run in the current buffer.
464For convenience, ensure function wrappers return \"\" as a
465fallback."
466 (cl-check-type (car spec) cons)
467 (let ((buffer (make-symbol "buffer")))
468 `(let ((,buffer (current-buffer)))
469 ,(list '\`
470 (mapcar
471 (pcase-lambda (`(,k . ,v))
472 (cons k
473 (list '\,(if (>= emacs-major-version 29)
474 `(lambda ()
475 (or (if (eq ,buffer (current-buffer))
476 ,v
477 (with-current-buffer ,buffer
478 ,v))
479 ""))
480 `(or ,v "")))))
481 spec)))))
462 482
463(provide 'erc-compat) 483(provide 'erc-compat)
464 484
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 8cd69d1431e..a2f4562d333 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -751,7 +751,74 @@ parameters are not included.")
751(defcustom erc-prompt "ERC>" 751(defcustom erc-prompt "ERC>"
752 "Prompt used by ERC. Trailing whitespace is not required." 752 "Prompt used by ERC. Trailing whitespace is not required."
753 :group 'erc-display 753 :group 'erc-display
754 :type '(choice string function)) 754 :type '(choice string
755 (function-item :tag "Interpret format specifiers"
756 erc-prompt-format)
757 function))
758
759(defvar erc--prompt-format-face-example
760 #("%p%m%a\u00b7%b>"
761 0 2 (font-lock-face erc-my-nick-prefix-face)
762 2 4 (font-lock-face font-lock-keyword-face)
763 4 6 (font-lock-face erc-error-face)
764 6 7 (font-lock-face shadow)
765 7 9 (font-lock-face font-lock-constant-face)
766 9 10 (font-lock-face shadow))
767 "An example value for option `erc-prompt-format' with faces.")
768
769(defcustom erc-prompt-format erc--prompt-format-face-example
770 "Format string when `erc-prompt' is `erc-prompt-format'.
771ERC recognizes these substitution specifiers:
772
773 %a - away indicator
774 %b - buffer name
775 %t - channel or query target, server domain, or dialed address
776 %S - target@network or buffer name
777 %s - target@server or server
778 %N - current network, like Libera.Chat
779 %p - channel membership prefix, like @ or +
780 %n - current nickname
781 %c - channel modes with args for select modes
782 %C - channel modes with all args
783 %u - user modes
784 %m - channel modes sans args in channels, user modes elsewhere
785 %M - like %m but show nothing in query buffers
786
787To pick your own colors, do something like:
788
789 (setopt erc-prompt-format
790 (concat
791 (propertize \"%b\" \\='font-lock-face \\='erc-input-face)
792 (propertize \"%a\" \\='font-lock-face \\='erc-error-face)))
793
794Please remember that ERC ignores this option completely unless
795the \"parent\" option `erc-prompt' is set to `erc-prompt-format'."
796 :package-version '(ERC . "5.6")
797 :group 'erc-display
798 :type `(choice (const :tag "{Prefix}{Mode}{Away}{MIDDLE DOT}{Buffer}>"
799 ,erc--prompt-format-face-example)
800 string))
801
802(defun erc-prompt-format ()
803 "Make predefined `format-spec' substitutions.
804
805See option `erc-prompt-format' and option `erc-prompt'."
806 (format-spec erc-prompt-format
807 (erc-compat--defer-format-spec-in-buffer
808 (?C erc--channel-modes 3 ",")
809 (?M erc--format-modes 'no-query-p)
810 (?N erc-format-network)
811 (?S erc-format-target-and/or-network)
812 (?a erc--format-away-indicator)
813 (?b buffer-name)
814 (?c erc-format-channel-modes)
815 (?m erc--format-modes)
816 (?n erc-current-nick)
817 (?p erc--format-channel-status-prefix)
818 (?s erc-format-target-and/or-server)
819 (?t erc-format-target)
820 (?u erc--format-user-modes))
821 'ignore-missing)) ; formerly `only-present'
755 822
756(defun erc-prompt () 823(defun erc-prompt ()
757 "Return the input prompt as a string. 824 "Return the input prompt as a string.
@@ -8311,6 +8378,62 @@ shortened server name instead."
8311 (format-time-string erc-mode-line-away-status-format a) 8378 (format-time-string erc-mode-line-away-status-format a)
8312 ""))) 8379 "")))
8313 8380
8381(defvar-local erc--away-indicator nil
8382 "Cons containing an away indicator for the connection.")
8383
8384(defvar erc-away-status-indicator "A"
8385 "String shown by various formatting facilities to indicate away status.
8386Currently only used by the option `erc-prompt-format'.")
8387
8388(defun erc--format-away-indicator ()
8389 "Return char with `display' property of `erc--away-indicator'."
8390 (and-let* ((indicator (erc-with-server-buffer
8391 (or erc--away-indicator
8392 (setq erc--away-indicator (list "")))))
8393 (newcar (if (erc-away-time) erc-away-status-indicator "")))
8394 ;; Inform other buffers of the change when necessary.
8395 (let ((dispp (not erc--inhibit-prompt-display-property-p)))
8396 (unless (eq newcar (car indicator))
8397 (erc--refresh-prompt-continue (and dispp 'hooks-only-p))
8398 (setcar indicator newcar))
8399 (if dispp
8400 (propertize "(away?)" 'display indicator)
8401 newcar))))
8402
8403(defvar-local erc--user-modes-indicator nil
8404 "Cons containing connection-wide indicator for user modes.")
8405
8406;; If adding more of these functions, should factor out commonalities.
8407;; As of ERC 5.6, this is identical to the away variant aside from
8408;; the var names and `eq', which isn't important.
8409(defun erc--format-user-modes ()
8410 "Return server's user modes as a string"
8411 (and-let* ((indicator (erc-with-server-buffer
8412 (or erc--user-modes-indicator
8413 (setq erc--user-modes-indicator (list "")))))
8414 (newcar (erc--user-modes 'string)))
8415 (let ((dispp (not erc--inhibit-prompt-display-property-p)))
8416 (unless (string= newcar (car indicator))
8417 (erc--refresh-prompt-continue (and dispp 'hooks-only-p))
8418 (setcar indicator newcar))
8419 (if dispp
8420 (propertize "(user-modes?)" 'display indicator)
8421 newcar))))
8422
8423(defun erc--format-channel-status-prefix ()
8424 "Return the current channel membership prefix."
8425 (and (erc--target-channel-p erc--target)
8426 (erc-get-user-mode-prefix (erc-current-nick))))
8427
8428(defun erc--format-modes (&optional no-query-p)
8429 "Return a string of channel modes in channels and user modes elsewhere.
8430With NO-QUERY-P, return nil instead of user modes in query
8431buffers. Also return nil when mode information is unavailable."
8432 (cond ((erc--target-channel-p erc--target)
8433 (erc--channel-modes 'string))
8434 ((not (and erc--target no-query-p))
8435 (erc--format-user-modes))))
8436
8314(defun erc-format-channel-modes () 8437(defun erc-format-channel-modes ()
8315 "Return the current channel's modes." 8438 "Return the current channel's modes."
8316 (concat (apply #'concat 8439 (concat (apply #'concat