summaryrefslogtreecommitdiff
path: root/lisp/erc/erc-common.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/erc/erc-common.el')
-rw-r--r--lisp/erc/erc-common.el95
1 files changed, 67 insertions, 28 deletions
diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el
index b8ba0673355..8388efe062c 100644
--- a/lisp/erc/erc-common.el
+++ b/lisp/erc/erc-common.el
@@ -37,6 +37,7 @@
(defvar erc-session-server)
(declare-function erc--get-isupport-entry "erc-backend" (key &optional single))
+(declare-function erc--init-cusr-fallback-status "erc" (v h o a q))
(declare-function erc-get-buffer "erc" (target &optional proc))
(declare-function erc-server-buffer "erc" nil)
(declare-function widget-apply-action "wid-edit" (widget &optional event))
@@ -49,15 +50,30 @@
(declare-function widget-type "wid-edit" (widget))
(cl-defstruct erc-input
- string insertp sendp)
+ "Object shared among members of `erc-pre-send-functions'.
+Any use outside of the hook is not supported."
+ ( string "" :type string
+ :documentation "String to send and, without `substxt', insert.
+ERC treats separate lines as separate messages.")
+ ( insertp nil :type boolean
+ :documentation "Whether to insert outgoing message.
+When nil, ERC still sends `string'.")
+ ( sendp nil :type boolean
+ :documentation "Whether to send and (for compat reasons) insert.
+To insert without sending, define a (slash) command.")
+ ( substxt nil :type (or function string null)
+ :documentation "Alternate string to insert without splitting.
+The function form is for internal use.")
+ ( refoldp nil :type boolean
+ :documentation "Whether to resplit a possibly overlong `string'.
+ERC only refolds `string', never `substxt'."))
(cl-defstruct (erc--input-split (:include erc-input
- (string :read-only)
+ (string "" :read-only t)
(insertp erc-insert-this)
(sendp (with-suppressed-warnings
((obsolete erc-send-this))
erc-send-this))))
- (refoldp nil :type boolean)
(lines nil :type (list-of string))
(abortp nil :type (list-of symbol))
(cmdp nil :type boolean))
@@ -76,11 +92,11 @@
make-erc-channel-user
( &key voice halfop op admin owner
last-message-time
- &aux (status (+ (if voice 1 0)
- (if halfop 2 0)
- (if op 4 0)
- (if admin 8 0)
- (if owner 16 0)))))
+ &aux (status
+ (if (or voice halfop op admin owner)
+ (erc--init-cusr-fallback-status
+ voice halfop op admin owner)
+ 0))))
:named)
"Object containing channel-specific data for a single user."
;; voice halfop op admin owner
@@ -140,9 +156,12 @@ For use with the macro `erc--with-isupport-data'."
(cl-defstruct (erc--parsed-prefix (:include erc--isupport-data))
"Server-local data for recognized membership-status prefixes.
Derived from the advertised \"PREFIX\" ISUPPORT parameter."
- (letters "qaohv" :type string)
- (statuses "~&@%+" :type string)
- (alist nil :type (list-of cons)))
+ ( letters "vhoaq" :type string
+ :documentation "Status letters ranked lowest to highest.")
+ ( statuses "+%@&~" :type string
+ :documentation "Status prefixes ranked lowest to highest.")
+ ( alist nil :type (list-of cons)
+ :documentation "Alist of letters-prefix pairs."))
(cl-defstruct (erc--channel-mode-types (:include erc--isupport-data))
"Server-local \"CHANMODES\" data."
@@ -152,7 +171,7 @@ Derived from the advertised \"PREFIX\" ISUPPORT parameter."
;; After dropping 28, we can use prefixed "erc-autoload" cookies.
(defun erc--normalize-module-symbol (symbol)
- "Return preferred SYMBOL for `erc--modules'."
+ "Return preferred SYMBOL for `erc--module'."
(while-let ((canonical (get symbol 'erc--module))
((not (eq canonical symbol))))
(setq symbol canonical))
@@ -333,6 +352,7 @@ instead of a `set' state, which precludes any actual saving."
(read (current-buffer))))
(defmacro erc--find-feature (name alias)
+ ;; Don't use this outside of the file that defines NAME.
`(pcase (erc--find-group ',name ,(and alias (list 'quote alias)))
('erc (and-let* ((file (or (macroexp-file-name) buffer-file-name)))
(intern (file-name-base file))))
@@ -350,8 +370,12 @@ See Info node `(elisp) Defining Minor Modes' for more.")
(defmacro define-erc-module (name alias doc enable-body disable-body
&optional local-p)
"Define a new minor mode using ERC conventions.
-Symbol NAME is the name of the module.
-Symbol ALIAS is the alias to use, or nil.
+Expect NAME to be the module's name and ALIAS, when non-nil, to
+be a retired name used only for compatibility purposes. In new
+code, assume NAME is the same symbol users should specify when
+customizing `erc-modules' (see info node `(erc) Module Loading'
+for more on naming).
+
DOC is the documentation string to use for the minor mode.
ENABLE-BODY is a list of expressions used to enable the mode.
DISABLE-BODY is a list of expressions used to disable the mode.
@@ -382,7 +406,10 @@ Example:
(let* ((sn (symbol-name name))
(mode (intern (format "erc-%s-mode" (downcase sn))))
(enable (intern (format "erc-%s-enable" (downcase sn))))
- (disable (intern (format "erc-%s-disable" (downcase sn)))))
+ (disable (intern (format "erc-%s-disable" (downcase sn))))
+ (nmodule (erc--normalize-module-symbol name))
+ (amod (and alias (intern (format "erc-%s-mode"
+ (downcase (symbol-name alias)))))))
`(progn
(define-minor-mode
,mode
@@ -399,13 +426,9 @@ if ARG is omitted or nil.
(if ,mode (,enable) (,disable))))
,(erc--assemble-toggle local-p name enable mode t enable-body)
,(erc--assemble-toggle local-p name disable mode nil disable-body)
- ,@(and-let* ((alias)
- ((not (eq name alias)))
- (aname (intern (format "erc-%s-mode"
- (downcase (symbol-name alias))))))
- `((defalias ',aname #',mode)
- (put ',aname 'erc-module ',(erc--normalize-module-symbol name))))
- (put ',mode 'erc-module ',(erc--normalize-module-symbol name))
+ ,@(and amod `((defalias ',amod #',mode)
+ (put ',amod 'erc-module ',nmodule)))
+ (put ',mode 'erc-module ',nmodule)
;; For find-function and find-variable.
(put ',mode 'definition-name ',name)
(put ',enable 'definition-name ',name)
@@ -462,10 +485,9 @@ If no server buffer exists, return nil."
,@body)))))
(defmacro erc-with-all-buffers-of-server (process pred &rest forms)
- "Execute FORMS in all buffers which have same process as this server.
-FORMS will be evaluated in all buffers having the process PROCESS and
-where PRED matches or in all buffers of the server process if PRED is
-nil."
+ "Evaluate FORMS in all buffers of PROCESS in which PRED returns non-nil.
+When PROCESS is nil, do so in all ERC buffers. When PRED is nil,
+run FORMS unconditionally."
(declare (indent 2) (debug (form form body)))
(macroexp-let2 nil pred pred
`(erc-buffer-filter (lambda ()
@@ -554,9 +576,21 @@ See `erc-define-message-format-catalog' for the meaning of
ENTRIES, an alist, and `erc-tests-common-pp-propertized-parts' in
tests/lisp/erc/erc-tests.el for a convenience command to convert
a literal string into a sequence of `propertize' forms, which are
-much easier to review and edit."
+much easier to review and edit. When ENTRIES begins with a
+sequence of keyword-value pairs remove them and consider their
+evaluated values before processing the alist proper.
+
+Currently, the only recognized keyword is `:parent', which tells
+ERC to search recursively for a given template key using the
+keyword's associated value, another catalog symbol, if not found
+in catalog NAME."
(declare (indent 1))
(let (out)
+ (while (keywordp (car entries))
+ (push (pcase-exhaustive (pop entries)
+ (:parent `(put ',name 'erc--base-format-catalog
+ ,(pop entries))))
+ out))
(dolist (e entries (cons 'progn (nreverse out)))
(push `(defvar ,(intern (format "erc-message-%s-%s" name (car e)))
,(cdr e)
@@ -575,9 +609,14 @@ symbol, and FORMAT evaluates to a format string compatible with
`format-spec'. Expect modules that only define a handful of
entries to do so manually, instead of using this macro, so that
the resulting variables will end up with more useful doc strings."
- (declare (indent 1))
+ (declare (indent 1)
+ (debug (symbolp [&rest [keywordp form]] &rest (symbolp . form))))
`(erc--define-catalog ,language ,entries))
+(define-inline erc--strpos (char string)
+ "Return position of CHAR in STRING or nil if not found."
+ (inline-quote (string-search (string ,char) ,string)))
+
(defmacro erc--doarray (spec &rest body)
"Map over ARRAY, running BODY with VAR bound to iteration element.
Behave more or less like `seq-doseq', but tailor operations for