From 1fc18ed7a18fecaa492a831150af0f27696c1c7a Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Sun, 18 Dec 2022 19:01:40 -0800 Subject: [PATCH 1/2] [5.6] Allow ERC modules to extend erc-nick-popup-alist * etc/ERC-NEWS: Mention superficial changes to `erc-nick-popup-alist'. * lisp/erc/erc-button.el (erc-nick-popup-alist): Accept alternate shape for type with strings associated with functions instead of arbitrary sexps. (erc-button-cmd-KICK, erc-button-cmd-MSG): New functions to serve as wrappers for `erc-cmd-KICK' and `erc-cmd-MSG', respectively. The first also fixes a bug in which all but the first token of a given "reason" would be omitted from the ":trailing" portion of an outgoing KICK message. (erc-button--nick-popup-alist): New variable to help built-in modules expose special actions to `erc-nick-popup' without touching `erc-nick-popup-alist'. (erc-nick-popup): Present both `erc--nick-popup-alist' and `erc-nick-popup-alist' to the invoking user. Accommodate functions as well as arbitrary sexps. (bug#63569) --- etc/ERC-NEWS | 18 ++++++++---- lisp/erc/erc-button.el | 64 +++++++++++++++++++++++++++++++----------- 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index e9ec9e2caab..840ac64f963 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -116,13 +116,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. -** The 'nicknames' entry in 'erc-button-alist' is officially exceptional. +** 'erc-button-alist' and 'erc-nick-popup-alist' have evolved slightly. It's no secret that the 'buttons' module treats potential nicknames -specially. To simplify ERC's move to next-gen "rich UI" extensions, -this special treatment is being canonized. From now on, all values -other than the symbol 'erc-button-buttonize-nicks' appearing in the -"FORM" field (third element) of this entry are considered deprecated -and will incur a warning. +specially. This is perhaps most evident in its treatment of the +'nicknames' entry in 'erc-button-alist'. Indeed, to simplify ERC's +move to next-gen "rich UI" extensions, this special treatment is being +canonized. From now on, all values other than the symbol +'erc-button-buttonize-nicks' appearing in the "FORM" field (third +element) of this entry are considered deprecated and will incur a +warning. Relatedly, the option 'erc-nick-popup-alist' now favors +functions, which ERC calls non-interactively, over arbitrary +s-expressions, which ERC will continue to honor. Although the default +lineup remains functionally equivalent, its members have all been +updated accordingly. ** Option 'erc-query-on-unjoined-chan-privmsg' restored and renamed. This option was accidentally removed from the default client in ERC diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el index 33b93ff6744..9c84de6720a 100644 --- a/lisp/erc/erc-button.el +++ b/lisp/erc/erc-button.el @@ -660,20 +660,20 @@ erc-browse-emacswiki-lisp ;;; Nickname buttons: (defcustom erc-nick-popup-alist - '(("DeOp" . (erc-cmd-DEOP nick)) - ("Kick" . (erc-cmd-KICK (concat nick " " - (read-from-minibuffer - (concat "Kick " nick ", reason: "))))) - ("Msg" . (erc-cmd-MSG (concat nick " " - (read-from-minibuffer - (concat "Message to " nick ": "))))) - ("Op" . (erc-cmd-OP nick)) - ("Query" . (erc-cmd-QUERY nick)) - ("Whois" . (erc-cmd-WHOIS nick)) - ("Lastlog" . (erc-cmd-LASTLOG nick))) + '(("DeOp" . erc-cmd-DEOP) + ("Kick" . erc-button-cmd-KICK) + ("Msg" . erc-button-cmd-MSG) + ("Op" . erc-cmd-OP) + ("Query" . erc-cmd-QUERY) + ("Whois" . erc-cmd-WHOIS) + ("Lastlog" . erc-cmd-LASTLOG)) "An alist of possible actions to take on a nickname. -An entry looks like (\"Action\" . SEXP) where SEXP is evaluated with -the variable `nick' bound to the nick in question. +For all entries (ACTION . FUNC), ERC offers ACTION as a possible +completion item and calls the selected entry's FUNC with the +buttonized nickname at point as the only argument. For +historical reasons, FUNC can also be an arbitrary sexp, in which +case, ERC binds the nick in question to the variable `nick' and +evaluates the expression. Examples: (\"DebianDB\" . @@ -681,18 +681,48 @@ erc-nick-popup-alist (format \"ldapsearch -x -P 2 -h db.debian.org -b dc=debian,dc=org ircnick=%s\" nick)))" + :package-version '(ERC . "5.6") ; FIXME sync on release :type '(repeat (cons (string :tag "Op") - sexp))) + (choice function sexp)))) + +(defun erc-button-cmd-KICK (nick) + "Prompt for a reason, then kick NICK via `erc-cmd-KICK'. +In server buffers, also prompt for a channel." + (erc-cmd-KICK + (or (and erc--target (erc-default-target)) + (let ((targets (mapcar (lambda (b) + (cons (erc--target-string + (buffer-local-value 'erc--target b)) + b)) + (erc-channel-list erc-server-process)))) + (completing-read (format "Channel (%s): " (caar targets)) + targets (pcase-lambda (`(,_ . ,buf)) + (with-current-buffer buf + (erc-get-channel-user nick))) + t nil t (caar targets)))) + nick + (read-from-minibuffer "Reason: "))) + +(defun erc-button-cmd-MSG (nick) + "Prompt for a message to NICK, and send it via `erc-cmd-MSG'." + (let ((msg (read-from-minibuffer (concat "Message to " nick ": ")))) + (erc-cmd-MSG (concat nick " " msg)))) + +(defvar-local erc-button--nick-popup-alist nil + "Internally controlled items for `erc-nick-popup-alist'.") (defun erc-nick-popup (nick) (let* ((completion-ignore-case t) + (alist (append erc-nick-popup-alist erc-button--nick-popup-alist)) (action (completing-read (format-message "What action to take on `%s'? " nick) - erc-nick-popup-alist)) - (code (cdr (assoc action erc-nick-popup-alist)))) + alist)) + (code (cdr (assoc action alist)))) (when code (erc-set-active-buffer (current-buffer)) - (eval code `((nick . ,nick)))))) + (if (functionp code) + (funcall code nick) + (eval code `((nick . ,nick))))))) ;;; Callback functions (defun erc-button-describe-symbol (symbol-name) -- 2.40.1