diff options
| author | Craig Jennings <c@cjennings.net> | 2026-05-26 14:21:20 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-05-26 14:21:20 -0500 |
| commit | 6c7f9ae225b91dee81a04d2271a6648924c0f3cf (patch) | |
| tree | 2ca709a04afa25f7d106a425e8cf438f62ddd55d | |
| parent | fcf3e0f89f47cd377612406c62448b0bf626b389 (diff) | |
| download | dotemacs-6c7f9ae225b91dee81a04d2271a6648924c0f3cf.tar.gz dotemacs-6c7f9ae225b91dee81a04d2271a6648924c0f3cf.zip | |
feat(slack): open rooms in another window, never the selected one
slack-buffer-function defaulted to switch-to-buffer-other-window, which gives no real guarantee about placement: with three or more panes it picks a least-recently-used window, and it offers nothing that keeps Slack out of the window point is in. So opening a room in a split could land it wherever, including over the buffer I was working in.
I set slack-buffer-function to cj/slack--display-buffer, a pop-to-buffer call with inhibit-same-window and a reuse / use-some-window / pop-up-window action list. In a split it reuses one of the other windows and leaves the selected window alone; with a lone window it splits. Tests cover both the split-placement case and the selected-window-preserved invariant.
| -rw-r--r-- | modules/slack-config.el | 17 | ||||
| -rw-r--r-- | tests/test-slack-config-display.el | 48 |
2 files changed, 65 insertions, 0 deletions
diff --git a/modules/slack-config.el b/modules/slack-config.el index 48af9c93..0902ef35 100644 --- a/modules/slack-config.el +++ b/modules/slack-config.el @@ -102,6 +102,20 @@ (slack-ws-close) (message "Slack disconnected.")) +(defun cj/slack--display-buffer (buffer) + "Display Slack BUFFER in another window, never the selected one. +With a split, reuse one of the other windows rather than taking over the +window point is in or always spawning a fresh split; with a lone window, +split. Wired as `slack-buffer-function' so opening a room or thread lands +beside the current work instead of clobbering it. The default +`switch-to-buffer-other-window' picks a least-recently-used window with three +or more panes; this pins the choice to any non-selected window." + (pop-to-buffer buffer + '((display-buffer-reuse-window + display-buffer-use-some-window + display-buffer-pop-up-window) + (inhibit-same-window . t)))) + (use-package slack :defer t :commands (slack-start slack-select-rooms slack-select-unread-rooms @@ -114,6 +128,9 @@ ;; Re-enable if emojify/circe fix the interaction. (2026-03-16) (slack-buffer-emojify nil) (slack-prefer-current-team t) + ;; Open rooms/threads in another window, never the selected one (see + ;; cj/slack--display-buffer) so Slack lands beside the current work in a split. + (slack-buffer-function #'cj/slack--display-buffer) :config (setq slack-message-custom-notifier #'cj/slack-notify)) diff --git a/tests/test-slack-config-display.el b/tests/test-slack-config-display.el new file mode 100644 index 00000000..24128ddc --- /dev/null +++ b/tests/test-slack-config-display.el @@ -0,0 +1,48 @@ +;;; test-slack-config-display.el --- Slack buffer placement -*- lexical-binding: t; -*- + +;;; Commentary: +;; cj/slack--display-buffer is wired as `slack-buffer-function' so opening a +;; Slack room or thread shows it in another window and never replaces the +;; selected window's buffer. These exercise the placement directly with plain +;; buffers (no live Slack), using a side-by-side split so the window math is +;; reliable under `emacs --batch'. + +;;; Code: + +(require 'ert) +(require 'slack-config) + +(ert-deftest test-slack-config-display-buffer-uses-other-window-when-split () + "Normal: with a split, the buffer lands in a non-selected window." + (let ((a (get-buffer-create "*slack-disp-a*")) + (b (get-buffer-create "*slack-disp-b*"))) + (unwind-protect + (save-window-excursion + (delete-other-windows) + (set-window-buffer (selected-window) a) + (let ((win-a (selected-window))) + (split-window win-a nil t) ;; side-by-side, batch-friendly + (cj/slack--display-buffer b) + (let ((win-b (get-buffer-window b))) + (should win-b) + (should-not (eq win-b win-a))))) + (ignore-errors (kill-buffer a)) + (ignore-errors (kill-buffer b))))) + +(ert-deftest test-slack-config-display-buffer-keeps-selected-window () + "Boundary: displaying does not replace the selected window's buffer." + (let ((a (get-buffer-create "*slack-disp-a*")) + (b (get-buffer-create "*slack-disp-b*"))) + (unwind-protect + (save-window-excursion + (delete-other-windows) + (set-window-buffer (selected-window) a) + (let ((win-a (selected-window))) + (split-window win-a nil t) + (cj/slack--display-buffer b) + (should (eq (window-buffer win-a) a)))) + (ignore-errors (kill-buffer a)) + (ignore-errors (kill-buffer b))))) + +(provide 'test-slack-config-display) +;;; test-slack-config-display.el ends here |
