diff options
| -rw-r--r-- | lisp/erc/erc-status-sidebar.el | 105 |
1 files changed, 68 insertions, 37 deletions
diff --git a/lisp/erc/erc-status-sidebar.el b/lisp/erc/erc-status-sidebar.el index b8bd7b0065e..cf3d20aeffa 100644 --- a/lisp/erc/erc-status-sidebar.el +++ b/lisp/erc/erc-status-sidebar.el | |||
| @@ -45,8 +45,8 @@ | |||
| 45 | ;; Use M-x erc-status-sidebar-kill RET to kill the sidebar buffer and | 45 | ;; Use M-x erc-status-sidebar-kill RET to kill the sidebar buffer and |
| 46 | ;; close the sidebar on all frames. | 46 | ;; close the sidebar on all frames. |
| 47 | 47 | ||
| 48 | ;; In addition to the commands above, you can also try the all-in-one, | 48 | ;; In addition to the commands above, you can also try the all-in-one |
| 49 | ;; "DWIM" command, `erc-bufbar-mode'. See its doc string for usage. | 49 | ;; entry point `erc-bufbar-mode'. See its doc string for usage. |
| 50 | 50 | ||
| 51 | ;; If you want the status sidebar enabled whenever you use ERC, add | 51 | ;; If you want the status sidebar enabled whenever you use ERC, add |
| 52 | ;; `bufbar' to `erc-modules'. Note that this library also has a major | 52 | ;; `bufbar' to `erc-modules'. Note that this library also has a major |
| @@ -130,8 +130,11 @@ buffers, using the functions | |||
| 130 | `erc-status-sidebar-pad-hierarchy' | 130 | `erc-status-sidebar-pad-hierarchy' |
| 131 | 131 | ||
| 132 | for the above-mentioned purposes. ERC also accepts a list of | 132 | for the above-mentioned purposes. ERC also accepts a list of |
| 133 | functions to preform these roles a la carte. See doc strings for | 133 | functions to preform these roles a la carte. Since the members |
| 134 | a description of their expected arguments and return values." | 134 | of the above sets aren't really interoperable, we don't offer |
| 135 | them here as customization choices, but you can still specify | ||
| 136 | them manually. See doc strings for a description of their | ||
| 137 | expected arguments and return values." | ||
| 135 | :package-version '(ERC . "5.6") ; FIXME sync on release | 138 | :package-version '(ERC . "5.6") ; FIXME sync on release |
| 136 | :type '(choice (const channels-only) | 139 | :type '(choice (const channels-only) |
| 137 | (const all-mixed) | 140 | (const all-mixed) |
| @@ -158,10 +161,12 @@ ACTION parameter." | |||
| 158 | :key-type symbol | 161 | :key-type symbol |
| 159 | :value-type (sexp :tag "Value"))))) | 162 | :value-type (sexp :tag "Value"))))) |
| 160 | 163 | ||
| 161 | (defcustom erc-status-sidebar-singular t | 164 | (defvar erc-status-sidebar--singular-p t |
| 162 | "Whether to show the sidebar on all frames or just one (default)." | 165 | "Whether to restrict the sidebar to a single frame. |
| 163 | :package-version '(ERC . "5.6") ; FIXME sync on release | 166 | This variable only affects `erc-bufbar-mode'. Disabling it does |
| 164 | :type 'boolean) | 167 | not arrange for automatically showing the sidebar in all frames. |
| 168 | Rather, disabling it allows for displaying the sidebar in the | ||
| 169 | selected frame even if it's already showing in some other frame.") | ||
| 165 | 170 | ||
| 166 | (defvar hl-line-mode) | 171 | (defvar hl-line-mode) |
| 167 | (declare-function hl-line-highlight "hl-line" nil) | 172 | (declare-function hl-line-highlight "hl-line" nil) |
| @@ -178,7 +183,7 @@ ACTION parameter." | |||
| 178 | 183 | ||
| 179 | If NO-CREATION is non-nil, the window is not created." | 184 | If NO-CREATION is non-nil, the window is not created." |
| 180 | (let ((sidebar-window (get-buffer-window erc-status-sidebar-buffer-name | 185 | (let ((sidebar-window (get-buffer-window erc-status-sidebar-buffer-name |
| 181 | erc-status-sidebar-singular))) | 186 | erc-status-sidebar--singular-p))) |
| 182 | (unless (or sidebar-window no-creation) | 187 | (unless (or sidebar-window no-creation) |
| 183 | (with-current-buffer (erc-status-sidebar-get-buffer) | 188 | (with-current-buffer (erc-status-sidebar-get-buffer) |
| 184 | (setq-local vertical-scroll-bar nil)) | 189 | (setq-local vertical-scroll-bar nil)) |
| @@ -214,7 +219,7 @@ The erc-status-sidebar buffer is left alone, but the window | |||
| 214 | containing it on the current frame is closed. See | 219 | containing it on the current frame is closed. See |
| 215 | `erc-status-sidebar-kill'." | 220 | `erc-status-sidebar-kill'." |
| 216 | (interactive "P") | 221 | (interactive "P") |
| 217 | (mapcar #'delete-window | 222 | (mapcar #'delete-window ; FIXME use `mapc'. |
| 218 | (get-buffer-window-list (erc-status-sidebar-get-buffer) | 223 | (get-buffer-window-list (erc-status-sidebar-get-buffer) |
| 219 | nil (if all-frames t)))) | 224 | nil (if all-frames t)))) |
| 220 | 225 | ||
| @@ -223,10 +228,8 @@ containing it on the current frame is closed. See | |||
| 223 | `(let ((buffer-read-only nil)) | 228 | `(let ((buffer-read-only nil)) |
| 224 | ,@body)) | 229 | ,@body)) |
| 225 | 230 | ||
| 226 | ;;;###autoload | 231 | (defun erc-status-sidebar--open () |
| 227 | (defun erc-status-sidebar-open () | 232 | "Maybe open the sidebar, respecting `erc-status-sidebar--singular-p'." |
| 228 | "Open or create a sidebar." | ||
| 229 | (interactive) | ||
| 230 | (save-excursion | 233 | (save-excursion |
| 231 | (if (erc-status-sidebar-buffer-exists-p) | 234 | (if (erc-status-sidebar-buffer-exists-p) |
| 232 | (erc-status-sidebar-get-window) | 235 | (erc-status-sidebar-get-window) |
| @@ -237,11 +240,15 @@ containing it on the current frame is closed. See | |||
| 237 | ;;;###autoload(autoload 'erc-bufbar-mode "erc-status-sidebar" nil t) | 240 | ;;;###autoload(autoload 'erc-bufbar-mode "erc-status-sidebar" nil t) |
| 238 | (define-erc-module bufbar nil | 241 | (define-erc-module bufbar nil |
| 239 | "Show `erc-track'-like activity in a side window. | 242 | "Show `erc-track'-like activity in a side window. |
| 240 | When enabling, show the sidebar immediately if called from a | 243 | When enabling, show the sidebar immediately in the current frame |
| 241 | connected ERC buffer. Otherwise, arrange for doing so on connect | 244 | if called from a connected ERC buffer. Otherwise, arrange for |
| 242 | or whenever next displaying a new ERC buffer. When disabling, | 245 | doing so on connect or whenever next displaying a new ERC buffer. |
| 243 | hide the status window if it's showing. With a negative prefix | 246 | When disabling, hide the status window in all frames. With a |
| 244 | arg, also shutdown the session." | 247 | negative prefix arg, also shutdown the session. Normally, this |
| 248 | module only allows one sidebar window in an Emacs session. To | ||
| 249 | override this, use `erc-status-sidebar-open' to force creation | ||
| 250 | and `erc-status-sidebar-close' to hide a single instance on the | ||
| 251 | current frame only." | ||
| 245 | ((unless erc-track-mode | 252 | ((unless erc-track-mode |
| 246 | (unless (memq 'track erc-modules) | 253 | (unless (memq 'track erc-modules) |
| 247 | (erc--warn-once-before-connect 'erc-bufbar-mode | 254 | (erc--warn-once-before-connect 'erc-bufbar-mode |
| @@ -249,30 +256,38 @@ arg, also shutdown the session." | |||
| 249 | " This will affect \C-]all\C-] ERC sessions." | 256 | " This will affect \C-]all\C-] ERC sessions." |
| 250 | " Add `track' to `erc-modules' to silence this message.")) | 257 | " Add `track' to `erc-modules' to silence this message.")) |
| 251 | (erc-track-mode +1)) | 258 | (erc-track-mode +1)) |
| 252 | (add-hook 'erc--setup-buffer-hook #'erc-status-sidebar-open) | 259 | (add-hook 'erc--setup-buffer-hook #'erc-status-sidebar--open) |
| 253 | (unless erc--updating-modules-p | 260 | (unless erc--updating-modules-p |
| 254 | (if (erc-with-server-buffer erc-server-connected) | 261 | (if (erc-with-server-buffer erc-server-connected) |
| 255 | (erc-status-sidebar-open) | 262 | (erc-status-sidebar--open) |
| 256 | (setq erc-bufbar-mode nil) | ||
| 257 | (when (derived-mode-p 'erc-mode) | 263 | (when (derived-mode-p 'erc-mode) |
| 258 | (erc-error "Not initializing `erc-bufbar-mode' in %s" | 264 | (erc-error "Not initializing `erc-bufbar-mode' in %s" |
| 259 | (current-buffer)))))) | 265 | (current-buffer)))))) |
| 260 | ((remove-hook 'erc--setup-buffer-hook #'erc-status-sidebar-open) | 266 | ((remove-hook 'erc--setup-buffer-hook #'erc-status-sidebar--open) |
| 261 | (erc-status-sidebar-close erc-status-sidebar-singular) | 267 | (erc-status-sidebar-close 'all-frames) |
| 262 | (when-let ((arg erc--module-toggle-prefix-arg) | 268 | (when-let ((arg erc--module-toggle-prefix-arg) |
| 263 | ((numberp arg)) | 269 | ((numberp arg)) |
| 264 | ((< arg 0))) | 270 | ((< arg 0))) |
| 265 | (erc-status-sidebar-kill)))) | 271 | (erc-status-sidebar-kill)))) |
| 266 | 272 | ||
| 267 | ;;;###autoload | 273 | ;;;###autoload |
| 274 | (defun erc-status-sidebar-open () | ||
| 275 | "Open or create a sidebar window in the current frame. | ||
| 276 | When `erc-bufbar-mode' is active, do this even if one already | ||
| 277 | exists in another frame." | ||
| 278 | (interactive) | ||
| 279 | (let ((erc-status-sidebar--singular-p (not erc-bufbar-mode))) | ||
| 280 | (erc-status-sidebar--open))) | ||
| 281 | |||
| 282 | ;;;###autoload | ||
| 268 | (defun erc-status-sidebar-toggle () | 283 | (defun erc-status-sidebar-toggle () |
| 269 | "Toggle the sidebar open/closed on the current frame. | 284 | "Toggle the sidebar open/closed on the current frame. |
| 270 | Do this regardless of `erc-status-sidebar-singular'." | 285 | When opening, and `erc-bufbar-mode' is active, create a sidebar |
| 286 | even if one already exists in another frame." | ||
| 271 | (interactive) | 287 | (interactive) |
| 272 | (if (get-buffer-window erc-status-sidebar-buffer-name nil) | 288 | (if (get-buffer-window erc-status-sidebar-buffer-name nil) |
| 273 | (erc-status-sidebar-close) | 289 | (erc-status-sidebar-close) |
| 274 | (let (erc-status-sidebar-singular) | 290 | (erc-status-sidebar-open))) |
| 275 | (erc-status-sidebar-open)))) | ||
| 276 | 291 | ||
| 277 | (defun erc-status-sidebar-get-channame (buffer) | 292 | (defun erc-status-sidebar-get-channame (buffer) |
| 278 | "Return name of BUFFER with all leading \"#\" characters removed." | 293 | "Return name of BUFFER with all leading \"#\" characters removed." |
| @@ -413,11 +428,10 @@ name stand out." | |||
| 413 | erc-status-sidebar-pad-hierarchy)) | 428 | erc-status-sidebar-pad-hierarchy)) |
| 414 | (v v))) | 429 | (v v))) |
| 415 | (chanlist (apply sort-fn (funcall list-fn nil) nil)) | 430 | (chanlist (apply sort-fn (funcall list-fn nil) nil)) |
| 416 | (window nil) | 431 | (windows nil)) |
| 417 | (winstart nil)) | ||
| 418 | (with-current-buffer (erc-status-sidebar-get-buffer) | 432 | (with-current-buffer (erc-status-sidebar-get-buffer) |
| 419 | (setq window (get-buffer-window nil erc-status-sidebar-singular) | 433 | (dolist (window (get-buffer-window-list nil nil t)) |
| 420 | winstart (and window (window-start window))) | 434 | (push (cons window (window-start window)) windows)) |
| 421 | (erc-status-sidebar-writable | 435 | (erc-status-sidebar-writable |
| 422 | (delete-region (point-min) (point-max)) | 436 | (delete-region (point-min) (point-max)) |
| 423 | (goto-char (point-min)) | 437 | (goto-char (point-min)) |
| @@ -443,9 +457,8 @@ name stand out." | |||
| 443 | 0 cnlen 'help-echo | 457 | 0 cnlen 'help-echo |
| 444 | "mouse-1: switch to buffer in other window" channame) | 458 | "mouse-1: switch to buffer in other window" channame) |
| 445 | (funcall insert-fn channame chanbuf chanlist))) | 459 | (funcall insert-fn channame chanbuf chanlist))) |
| 446 | (when winstart | 460 | (when windows |
| 447 | (set-window-point window winstart) | 461 | (map-apply #'set-window-start windows)) |
| 448 | (with-selected-window window (recenter 0))) | ||
| 449 | (when (and erc-status-sidebar-highlight-active-buffer | 462 | (when (and erc-status-sidebar-highlight-active-buffer |
| 450 | (marker-buffer erc-status-sidebar--active-marker)) | 463 | (marker-buffer erc-status-sidebar--active-marker)) |
| 451 | (goto-char erc-status-sidebar--active-marker) | 464 | (goto-char erc-status-sidebar--active-marker) |
| @@ -519,14 +532,28 @@ highlighted." | |||
| 519 | erc-kill-server-hook | 532 | erc-kill-server-hook |
| 520 | erc-kick-hook | 533 | erc-kick-hook |
| 521 | erc-disconnected-hook | 534 | erc-disconnected-hook |
| 522 | erc-quit-hook)) | 535 | erc-quit-hook) |
| 536 | "Hooks to refresh the sidebar on. | ||
| 537 | This may be set locally in the status-sidebar buffer under | ||
| 538 | various conditions, like when the option | ||
| 539 | `erc-status-sidebar-highlight-active-buffer' is non-nil.") | ||
| 540 | |||
| 541 | (defvar erc-status-sidebar--highlight-refresh-triggers | ||
| 542 | '(window-selection-change-functions) | ||
| 543 | "Triggers enabled with `erc-status-sidebar-highlight-active-buffer'.") | ||
| 544 | |||
| 545 | (defun erc-status-sidebar--refresh-unless-input () | ||
| 546 | "Run `erc-status-sidebar-refresh' unless there are unread commands. | ||
| 547 | Also abstain when the user is interacting with the minibuffer." | ||
| 548 | (unless (or (input-pending-p) (minibuffer-window-active-p (selected-window))) | ||
| 549 | (erc-status-sidebar-refresh))) | ||
| 523 | 550 | ||
| 524 | (defun erc-status-sidebar--post-refresh (&rest _ignore) | 551 | (defun erc-status-sidebar--post-refresh (&rest _ignore) |
| 525 | "Schedule sidebar refresh for execution after command stack is cleared. | 552 | "Schedule sidebar refresh for execution after command stack is cleared. |
| 526 | 553 | ||
| 527 | Ignore arguments in IGNORE, allowing this function to be added to | 554 | Ignore arguments in IGNORE, allowing this function to be added to |
| 528 | hooks that invoke it with arguments." | 555 | hooks that invoke it with arguments." |
| 529 | (run-at-time 0 nil #'erc-status-sidebar-refresh)) | 556 | (run-at-time 0 nil #'erc-status-sidebar--refresh-unless-input)) |
| 530 | 557 | ||
| 531 | (defun erc-status-sidebar-mode--unhook () | 558 | (defun erc-status-sidebar-mode--unhook () |
| 532 | "Remove hooks installed by `erc-status-sidebar-mode'." | 559 | "Remove hooks installed by `erc-status-sidebar-mode'." |
| @@ -541,7 +568,7 @@ hooks that invoke it with arguments." | |||
| 541 | Note that preserve status needs to be reset when the window is | 568 | Note that preserve status needs to be reset when the window is |
| 542 | manually resized, so `erc-status-sidebar-mode' adds this function | 569 | manually resized, so `erc-status-sidebar-mode' adds this function |
| 543 | to the `window-configuration-change-hook'." | 570 | to the `window-configuration-change-hook'." |
| 544 | (when (and (eq (selected-window) (let (erc-status-sidebar-singular) | 571 | (when (and (eq (selected-window) (let (erc-status-sidebar--singular-p) |
| 545 | (erc-status-sidebar-get-window))) | 572 | (erc-status-sidebar-get-window))) |
| 546 | (fboundp 'window-preserve-size)) | 573 | (fboundp 'window-preserve-size)) |
| 547 | (unless (eq (window-total-width) (window-min-size nil t)) | 574 | (unless (eq (window-total-width) (window-min-size nil t)) |
| @@ -563,6 +590,10 @@ to the `window-configuration-change-hook'." | |||
| 563 | 590 | ||
| 564 | (add-hook 'window-configuration-change-hook | 591 | (add-hook 'window-configuration-change-hook |
| 565 | #'erc-status-sidebar-set-window-preserve-size nil t) | 592 | #'erc-status-sidebar-set-window-preserve-size nil t) |
| 593 | (when erc-status-sidebar-highlight-active-buffer | ||
| 594 | (setq-local erc-status-sidebar-refresh-triggers | ||
| 595 | `(,@erc-status-sidebar--highlight-refresh-triggers | ||
| 596 | ,@erc-status-sidebar-refresh-triggers))) | ||
| 566 | (dolist (hk erc-status-sidebar-refresh-triggers) | 597 | (dolist (hk erc-status-sidebar-refresh-triggers) |
| 567 | (add-hook hk #'erc-status-sidebar--post-refresh)) | 598 | (add-hook hk #'erc-status-sidebar--post-refresh)) |
| 568 | 599 | ||