diff options
| author | F. Jason Park | 2024-05-22 22:59:54 -0700 |
|---|---|---|
| committer | F. Jason Park | 2024-05-27 16:46:40 -0700 |
| commit | 6888bbbe832e14c3aaaa2c9750ed27e577e0983d (patch) | |
| tree | 890d80927ef23f1b7d330ca6aa9a1ebd265fe963 | |
| parent | 5f84213c9802181b4d800615915e3c8dded7b94f (diff) | |
| download | emacs-6888bbbe832e14c3aaaa2c9750ed27e577e0983d.tar.gz emacs-6888bbbe832e14c3aaaa2c9750ed27e577e0983d.zip | |
Add ERC module querypoll as monitor placeholder
* doc/misc/erc.texi: Add module `querypoll' to list of built-in
modules'.
* etc/ERC-NEWS: Mention new module `querypoll', and explain new
default behavior for deriving query membership from that of channels.
* lisp/erc/erc-goodies.el (erc--querypoll-ring)
(erc--querypoll-timer): New variables.
(erc-querypoll-exclude-regexp): New option.
(erc-querypoll-mode, erc-querypoll-enable, erc-querypoll-disable): New
module for polling with "WHO" requests for the presence of otherwise
"untracked" query targets.
(erc-querypoll-period-params): New variable.
(erc--querypoll-compute-period)
(erc--querypoll-target-in-chan-p)
(erc--querypoll-get-length)
(erc--querypoll-get-next)
(erc--querypoll-subscribe)
(erc--querypoll-on-352)
(erc--querypoll-send): New functions.
* lisp/erc/erc-speedbar.el (erc-speedbar-buttons): Dispatch queries as
if they were channels when `erc--queries-current-p' returns non-nil.
That is, show head counts alongside query targets as users come and
go.
(erc-speedbar-insert-target): Defer to `erc--queries-current-p' to
know whether to show a query in the style of a channel. This affects
both the plain speedbar integration as well as the `nickbar' module
added for bug#63595. Also, use question marks rather than the empty
string for query bullets, so that query and channel items are aligned
vertically.
* lisp/erc/erc.el (erc--queries-current-p): New function.
* test/lisp/erc/erc-goodies-tests.el
(erc--querypoll-compute-period)
(erc--querypoll-target-in-chan-p)
(erc--querypoll-get-length)
(erc--querypoll-get-next): New tests. (Bug#70928)
| -rw-r--r-- | doc/misc/erc.texi | 4 | ||||
| -rw-r--r-- | etc/ERC-NEWS | 28 | ||||
| -rw-r--r-- | lisp/erc/erc-goodies.el | 190 | ||||
| -rw-r--r-- | lisp/erc/erc-speedbar.el | 13 | ||||
| -rw-r--r-- | lisp/erc/erc.el | 5 | ||||
| -rw-r--r-- | test/lisp/erc/erc-goodies-tests.el | 57 |
6 files changed, 292 insertions, 5 deletions
diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index 0c7e3b09f41..c7cbf7908b8 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi | |||
| @@ -518,6 +518,10 @@ or your nickname is mentioned | |||
| 518 | @item page | 518 | @item page |
| 519 | Process CTCP PAGE requests from IRC | 519 | Process CTCP PAGE requests from IRC |
| 520 | 520 | ||
| 521 | @cindex modules, querypoll | ||
| 522 | @item querypoll | ||
| 523 | Update query participant data by continually polling the server | ||
| 524 | |||
| 521 | @cindex modules, readonly | 525 | @cindex modules, readonly |
| 522 | @item readonly | 526 | @item readonly |
| 523 | Make displayed lines read-only | 527 | Make displayed lines read-only |
diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index acad0f03572..1fad62e1999 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS | |||
| @@ -100,6 +100,18 @@ one's optionally accessible from the keyboard, just like any other | |||
| 100 | side window. Hit '<RET>' over a nick to spawn a "/QUERY" or a | 100 | side window. Hit '<RET>' over a nick to spawn a "/QUERY" or a |
| 101 | "Lastlog" (Occur) session. See 'erc-nickbar-mode' for more. | 101 | "Lastlog" (Occur) session. See 'erc-nickbar-mode' for more. |
| 102 | 102 | ||
| 103 | ** New module to keep tabs on query pals who aren't in your channels. | ||
| 104 | ERC has gotten a bit pickier about managing participants in query | ||
| 105 | buffers. "Untracked" correspondents no longer appear automatically in | ||
| 106 | membership tables, even if you respond or initiate contact. Instead, | ||
| 107 | ERC only adds and removes participant data when these same users join | ||
| 108 | and leave channels. Anyone uncomfortable with the apparent | ||
| 109 | uncertainty this brings can look to the new 'querypoll' module, which | ||
| 110 | periodically sends WHO requests to keep track of correspondents. | ||
| 111 | Those familiar with the IRCv3 Monitor extension can think of this as | ||
| 112 | "fallback code" and a temporary placeholder for the real thing. | ||
| 113 | Add 'querypoll' (and 'nickbar') to 'erc-modules' to try it out. | ||
| 114 | |||
| 103 | ** Option 'erc-timestamp-use-align-to' more versatile. | 115 | ** Option 'erc-timestamp-use-align-to' more versatile. |
| 104 | While this option has always offered to right-align stamps via the | 116 | While this option has always offered to right-align stamps via the |
| 105 | 'display' text property, it's now more effective at doing so when set | 117 | 'display' text property, it's now more effective at doing so when set |
| @@ -563,6 +575,22 @@ redubbed 'erc-channel-members'. Similarly, the utility function | |||
| 563 | 'erc-get-channel-user' has been renamed to 'erc-get-channel-member'. | 575 | 'erc-get-channel-user' has been renamed to 'erc-get-channel-member'. |
| 564 | Expect deprecations of the old names to follow in a future release. | 576 | Expect deprecations of the old names to follow in a future release. |
| 565 | 577 | ||
| 578 | *** Query participant tables now depend on channel membership. | ||
| 579 | ERC has always been inconsistent and difficult to predict in its | ||
| 580 | handling of records describing other IRC users. This has made simple | ||
| 581 | things like detecting the online status of query peers and the | ||
| 582 | presence of one's own user in 'erc-server-users' especially | ||
| 583 | unreliable. From now on, ERC resolves to be more sensible and | ||
| 584 | conservative in such areas. For example, it now retains its own user | ||
| 585 | info, once discovered, for the remainder of a session. It also relies | ||
| 586 | solely on channel membership to "drive" query participant information. | ||
| 587 | That is, when another IRC user departs their last known channel, any | ||
| 588 | queries with them will consider them absent, even if they're likely | ||
| 589 | still online. Anyone with difficulty adapting to this new paradigm | ||
| 590 | should contact the mailing list to inquire about associated | ||
| 591 | compatibility flags, which can be made public on request. Also see | ||
| 592 | the related news item announcing the module 'querypoll'. | ||
| 593 | |||
| 566 | *** The 'erc-channel-user' struct has a changed internally. | 594 | *** The 'erc-channel-user' struct has a changed internally. |
| 567 | The five boolean slots for membership prefixes have been folded | 595 | The five boolean slots for membership prefixes have been folded |
| 568 | ("encoded") into a single integer slot. However, the old 'setf'-able | 596 | ("encoded") into a single integer slot. However, the old 'setf'-able |
diff --git a/lisp/erc/erc-goodies.el b/lisp/erc/erc-goodies.el index fe44c3bdfcb..9837ec302ee 100644 --- a/lisp/erc/erc-goodies.el +++ b/lisp/erc/erc-goodies.el | |||
| @@ -1114,6 +1114,196 @@ servers. If called from a program, PROC specifies the server process." | |||
| 1114 | nil erc-server-process))) | 1114 | nil erc-server-process))) |
| 1115 | (multi-occur (erc-buffer-list nil proc) string)) | 1115 | (multi-occur (erc-buffer-list nil proc) string)) |
| 1116 | 1116 | ||
| 1117 | |||
| 1118 | ;;;; querypoll | ||
| 1119 | |||
| 1120 | (declare-function ring-empty-p "ring" (ring)) | ||
| 1121 | (declare-function ring-insert "ring" (ring item)) | ||
| 1122 | (declare-function ring-insert+extend "ring" (ring item)) | ||
| 1123 | (declare-function ring-length "ring" (ring)) | ||
| 1124 | (declare-function ring-member "ring" (ring item)) | ||
| 1125 | (declare-function ring-ref "ring" (ring index)) | ||
| 1126 | (declare-function ring-remove "ring" (ring &optional index)) | ||
| 1127 | |||
| 1128 | (defvar-local erc--querypoll-ring nil) | ||
| 1129 | (defvar-local erc--querypoll-timer nil) | ||
| 1130 | |||
| 1131 | (defcustom erc-querypoll-exclude-regexp | ||
| 1132 | (rx bot (or (: "*" (+ nonl)) (: (+ (in "A-Za-z")) "Serv")) eot) | ||
| 1133 | "Pattern to skip polling for bots and services you regularly query." | ||
| 1134 | :group 'erc | ||
| 1135 | :package-version '(ERC . "5.6") | ||
| 1136 | :type 'regexp) | ||
| 1137 | |||
| 1138 | ;;;###autoload(autoload 'erc-querypoll-mode "erc-goodies" nil t) | ||
| 1139 | (define-erc-module querypoll nil | ||
| 1140 | "Send periodic \"WHO\" requests for each query buffer. | ||
| 1141 | Omit query participants who are currently present in some channel. | ||
| 1142 | Instead of announcing arrivals and departures, rely on other modules, | ||
| 1143 | like `nickbar', to provide UI feedback when changes occur. | ||
| 1144 | |||
| 1145 | Once ERC implements the `monitor' extension, this module will serve as | ||
| 1146 | an optional fallback for keeping query-participant rolls up to date on | ||
| 1147 | servers that lack support or are stingy with their allotments. Until | ||
| 1148 | such time, this module should be considered experimental. | ||
| 1149 | |||
| 1150 | This is a local ERC module, so selectively polling only a subset of | ||
| 1151 | query targets is possible but cumbersome. To do so, ensure | ||
| 1152 | `erc-querypoll-mode' is enabled in the server buffer, and then toggle it | ||
| 1153 | as appropriate in desired query buffers. To stop polling for the | ||
| 1154 | current connection, toggle off the command \\[erc-querypoll-mode] from a | ||
| 1155 | server buffer, or run \\`M-x C-u erc-querypoll-disable RET' from a | ||
| 1156 | target buffer." | ||
| 1157 | ((if erc--target | ||
| 1158 | (if (erc-query-buffer-p) | ||
| 1159 | (progn ; accommodate those who eschew `erc-modules' | ||
| 1160 | (erc-with-server-buffer | ||
| 1161 | (unless erc-querypoll-mode | ||
| 1162 | (erc-querypoll-mode +1))) | ||
| 1163 | (erc--querypoll-subscribe (current-buffer))) | ||
| 1164 | (erc-querypoll-mode -1)) | ||
| 1165 | (cl-assert (not erc--decouple-query-and-channel-membership-p)) | ||
| 1166 | (setq-local erc--querypoll-ring (make-ring 5)) | ||
| 1167 | (erc-with-all-buffers-of-server erc-server-process nil | ||
| 1168 | (unless erc-querypoll-mode | ||
| 1169 | (erc-querypoll-mode +1))))) | ||
| 1170 | ((when erc--querypoll-timer | ||
| 1171 | (cancel-timer erc--querypoll-timer)) | ||
| 1172 | (if erc--target | ||
| 1173 | (when-let (((erc-query-buffer-p)) | ||
| 1174 | (ring (erc-with-server-buffer erc--querypoll-ring)) | ||
| 1175 | (index (ring-member ring (current-buffer))) | ||
| 1176 | ((not (erc--querypoll-target-in-chan-p (current-buffer))))) | ||
| 1177 | (ring-remove ring index) | ||
| 1178 | (unless (erc-current-nick-p (erc-target)) | ||
| 1179 | (erc-remove-current-channel-member (erc-target)))) | ||
| 1180 | (erc-with-all-buffers-of-server erc-server-process #'erc-query-buffer-p | ||
| 1181 | (erc-querypoll-mode -1))) | ||
| 1182 | (kill-local-variable 'erc--querypoll-ring) | ||
| 1183 | (kill-local-variable 'erc--querypoll-timer)) | ||
| 1184 | 'local) | ||
| 1185 | |||
| 1186 | (cl-defmethod erc--queries-current-p (&context (erc-querypoll-mode (eql t))) t) | ||
| 1187 | |||
| 1188 | (defvar erc-querypoll-period-params '(10 10 1) | ||
| 1189 | "Parameters affecting the delay with respect to the number of buffers. | ||
| 1190 | The elements represent some parameters of an exponential decay function, | ||
| 1191 | a(e)^{-x/b}+c. The first number (a) affects the overall scaling. A | ||
| 1192 | higher value means longer delays for all query buffers relative to queue | ||
| 1193 | length. The second number (b) determines how quickly the delay | ||
| 1194 | decreases as the queue length increases. Larger values make the delay | ||
| 1195 | taper off more gradually. The last number (c) sets the minimum delay | ||
| 1196 | between updates regardless of queue length.") | ||
| 1197 | |||
| 1198 | (defun erc--querypoll-compute-period (queue-size) | ||
| 1199 | "Calculate delay based on QUEUE-SIZE." | ||
| 1200 | (let ((scale (nth 0 erc-querypoll-period-params)) | ||
| 1201 | (rate (* 1.0 (nth 1 erc-querypoll-period-params))) | ||
| 1202 | (min (nth 2 erc-querypoll-period-params))) | ||
| 1203 | (+ (* scale (exp (/ (- queue-size) rate))) min))) | ||
| 1204 | |||
| 1205 | (defun erc--querypoll-target-in-chan-p (buffer) | ||
| 1206 | "Determine whether buffer's target, as a user, is joined to any channels." | ||
| 1207 | (and-let* | ||
| 1208 | ((target (erc--target-string (buffer-local-value 'erc--target buffer))) | ||
| 1209 | (user (erc-get-server-user target)) | ||
| 1210 | (buffers (erc-server-user-buffers user)) | ||
| 1211 | ((seq-some #'erc-channel-p buffers))))) | ||
| 1212 | |||
| 1213 | (defun erc--querypoll-get-length (ring) | ||
| 1214 | "Return the effective length of RING, discounting chan members." | ||
| 1215 | (let ((count 0)) | ||
| 1216 | (dotimes (i (ring-length ring)) | ||
| 1217 | (unless (erc--querypoll-target-in-chan-p (ring-ref ring i)) | ||
| 1218 | (cl-incf count 1))) | ||
| 1219 | count)) | ||
| 1220 | |||
| 1221 | (defun erc--querypoll-get-next (ring) | ||
| 1222 | (let ((n (ring-length ring))) | ||
| 1223 | (catch 'found | ||
| 1224 | (while (natnump (cl-decf n)) | ||
| 1225 | (when-let ((buffer (ring-remove ring)) | ||
| 1226 | ((buffer-live-p buffer))) | ||
| 1227 | ;; Push back buffers for users joined to some chan. | ||
| 1228 | (if (erc--querypoll-target-in-chan-p buffer) | ||
| 1229 | (ring-insert ring buffer) | ||
| 1230 | (throw 'found buffer))))))) | ||
| 1231 | |||
| 1232 | (defun erc--querypoll-subscribe (query-buffer &optional penalty) | ||
| 1233 | "Add QUERY-BUFFER to FIFO and ensure timer is running." | ||
| 1234 | (when query-buffer | ||
| 1235 | (cl-assert (erc-query-buffer-p query-buffer))) | ||
| 1236 | (erc-with-server-buffer | ||
| 1237 | (when (and query-buffer | ||
| 1238 | (not (with-current-buffer query-buffer | ||
| 1239 | (or (erc-current-nick-p (erc-target)) | ||
| 1240 | (string-match erc-querypoll-exclude-regexp | ||
| 1241 | (erc-target))))) | ||
| 1242 | (not (ring-member erc--querypoll-ring query-buffer))) | ||
| 1243 | (ring-insert+extend erc--querypoll-ring query-buffer)) | ||
| 1244 | (unless erc--querypoll-timer | ||
| 1245 | (setq erc--querypoll-timer | ||
| 1246 | (let* ((length (erc--querypoll-get-length erc--querypoll-ring)) | ||
| 1247 | (period (erc--querypoll-compute-period length))) | ||
| 1248 | (run-at-time (+ (or penalty 0) period) | ||
| 1249 | nil #'erc--querypoll-send (current-buffer))))))) | ||
| 1250 | |||
| 1251 | (defun erc--querypoll-on-352 (target-nick args) | ||
| 1252 | "Add or update `erc-server-users' data for TARGET-NICK from ARGS. | ||
| 1253 | Then add user to participant rolls in any existing query buffers." | ||
| 1254 | (pcase-let | ||
| 1255 | ((`(,_ ,channel ,login ,host ,_server ,nick ,_flags, hop-real) args)) | ||
| 1256 | (when (and (string= channel "*") (erc-nick-equal-p nick target-nick)) | ||
| 1257 | (if-let ((user (erc-get-server-user nick))) | ||
| 1258 | (erc-update-user user nick host login | ||
| 1259 | (erc--extract-352-full-name hop-real)) | ||
| 1260 | ;; Don't add unless target is already known. | ||
| 1261 | (when (erc-get-buffer nick erc-server-process) | ||
| 1262 | (erc-add-server-user | ||
| 1263 | nick (make-erc-server-user | ||
| 1264 | :nickname nick :login login :host host | ||
| 1265 | :full-name (erc--extract-352-full-name hop-real))))) | ||
| 1266 | (erc--ensure-query-member nick) | ||
| 1267 | t))) | ||
| 1268 | |||
| 1269 | ;; This uses heuristics to associate replies to the initial request | ||
| 1270 | ;; because ERC does not yet support `labeled-response'. | ||
| 1271 | (defun erc--querypoll-send (server-buffer) | ||
| 1272 | "Send a captive \"WHO\" in SERVER-BUFFER." | ||
| 1273 | (when (and (buffer-live-p server-buffer) | ||
| 1274 | (buffer-local-value 'erc-server-connected server-buffer)) | ||
| 1275 | (with-current-buffer server-buffer | ||
| 1276 | (setq erc--querypoll-timer nil) | ||
| 1277 | (if-let ((buffer (erc--querypoll-get-next erc--querypoll-ring))) | ||
| 1278 | (letrec | ||
| 1279 | ((target (erc--target-string | ||
| 1280 | (buffer-local-value 'erc--target buffer))) | ||
| 1281 | (penalty 0) | ||
| 1282 | (here-fn (erc-once-with-server-event | ||
| 1283 | "352" (lambda (_ parsed) | ||
| 1284 | (erc--querypoll-on-352 | ||
| 1285 | target (erc-response.command-args parsed))))) | ||
| 1286 | (done-fn (erc-once-with-server-event | ||
| 1287 | "315" | ||
| 1288 | (lambda (_ parsed) | ||
| 1289 | (if (memq here-fn erc-server-352-functions) | ||
| 1290 | (erc-remove-user | ||
| 1291 | (nth 1 (erc-response.command-args parsed))) | ||
| 1292 | (remove-hook 'erc-server-352-functions here-fn t)) | ||
| 1293 | (remove-hook 'erc-server-263-functions fail-fn t) | ||
| 1294 | (remove-hook 'erc-server-315-functions done-fn t) | ||
| 1295 | (erc--querypoll-subscribe buffer penalty) | ||
| 1296 | t))) | ||
| 1297 | (fail-fn (erc-once-with-server-event | ||
| 1298 | "263" | ||
| 1299 | (lambda (proc parsed) | ||
| 1300 | (setq penalty 60) | ||
| 1301 | (funcall done-fn proc parsed) | ||
| 1302 | t)))) | ||
| 1303 | (erc-server-send (concat "WHO " target))) | ||
| 1304 | (unless (ring-empty-p erc--querypoll-ring) | ||
| 1305 | (erc--querypoll-subscribe nil 30)))))) | ||
| 1306 | |||
| 1117 | (provide 'erc-goodies) | 1307 | (provide 'erc-goodies) |
| 1118 | 1308 | ||
| 1119 | ;;; erc-goodies.el ends here | 1309 | ;;; erc-goodies.el ends here |
diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el index 9cde452be58..d4f91bb363a 100644 --- a/lisp/erc/erc-speedbar.el +++ b/lisp/erc/erc-speedbar.el | |||
| @@ -133,7 +133,7 @@ This will add a speedbar major display mode." | |||
| 133 | (defun erc-speedbar-buttons (buffer) | 133 | (defun erc-speedbar-buttons (buffer) |
| 134 | "Create buttons for speedbar in BUFFER." | 134 | "Create buttons for speedbar in BUFFER." |
| 135 | (erase-buffer) | 135 | (erase-buffer) |
| 136 | (let (serverp chanp queryp) | 136 | (let (serverp chanp queryp queries-current-p) |
| 137 | (with-current-buffer buffer | 137 | (with-current-buffer buffer |
| 138 | ;; The function `dframe-help-echo' checks the default value of | 138 | ;; The function `dframe-help-echo' checks the default value of |
| 139 | ;; `dframe-help-echo-function' when deciding whether to visit | 139 | ;; `dframe-help-echo-function' when deciding whether to visit |
| @@ -145,13 +145,14 @@ This will add a speedbar major display mode." | |||
| 145 | (setq-local dframe-help-echo-function #'ignore) | 145 | (setq-local dframe-help-echo-function #'ignore) |
| 146 | (setq serverp (erc--server-buffer-p)) | 146 | (setq serverp (erc--server-buffer-p)) |
| 147 | (setq chanp (erc-channel-p (erc-default-target))) | 147 | (setq chanp (erc-channel-p (erc-default-target))) |
| 148 | (setq queryp (erc-query-buffer-p))) | 148 | (setq queryp (erc-query-buffer-p) |
| 149 | queries-current-p (erc--queries-current-p))) | ||
| 149 | (defvar erc-nickbar-mode) | 150 | (defvar erc-nickbar-mode) |
| 150 | (cond ((and erc-nickbar-mode (null (get-buffer-window speedbar-buffer))) | 151 | (cond ((and erc-nickbar-mode (null (get-buffer-window speedbar-buffer))) |
| 151 | (run-at-time 0 nil #'erc-nickbar-mode -1)) | 152 | (run-at-time 0 nil #'erc-nickbar-mode -1)) |
| 152 | (serverp | 153 | (serverp |
| 153 | (erc-speedbar-channel-buttons nil 0 buffer)) | 154 | (erc-speedbar-channel-buttons nil 0 buffer)) |
| 154 | (chanp | 155 | ((or chanp (and queryp queries-current-p)) |
| 155 | (erc-speedbar-insert-target buffer 0) | 156 | (erc-speedbar-insert-target buffer 0) |
| 156 | (forward-line -1) | 157 | (forward-line -1) |
| 157 | (erc-speedbar-expand-channel "+" buffer 0)) | 158 | (erc-speedbar-expand-channel "+" buffer 0)) |
| @@ -205,7 +206,8 @@ This will add a speedbar major display mode." | |||
| 205 | t))))) | 206 | t))))) |
| 206 | 207 | ||
| 207 | (defun erc-speedbar-insert-target (buffer depth) | 208 | (defun erc-speedbar-insert-target (buffer depth) |
| 208 | (if (erc--target-channel-p (buffer-local-value 'erc--target buffer)) | 209 | (if (with-current-buffer buffer |
| 210 | (or (erc--target-channel-p erc--target) (erc--queries-current-p))) | ||
| 209 | (progn | 211 | (progn |
| 210 | (speedbar-make-tag-line | 212 | (speedbar-make-tag-line |
| 211 | 'bracket ?+ 'erc-speedbar-expand-channel buffer | 213 | 'bracket ?+ 'erc-speedbar-expand-channel buffer |
| @@ -218,8 +220,9 @@ This will add a speedbar major display mode." | |||
| 218 | (speedbar-add-indicator (format "(%d)" (hash-table-count table))) | 220 | (speedbar-add-indicator (format "(%d)" (hash-table-count table))) |
| 219 | (rx "(" (+ (any "0-9")) ")")))) | 221 | (rx "(" (+ (any "0-9")) ")")))) |
| 220 | ;; Query target | 222 | ;; Query target |
| 223 | (cl-assert (erc-query-buffer-p buffer)) | ||
| 221 | (speedbar-make-tag-line | 224 | (speedbar-make-tag-line |
| 222 | nil nil nil nil | 225 | 'bracket ?? nil nil |
| 223 | (buffer-name buffer) 'erc-speedbar-goto-buffer buffer nil | 226 | (buffer-name buffer) 'erc-speedbar-goto-buffer buffer nil |
| 224 | depth))) | 227 | depth))) |
| 225 | 228 | ||
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 565f18163df..b375df1edb6 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el | |||
| @@ -557,6 +557,11 @@ user from `erc-server-users'. Note that enabling this compatibility | |||
| 557 | flag degrades the user experience and isn't guaranteed to correctly | 557 | flag degrades the user experience and isn't guaranteed to correctly |
| 558 | restore the described historical behavior.") | 558 | restore the described historical behavior.") |
| 559 | 559 | ||
| 560 | (cl-defmethod erc--queries-current-p () | ||
| 561 | "Return non-nil if ERC actively updates query manifests." | ||
| 562 | (and (not erc--decouple-query-and-channel-membership-p) | ||
| 563 | (erc-query-buffer-p) (erc-get-channel-member (erc-target)))) | ||
| 564 | |||
| 560 | (defun erc--ensure-query-member (nick) | 565 | (defun erc--ensure-query-member (nick) |
| 561 | "Populate membership table in query buffer for online NICK." | 566 | "Populate membership table in query buffer for online NICK." |
| 562 | (erc-with-buffer (nick) | 567 | (erc-with-buffer (nick) |
diff --git a/test/lisp/erc/erc-goodies-tests.el b/test/lisp/erc/erc-goodies-tests.el index 7cbaa39d3f7..ead0bf5a979 100644 --- a/test/lisp/erc/erc-goodies-tests.el +++ b/test/lisp/erc/erc-goodies-tests.el | |||
| @@ -609,4 +609,61 @@ | |||
| 609 | (should (equal '(3 . 11) (erc--get-inserted-msg-bounds arg)))))) | 609 | (should (equal '(3 . 11) (erc--get-inserted-msg-bounds arg)))))) |
| 610 | 610 | ||
| 611 | 611 | ||
| 612 | ;;;; querypoll | ||
| 613 | |||
| 614 | (ert-deftest erc--querypoll-compute-period () | ||
| 615 | (should (equal (mapcar (lambda (i) | ||
| 616 | (/ (round (* 100 (erc--querypoll-compute-period i))) | ||
| 617 | 100.0)) | ||
| 618 | (number-sequence 0 10)) | ||
| 619 | '(11.0 10.05 9.19 8.41 7.7 7.07 6.49 5.97 5.49 5.07 4.68)))) | ||
| 620 | |||
| 621 | (declare-function ring-insert "ring" (ring item)) | ||
| 622 | |||
| 623 | (ert-deftest erc--querypoll-target-in-chan-p () | ||
| 624 | (erc-tests-common-make-server-buf) | ||
| 625 | (with-current-buffer (erc--open-target "#chan") | ||
| 626 | (erc-update-current-channel-member "bob" "bob" 'addp)) | ||
| 627 | |||
| 628 | (with-current-buffer (erc--open-target "bob") | ||
| 629 | (should (erc--querypoll-target-in-chan-p (current-buffer)))) | ||
| 630 | |||
| 631 | (with-current-buffer (erc--open-target "alice") | ||
| 632 | (should-not (erc--querypoll-target-in-chan-p (current-buffer)))) | ||
| 633 | |||
| 634 | (when noninteractive | ||
| 635 | (erc-tests-common-kill-buffers))) | ||
| 636 | |||
| 637 | (ert-deftest erc--querypoll-get-length () | ||
| 638 | (erc-tests-common-make-server-buf) | ||
| 639 | (with-current-buffer (erc--open-target "#chan") | ||
| 640 | (erc-update-current-channel-member "bob" "bob" 'addp)) | ||
| 641 | |||
| 642 | (let ((ring (make-ring 5))) | ||
| 643 | (ring-insert ring (with-current-buffer (erc--open-target "bob"))) | ||
| 644 | (should (= 0 (erc--querypoll-get-length ring))) | ||
| 645 | (ring-insert ring (with-current-buffer (erc--open-target "alice"))) | ||
| 646 | (should (= 1 (erc--querypoll-get-length ring)))) | ||
| 647 | |||
| 648 | (when noninteractive | ||
| 649 | (erc-tests-common-kill-buffers))) | ||
| 650 | |||
| 651 | (ert-deftest erc--querypoll-get-next () | ||
| 652 | (erc-tests-common-make-server-buf) | ||
| 653 | (with-current-buffer (erc--open-target "#chan") | ||
| 654 | (erc-update-current-channel-member "bob" "bob" 'addp) | ||
| 655 | (erc-update-current-channel-member "alice" "alice" 'addp)) | ||
| 656 | |||
| 657 | (let ((ring (make-ring 5))) | ||
| 658 | (ring-insert ring (with-current-buffer (erc--open-target "bob"))) | ||
| 659 | (ring-insert ring (with-current-buffer (erc--open-target "dummy"))) | ||
| 660 | (ring-insert ring (with-current-buffer (erc--open-target "alice"))) | ||
| 661 | (ring-insert ring (with-current-buffer (erc--open-target "tester"))) | ||
| 662 | (kill-buffer (get-buffer "dummy")) | ||
| 663 | |||
| 664 | (should (eq (get-buffer "tester") (erc--querypoll-get-next ring)))) | ||
| 665 | |||
| 666 | (when noninteractive | ||
| 667 | (erc-tests-common-kill-buffers))) | ||
| 668 | |||
| 612 | ;;; erc-goodies-tests.el ends here | 669 | ;;; erc-goodies-tests.el ends here |