diff options
| author | F. Jason Park | 2021-10-07 14:26:36 +0200 |
|---|---|---|
| committer | F. Jason Park | 2023-11-24 13:38:52 -0800 |
| commit | 2ed9c9f1b3230bb99b60646fe1cf46664453f693 (patch) | |
| tree | 00fbb23f7283648d87e598bd6d98cec51f3629ab /lisp/erc | |
| parent | 7cbe6ae7124cade32bce1268212e2279dcb6df20 (diff) | |
| download | emacs-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.el | 20 | ||||
| -rw-r--r-- | lisp/erc/erc.el | 125 |
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. | ||
| 464 | For convenience, ensure function wrappers return \"\" as a | ||
| 465 | fallback." | ||
| 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'. | ||
| 771 | ERC 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 | |||
| 787 | To 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 | |||
| 794 | Please remember that ERC ignores this option completely unless | ||
| 795 | the \"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 | |||
| 805 | See 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. | ||
| 8386 | Currently 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. | ||
| 8430 | With NO-QUERY-P, return nil instead of user modes in query | ||
| 8431 | buffers. 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 |