help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

tabbar: Grouping buffers by windows


From: Yuri Khan
Subject: tabbar: Grouping buffers by windows
Date: Thu, 19 Sep 2013 22:06:59 +0700

Hello All,

I am using tabbar-mode to visualize my buffers. Additionally, I map
M-S-<left> and M-S-<right> to tabbar-backward-tab and
tabbar-forward-tab, respectively.

===
(global-set-key (kbd "M-S-<right>") 'tabbar-forward-tab)
(global-set-key (kbd "M-S-<left>") 'tabbar-backward-tab)
(tabbar-mode 1)
(tabbar-mwheel-mode 0)
===

In the default configuration, every window displays every tab. This
poses three problems:

* If the buffer I want is more than three tabs away from where I am, I
reach for the mouse, which is annoying.
* When the tabbar grows beyond the screen width, I cannot see all
tabs. I cannot choose which direction to go, and I cannot click
because the tab I want is offscreen and scrolling the tabbar is
cumbersome.
* I often split my frame into two windows, and I often have two or
three frames dedicated to different tasks. (For example, I might have
a separate frame where I do my .emacs.d customizations, a separate
frame for the program I’m writing (with one frame for a .h file and
another for .cpp), and a third frame for the library I’m using.) I
usually don’t want to mix buffers — in my mind, in most cases, each
buffer logically belongs to a single window in a single frame; a
buffer should show up in a different window only if I explicitly ask
for it.

Therefore, I want tabbar to show in each window only those tabs that
“belong” to that window.


After some trying and tweaking, I decided on the following heuristics
for the “belong” relationship:

* Each buffer remembers and maintains the last window where it was displayed.
* Each buffer also maintains a list of windows it is “pinned” to.
(Pinning and unpinning are explicit user commands.)
* Each window’s tabbar shows tabs for the buffer that is currently
displayed in that window, all buffers pinned to that window, and all
buffers that were last displayed in that window.


I have implemented this logic and it seems to work for me. I’d be glad
if somebody much more familiar with Elisp reviewed my code and gave
comments if I am doing something wrong or suboptimal.


Here’s the code from my init.el:

===
(defvar yk-buffer-last-window nil "Window the buffer was last displayed in")
(make-variable-buffer-local 'yk-buffer-last-window)

(defun yk-tabbar-window-configuration-change ()
  (setq yk-buffer-last-window (selected-window)))
(add-hook 'window-configuration-change-hook
'yk-tabbar-window-configuration-change)

(defadvice select-window (after yk-tabbar-select-window (window
&optional norecord))
  (with-current-buffer (window-buffer window)
    (setq yk-buffer-last-window window)))
(ad-activate 'select-window)


(defvar yk-buffer-pin-window-list nil "Windows the buffer is pinned to")
(make-variable-buffer-local 'yk-buffer-pin-window-list)

(defun yk-tabbar-pin-buffer ()
  "Pin the current buffer to the selected window."
  (interactive)
  (add-to-list 'yk-buffer-pin-window-list (selected-window) nil 'eq))

(defun yk-tabbar-unpin-buffer ()
  "Unpin the current buffer from the selected window."
  (interactive)
  (delq (selected-window) yk-buffer-pin-window-list))


;;; The buffer’s list of groups is, in this order:
;;; 1. The currently selected window, if it is displaying this buffer.
;;; 2. All other windows (if any) that are displaying this buffer.
;;; 3. The windows that this buffer is pinned to (if any).
;;; 4. The window that this buffer was last displayed in (if any).
;;; 5. The default group (always).
(defun yk-tabbar-buffer-groups ()
  (let* ((window (selected-window))
         (buffer (current-buffer))
         (windows (get-buffer-window-list buffer nil t)))
    (append
     (mapcar 'prin1-to-string
             (append (and (eq (window-buffer window) buffer) `(,window))     ; 1
                     (remq window windows)                                   ; 2
                     yk-buffer-pin-window-list                               ; 3
                     (and yk-buffer-last-window `(,yk-buffer-last-window)))) ; 4
     '("default"))))                                                         ; 5
(setq tabbar-buffer-groups-function 'yk-tabbar-buffer-groups)
===



reply via email to

[Prev in Thread] Current Thread [Next in Thread]