diff options
| author | F. Jason Park | 2023-05-04 00:01:11 -0700 |
|---|---|---|
| committer | F. Jason Park | 2023-07-13 18:45:31 -0700 |
| commit | ded35c2da4da52641ec99927347cd50b736b9577 (patch) | |
| tree | b8f865ed50f352031da634170d3244d41e427bf6 /lisp | |
| parent | 3c70e85d362262d096301e7663a11ca8c392f526 (diff) | |
| download | emacs-ded35c2da4da52641ec99927347cd50b736b9577.tar.gz emacs-ded35c2da4da52641ec99927347cd50b736b9577.zip | |
Add erc-status-sidebar integration to erc-speedbar
* lisp/erc/erc-speedbar.el: Require `erc-button' atop file and don't
bother loading `dframe', which `speedbar' handles for us.
(erc-speedbar): Explain that `nickbar' is the module for this group
and library for the benefit of those who run M-x customize-group.
(erc-speedbar-nicknames-window-width): New option.
(erc-speedbar-hide-mode-topic): New option determining whether to hide
the mode and topic.
(erc-speedbar-my-nick-face): New option for determining face to use
when displaying user's current nick.
(erc-speedbar-browser): Call `erc-install-speedbar-variables'
explicitly and remove top-level `with-eval-after-load'.
(erc-speedbar-insert-target): Add parenthesized channel count after
channel name in server and channel views.
(erc-speedbar-expand-channel): Hide mode and topic depending on option
`erc-speedbar-hide-mode-topic' and pass buffer to
`erc-speedbar-insert-user'.
(erc-speedbar--nick-face-function): New internal function-valued
variable.
(erc-speedbar--highlight-self-and-ops): New function to serve as
default value for `erc-speedbar--nick-face-function'.
(erc-speedbar--on-click): Dispatch `erc-nick-popup' after trimming
status chars.
(erc-speedbar-insert-user): Revise doc string. Call
`erc-speedbar--nick-face-function' to determine face. Change
token for both expansion and on-click text props. Assign
`erc-speedbar--on-click' as the mouse handler for nick items.
(erc-speedbar--buffer-options): Variable to override options locally
in speedbar buffer.
(erc-speedbar--hidden-speedbar-frame): Add variable to hold original
`speedbar-frame' before spoofing by setting to selected frame
containing window showing ERC buffer.
(erc-speedbar--emulate-sidebar-set-window-preserve-size,
erc-speedbar--status-sidebar-mode--unhook): Add function
to ensure status sidebar is showing correctly and helper to
unregister from hook on teardown.
(erc-speedbar--emulate-sidebar): Add function to control sidebar
nicknames setup.
(erc-speedbar--toggle-nicknames-sidebar): Add toggle function
for speedbar or emulated sidebar.
(erc-speedbar--ensure): Add helper function to show speedbar if it's
hidden or create one if none exists.
(erc-nickbar-mode, erc-nickbar-enable, erc-nickbar-disable):
Add new mini module.
(erc-speedbar--dframe-controlled) Add function to overwrite
`speedbar-frame-mode' as `dframe-controlled' in speedbar buffer.
(erc-speedbar-toggle-nicknames-window-lock,
erc-speedbar-close-nicknames-window): Add commands to close speedbar
window and toggle its cyclability.
(erc-speedbar--compose-nicks-face): Add helper for nicks integration.
* test/lisp/erc/erc-scenarios-status-sidebar.el
(erc-scenarios-status-sidebar--nickbar): New test. (Bug#63595)
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/erc/erc-speedbar.el | 287 |
1 files changed, 269 insertions, 18 deletions
diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el index a9443e0ea17..f5fbaac767d 100644 --- a/lisp/erc/erc-speedbar.el +++ b/lisp/erc/erc-speedbar.el | |||
| @@ -32,20 +32,31 @@ | |||
| 32 | ;; update-channel, update-nick, remove-nick-from-channel, ... | 32 | ;; update-channel, update-nick, remove-nick-from-channel, ... |
| 33 | ;; * Use indicator-strings for op/voice | 33 | ;; * Use indicator-strings for op/voice |
| 34 | ;; * Extract/convert face notes field from bbdb if available | 34 | ;; * Extract/convert face notes field from bbdb if available |
| 35 | ;; * Write tests that run in a term-mode subprocess | ||
| 35 | ;; | 36 | ;; |
| 36 | ;;; Code: | 37 | ;;; Code: |
| 37 | 38 | ||
| 38 | (require 'erc) | 39 | (require 'erc) |
| 39 | (require 'erc-goodies) | 40 | (require 'erc-goodies) |
| 41 | (require 'erc-button) | ||
| 40 | (require 'speedbar) | 42 | (require 'speedbar) |
| 41 | (condition-case nil (require 'dframe) (error nil)) | ||
| 42 | 43 | ||
| 43 | ;;; Customization: | 44 | ;;; Customization: |
| 44 | 45 | ||
| 45 | (defgroup erc-speedbar nil | 46 | (defgroup erc-speedbar nil |
| 46 | "Integration of ERC in the Speedbar." | 47 | "Speedbar integration for ERC. |
| 48 | To open an ERC-flavored speedbar in a separate frame, run the | ||
| 49 | command `erc-speedbar-browser'. To use a window-based proxy | ||
| 50 | instead, run \\[erc-nickbar-mode] in a connected ERC buffer or | ||
| 51 | put `nickbar' in `erc-modules' before connecting. See Info | ||
| 52 | node `(speedbar) Top' for more about the underlying integration." | ||
| 47 | :group 'erc) | 53 | :group 'erc) |
| 48 | 54 | ||
| 55 | (defcustom erc-speedbar-nicknames-window-width 18 | ||
| 56 | "Default width of the nicknames sidebar (in columns)." | ||
| 57 | :package-version '(ERC . "5.6") ; FIXME sync on release | ||
| 58 | :type 'integer) | ||
| 59 | |||
| 49 | (defcustom erc-speedbar-sort-users-type 'activity | 60 | (defcustom erc-speedbar-sort-users-type 'activity |
| 50 | "How channel nicknames are sorted. | 61 | "How channel nicknames are sorted. |
| 51 | 62 | ||
| @@ -56,6 +67,23 @@ nil - Do not sort users" | |||
| 56 | (const :tag "Sort users alphabetically" alphabetical) | 67 | (const :tag "Sort users alphabetically" alphabetical) |
| 57 | (const :tag "Do not sort users" nil))) | 68 | (const :tag "Do not sort users" nil))) |
| 58 | 69 | ||
| 70 | (defcustom erc-speedbar-hide-mode-topic 'headerline | ||
| 71 | "Hide mode and topic lines." | ||
| 72 | :package-version '(ERC . "5.6") ; FIXME sync on release | ||
| 73 | :type '(choice (const :tag "Always show" nil) | ||
| 74 | (const :tag "Always hide" t) | ||
| 75 | (const :tag "Omit when headerline visible" headerline))) | ||
| 76 | |||
| 77 | (defcustom erc-speedbar-my-nick-face t | ||
| 78 | "A face to use for your nickname. | ||
| 79 | When the value is t, ERC uses `erc-current-nick-face' if | ||
| 80 | `erc-match' has been loaded and `erc-my-nick-face' otherwise. | ||
| 81 | When using the `nicks' module, you can see your nick as it | ||
| 82 | appears to others by coordinating with the option | ||
| 83 | `erc-nicks-skip-faces'." | ||
| 84 | :package-version '(ERC . "5.6") ; FIXME sync on release | ||
| 85 | :type '(choice face (const :tag "Current nick or own speaker face" t))) | ||
| 86 | |||
| 59 | (defvar erc-speedbar-key-map nil | 87 | (defvar erc-speedbar-key-map nil |
| 60 | "Keymap used when in erc display mode.") | 88 | "Keymap used when in erc display mode.") |
| 61 | 89 | ||
| @@ -88,10 +116,6 @@ nil - Do not sort users" | |||
| 88 | (looking-at "[0-9]+: *.-. "))]) | 116 | (looking-at "[0-9]+: *.-. "))]) |
| 89 | "Additional menu-items to add to speedbar frame.") | 117 | "Additional menu-items to add to speedbar frame.") |
| 90 | 118 | ||
| 91 | ;; Make sure our special speedbar major mode is loaded | ||
| 92 | (with-eval-after-load 'speedbar | ||
| 93 | (erc-install-speedbar-variables)) | ||
| 94 | |||
| 95 | ;;; ERC hierarchy display method | 119 | ;;; ERC hierarchy display method |
| 96 | ;;;###autoload | 120 | ;;;###autoload |
| 97 | (defun erc-speedbar-browser () | 121 | (defun erc-speedbar-browser () |
| @@ -99,6 +123,7 @@ nil - Do not sort users" | |||
| 99 | This will add a speedbar major display mode." | 123 | This will add a speedbar major display mode." |
| 100 | (interactive) | 124 | (interactive) |
| 101 | (require 'speedbar) | 125 | (require 'speedbar) |
| 126 | (erc-install-speedbar-variables) | ||
| 102 | ;; Make sure that speedbar is active | 127 | ;; Make sure that speedbar is active |
| 103 | (speedbar-frame-mode 1) | 128 | (speedbar-frame-mode 1) |
| 104 | ;; Now, throw us into Info mode on speedbar. | 129 | ;; Now, throw us into Info mode on speedbar. |
| @@ -169,12 +194,18 @@ This will add a speedbar major display mode." | |||
| 169 | t))))) | 194 | t))))) |
| 170 | 195 | ||
| 171 | (defun erc-speedbar-insert-target (buffer depth) | 196 | (defun erc-speedbar-insert-target (buffer depth) |
| 172 | (if (with-current-buffer buffer | 197 | (if (erc--target-channel-p (buffer-local-value 'erc--target buffer)) |
| 173 | (erc-channel-p (erc-default-target))) | 198 | (progn |
| 174 | (speedbar-make-tag-line | 199 | (speedbar-make-tag-line |
| 175 | 'bracket ?+ 'erc-speedbar-expand-channel buffer | 200 | 'bracket ?+ 'erc-speedbar-expand-channel buffer |
| 176 | (buffer-name buffer) 'erc-speedbar-goto-buffer buffer nil | 201 | (erc--target-string (buffer-local-value 'erc--target buffer)) |
| 177 | depth) | 202 | 'erc-speedbar-goto-buffer buffer nil |
| 203 | depth) | ||
| 204 | (save-excursion | ||
| 205 | (forward-line -1) | ||
| 206 | (let ((table (buffer-local-value 'erc-channel-users buffer))) | ||
| 207 | (speedbar-add-indicator (format "(%d)" (hash-table-count table))) | ||
| 208 | (rx "(" (+ (any "0-9")) ")")))) | ||
| 178 | ;; Query target | 209 | ;; Query target |
| 179 | (speedbar-make-tag-line | 210 | (speedbar-make-tag-line |
| 180 | nil nil nil nil | 211 | nil nil nil nil |
| @@ -220,6 +251,13 @@ INDENT is the current indentation level." | |||
| 220 | 'angle ?i nil nil | 251 | 'angle ?i nil nil |
| 221 | (concat "Topic: " topic) nil nil nil | 252 | (concat "Topic: " topic) nil nil nil |
| 222 | (1+ indent))) | 253 | (1+ indent))) |
| 254 | (unless (pcase erc-speedbar-hide-mode-topic | ||
| 255 | ('nil 'show) | ||
| 256 | ('headerline (null erc-header-line-format))) | ||
| 257 | (save-excursion | ||
| 258 | (goto-char (point-max)) | ||
| 259 | (forward-line (if (string= topic "") -1 -2)) | ||
| 260 | (put-text-property (pos-bol) (point-max) 'invisible t))) | ||
| 223 | (let ((names (cond ((eq erc-speedbar-sort-users-type 'alphabetical) | 261 | (let ((names (cond ((eq erc-speedbar-sort-users-type 'alphabetical) |
| 224 | (erc-sort-channel-users-alphabetically | 262 | (erc-sort-channel-users-alphabetically |
| 225 | (with-current-buffer channel | 263 | (with-current-buffer channel |
| @@ -233,17 +271,52 @@ INDENT is the current indentation level." | |||
| 233 | (when names | 271 | (when names |
| 234 | (speedbar-with-writable | 272 | (speedbar-with-writable |
| 235 | (dolist (entry names) | 273 | (dolist (entry names) |
| 236 | (erc-speedbar-insert-user entry ?+ (1+ indent)))))))))) | 274 | (erc-speedbar-insert-user entry ?+ (1+ indent) channel))))))))) |
| 237 | ((string-search "-" text) | 275 | ((string-search "-" text) |
| 238 | (speedbar-change-expand-button-char ?+) | 276 | (speedbar-change-expand-button-char ?+) |
| 239 | (speedbar-delete-subblock indent)) | 277 | (speedbar-delete-subblock indent)) |
| 240 | (t (error "Ooops... not sure what to do"))) | 278 | (t (error "Ooops... not sure what to do"))) |
| 241 | (speedbar-center-buffer-smartly)) | 279 | (speedbar-center-buffer-smartly)) |
| 242 | 280 | ||
| 243 | (defun erc-speedbar-insert-user (entry exp-char indent) | 281 | (defvar erc-speedbar--nick-face-function #'erc-speedbar--highlight-self-and-ops |
| 282 | "Function called when finding a face for fontifying nicks. | ||
| 283 | Called with the proposed nick, the `erc-server-user', and the | ||
| 284 | `erc-channel-user'. Should return any valid face, possibly | ||
| 285 | composed or anonymous, or nil.") | ||
| 286 | |||
| 287 | (defun erc-speedbar--highlight-self-and-ops (buffer user cuser) | ||
| 288 | "Highlight own nick and op'd users in the speedbar." | ||
| 289 | (with-current-buffer buffer | ||
| 290 | (if (erc-current-nick-p (erc-server-user-nickname user)) | ||
| 291 | (pcase erc-speedbar-my-nick-face | ||
| 292 | ('t (if (facep 'erc-current-nick-face) | ||
| 293 | 'erc-current-nick-face | ||
| 294 | 'erc-my-nick-face)) | ||
| 295 | (v v)) | ||
| 296 | ;; FIXME overload `erc-channel-user-owner-p' and friends to | ||
| 297 | ;; accept an `erc-channel-user' object and replace this unrolled | ||
| 298 | ;; stuff with a single call to `erc-get-user-mode-prefix'. | ||
| 299 | (and cuser (or (erc-channel-user-owner cuser) | ||
| 300 | (erc-channel-user-admin cuser) | ||
| 301 | (erc-channel-user-op cuser) | ||
| 302 | (erc-channel-user-halfop cuser) | ||
| 303 | (erc-channel-user-voice cuser)) | ||
| 304 | erc-button-nickname-face)))) | ||
| 305 | |||
| 306 | (defun erc-speedbar--on-click (nick sbtoken _indent) | ||
| 307 | ;; 0: finger, 1: name, 2: info, 3: buffer-name | ||
| 308 | (with-current-buffer (nth 3 sbtoken) | ||
| 309 | (erc-nick-popup (string-trim-left nick "[~&@%+]+")))) | ||
| 310 | |||
| 311 | (defun erc-speedbar-insert-user (entry exp-char indent &optional buffer) | ||
| 244 | "Insert one user based on the channel member list ENTRY. | 312 | "Insert one user based on the channel member list ENTRY. |
| 245 | EXP-CHAR is the expansion character to use. | 313 | Expect EXP-CHAR to be the expansion character to use, INDENT the |
| 246 | INDENT is the current indentation level." | 314 | current indentation level, and BUFFER the associated channel or |
| 315 | query buffer. Set the `speedbar-function' text property to | ||
| 316 | `erc-speedbar--on-click', which is called with the formatted | ||
| 317 | nick, a so-called \"token\", and the indent level. The token is | ||
| 318 | a list of four items: the userhost, the GECOS, the current | ||
| 319 | `erc-server-user' info slot, and the associated buffer." | ||
| 247 | (let* ((user (car entry)) | 320 | (let* ((user (car entry)) |
| 248 | (cuser (cdr entry)) | 321 | (cuser (cdr entry)) |
| 249 | (nick (erc-server-user-nickname user)) | 322 | (nick (erc-server-user-nickname user)) |
| @@ -255,11 +328,12 @@ INDENT is the current indentation level." | |||
| 255 | (op (and cuser (erc-channel-user-op cuser))) | 328 | (op (and cuser (erc-channel-user-op cuser))) |
| 256 | (nick-str (concat (if op "@" "") (if voice "+" "") nick)) | 329 | (nick-str (concat (if op "@" "") (if voice "+" "") nick)) |
| 257 | (finger (concat login (when (or login host) "@") host)) | 330 | (finger (concat login (when (or login host) "@") host)) |
| 258 | (sbtoken (list finger name info))) | 331 | (sbtoken (list finger name info (buffer-name buffer)))) |
| 259 | (if (or login host name info) ; we want to be expandable | 332 | (if (or login host name info) ; we want to be expandable |
| 260 | (speedbar-make-tag-line | 333 | (speedbar-make-tag-line |
| 261 | 'bracket ?+ 'erc-speedbar-expand-user sbtoken | 334 | 'bracket ?+ 'erc-speedbar-expand-user sbtoken |
| 262 | nick-str nil sbtoken nil | 335 | nick-str #'erc-speedbar--on-click sbtoken |
| 336 | (funcall erc-speedbar--nick-face-function buffer user cuser) | ||
| 263 | indent) | 337 | indent) |
| 264 | (when (equal exp-char ?-) | 338 | (when (equal exp-char ?-) |
| 265 | (forward-line -1) | 339 | (forward-line -1) |
| @@ -357,6 +431,183 @@ The INDENT level is ignored." | |||
| 357 | (t | 431 | (t |
| 358 | (message "%s" txt))))) | 432 | (message "%s" txt))))) |
| 359 | 433 | ||
| 434 | |||
| 435 | ;;;; Status-sidebar integration | ||
| 436 | |||
| 437 | (defvar erc-track-mode) | ||
| 438 | (defvar erc-track--switch-fallback-blockers) | ||
| 439 | (defvar erc-status-sidebar-buffer-name) | ||
| 440 | (declare-function erc-status-sidebar-set-window-preserve-size | ||
| 441 | "erc-status-sidebar" nil) | ||
| 442 | (declare-function erc-status-sidebar-mode--unhook "erc-status-sidebar" nil) | ||
| 443 | |||
| 444 | (defvar erc-speedbar--buffer-options | ||
| 445 | '((speedbar-update-flag . t) | ||
| 446 | (speedbar-use-images . nil) | ||
| 447 | (speedbar-hide-button-brackets-flag . t))) | ||
| 448 | |||
| 449 | (defvar erc-speedbar--hidden-speedbar-frame nil) | ||
| 450 | |||
| 451 | (defun erc-speedbar--emulate-sidebar-set-window-preserve-size () | ||
| 452 | (let ((erc-status-sidebar-buffer-name (buffer-name speedbar-buffer)) | ||
| 453 | (display-buffer-overriding-action | ||
| 454 | `(display-buffer-in-side-window | ||
| 455 | . ((side . right) | ||
| 456 | (window-width . ,erc-speedbar-nicknames-window-width))))) | ||
| 457 | (erc-status-sidebar-set-window-preserve-size) | ||
| 458 | (when-let ((window (get-buffer-window speedbar-buffer))) | ||
| 459 | (set-window-parameter window 'no-other-window nil) | ||
| 460 | (internal-show-cursor window t)))) | ||
| 461 | |||
| 462 | (defun erc-speedbar--status-sidebar-mode--unhook () | ||
| 463 | "Remove hooks installed by `erc-status-sidebar-mode'." | ||
| 464 | (remove-hook 'window-configuration-change-hook | ||
| 465 | #'erc-speedbar--emulate-sidebar-set-window-preserve-size)) | ||
| 466 | |||
| 467 | (defun erc-speedbar--emulate-sidebar () | ||
| 468 | (require 'erc-status-sidebar) | ||
| 469 | (cl-assert speedbar-frame) | ||
| 470 | (cl-assert (eq speedbar-buffer (current-buffer))) | ||
| 471 | (cl-assert (eq speedbar-frame (selected-frame))) | ||
| 472 | (setq erc-speedbar--hidden-speedbar-frame speedbar-frame | ||
| 473 | dframe-controlled #'erc-speedbar--dframe-controlled) | ||
| 474 | (add-hook 'window-configuration-change-hook | ||
| 475 | #'erc-speedbar--emulate-sidebar-set-window-preserve-size nil t) | ||
| 476 | (add-hook 'kill-buffer-hook | ||
| 477 | #'erc-speedbar--status-sidebar-mode--unhook nil t) | ||
| 478 | (with-current-buffer speedbar-buffer | ||
| 479 | (pcase-dolist (`(,var . ,val) erc-speedbar--buffer-options) | ||
| 480 | (set (make-local-variable var) val))) | ||
| 481 | (when (memq 'nicks erc-modules) | ||
| 482 | (with-current-buffer speedbar-buffer | ||
| 483 | (add-function :around (local 'erc-speedbar--nick-face-function) | ||
| 484 | #'erc-speedbar--compose-nicks-face)))) | ||
| 485 | |||
| 486 | (defun erc-speedbar--toggle-nicknames-sidebar (arg) | ||
| 487 | (let ((force (numberp arg))) | ||
| 488 | (if speedbar-buffer | ||
| 489 | (progn | ||
| 490 | (cl-assert (buffer-live-p speedbar-buffer)) | ||
| 491 | (if (or (and force (< arg 0)) | ||
| 492 | (and (not force) (get-buffer-window speedbar-buffer nil))) | ||
| 493 | (erc-speedbar-close-nicknames-window nil) | ||
| 494 | (when (or (not force) (>= arg 0)) | ||
| 495 | (with-selected-frame speedbar-frame | ||
| 496 | (erc-speedbar--emulate-sidebar-set-window-preserve-size))))) | ||
| 497 | (when (or (not force) (>= arg 0)) | ||
| 498 | (let ((speedbar-frame-parameters (backquote-list* | ||
| 499 | '(visibility . nil) | ||
| 500 | '(no-other-frame . t) | ||
| 501 | speedbar-frame-parameters)) | ||
| 502 | (speedbar-after-create-hook #'erc-speedbar--emulate-sidebar)) | ||
| 503 | (erc-speedbar-browser) | ||
| 504 | ;; If we put the remaining parts in the "create hook" along | ||
| 505 | ;; with everything else, the frame with `window-main-window' | ||
| 506 | ;; gets raised and steals focus if you've switched away from | ||
| 507 | ;; Emacs in the meantime. | ||
| 508 | (make-frame-invisible speedbar-frame) | ||
| 509 | (select-frame (setq speedbar-frame (previous-frame))) | ||
| 510 | (erc-speedbar--emulate-sidebar-set-window-preserve-size)))))) | ||
| 511 | |||
| 512 | (defun erc-speedbar--ensure (&optional force) | ||
| 513 | (when (or (erc-server-buffer) force) | ||
| 514 | (when erc-track-mode | ||
| 515 | (cl-pushnew '(derived-mode . speedbar-mode) | ||
| 516 | erc-track--switch-fallback-blockers :test #'equal)) | ||
| 517 | (erc-speedbar--toggle-nicknames-sidebar +1) | ||
| 518 | (speedbar-enable-update))) | ||
| 519 | |||
| 520 | ;;;###autoload(autoload 'erc-nickbar-mode "erc-speedbar" nil t) | ||
| 521 | (define-erc-module nickbar nil | ||
| 522 | "Show nicknames in a side window. | ||
| 523 | When enabling, create a speedbar session if one doesn't exist and | ||
| 524 | show its buffer in an `erc-status-sidebar' window instead of a | ||
| 525 | separate frame. When disabling, close the window or, with a | ||
| 526 | negative prefix arg, destroy the session. | ||
| 527 | |||
| 528 | WARNING: this module may produce unwanted side effects, like the | ||
| 529 | raising of frames or the stealing of input focus. If you witness | ||
| 530 | such an occurrence, and can reproduce it, please file a bug | ||
| 531 | report with \\[erc-bug]." | ||
| 532 | ((add-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure) | ||
| 533 | (erc-speedbar--ensure) | ||
| 534 | (unless (or erc--updating-modules-p | ||
| 535 | (and-let* ((speedbar-buffer) | ||
| 536 | (win (get-buffer-window speedbar-buffer 'all-frames)) | ||
| 537 | ((eq speedbar-frame (window-frame win)))))) | ||
| 538 | (if speedbar-buffer | ||
| 539 | (erc-speedbar--ensure 'force) | ||
| 540 | (setq erc-nickbar-mode nil) | ||
| 541 | (when (derived-mode-p 'erc-mode) | ||
| 542 | (erc-error "Not initializing `erc-nickbar-mode' in %s" | ||
| 543 | (current-buffer)))))) | ||
| 544 | ((remove-hook 'erc--setup-buffer-hook #'erc-speedbar--ensure) | ||
| 545 | (speedbar-disable-update) | ||
| 546 | (when erc-track-mode | ||
| 547 | (setq erc-track--switch-fallback-blockers | ||
| 548 | (remove '(derived-mode . speedbar-mode) | ||
| 549 | erc-track--switch-fallback-blockers))) | ||
| 550 | (erc-speedbar--toggle-nicknames-sidebar -1) | ||
| 551 | (when-let ((arg erc--module-toggle-prefix-arg) | ||
| 552 | ((numberp arg)) | ||
| 553 | ((< arg 0))) | ||
| 554 | (erc-speedbar-close-nicknames-window 'kill)))) | ||
| 555 | |||
| 556 | (defun erc-speedbar--dframe-controlled (arg) | ||
| 557 | (when (and erc-speedbar--hidden-speedbar-frame (numberp arg) (< arg 0)) | ||
| 558 | (when erc-nickbar-mode | ||
| 559 | (erc-nickbar-mode -1)) | ||
| 560 | (setq speedbar-frame erc-speedbar--hidden-speedbar-frame | ||
| 561 | erc-speedbar--hidden-speedbar-frame nil) | ||
| 562 | ;; It's unknown whether leaving the frame invisible interferes | ||
| 563 | ;; with the upstream teardown procedure. | ||
| 564 | (when (display-graphic-p) | ||
| 565 | (make-frame-visible speedbar-frame)) | ||
| 566 | (speedbar-frame-mode arg) | ||
| 567 | (when speedbar-buffer | ||
| 568 | (kill-buffer speedbar-buffer) | ||
| 569 | (setq speedbar-buffer nil)))) | ||
| 570 | |||
| 571 | (defun erc-speedbar-toggle-nicknames-window-lock () | ||
| 572 | "Toggle whether nicknames window is selectable with \\[other-window]." | ||
| 573 | (interactive) | ||
| 574 | (unless erc-nickbar-mode | ||
| 575 | (user-error "`erc-nickbar-mode' inactive")) | ||
| 576 | (when-let ((window (get-buffer-window speedbar-buffer))) | ||
| 577 | (let ((val (window-parameter window 'no-other-window))) | ||
| 578 | (set-window-parameter window 'no-other-window (not val)) | ||
| 579 | (message "nick-window: %s" (if val "selectable" "protected"))))) | ||
| 580 | |||
| 581 | (defun erc-speedbar-close-nicknames-window (kill) | ||
| 582 | (interactive "P") | ||
| 583 | (if kill | ||
| 584 | (with-current-buffer speedbar-buffer | ||
| 585 | (dframe-close-frame) | ||
| 586 | (cl-assert (not erc-nickbar-mode)) | ||
| 587 | (setq erc-speedbar--hidden-speedbar-frame nil)) | ||
| 588 | (dolist (window (get-buffer-window-list speedbar-buffer nil t)) | ||
| 589 | (unless (frame-root-window-p window) | ||
| 590 | (when erc-speedbar--hidden-speedbar-frame | ||
| 591 | (cl-assert (not (eq (window-frame window) | ||
| 592 | erc-speedbar--hidden-speedbar-frame)))) | ||
| 593 | (delete-window window))))) | ||
| 594 | |||
| 595 | |||
| 596 | ;;;; Nicks integration | ||
| 597 | |||
| 598 | (declare-function erc-nicks--highlight "erc-nicks" (nickname &optional face)) | ||
| 599 | |||
| 600 | (defun erc-speedbar--compose-nicks-face (orig buffer user cuser) | ||
| 601 | (require 'erc-nicks) | ||
| 602 | (let ((rv (funcall orig buffer user cuser))) | ||
| 603 | (if-let ((nick (erc-server-user-nickname user)) | ||
| 604 | (face (with-current-buffer buffer | ||
| 605 | (erc-nicks--highlight nick rv))) | ||
| 606 | ((not (eq face erc-button-nickname-face)))) | ||
| 607 | (cons face (ensure-list rv)) | ||
| 608 | rv))) | ||
| 609 | |||
| 610 | |||
| 360 | (provide 'erc-speedbar) | 611 | (provide 'erc-speedbar) |
| 361 | ;;; erc-speedbar.el ends here | 612 | ;;; erc-speedbar.el ends here |
| 362 | ;; | 613 | ;; |