УВАГА: Групування буферів на основі кадру - це безпосередня реалізація концепцій та вибору частин коду, розроблених / написаних Альпом Акером у бібліотеці кадрів-буфів: https://github.com/alpaker/Frame-Bufs
Нижче наводиться приклад того, як tabbar.el
динамічно використовувати вкладки / буфери бібліотеки та групи на основі кадру шляхом додавання вкладок / буферів за допомогою C-c C-a
або видалення вкладок / буферів за допомогою C-c C-n
. Є лише дві (2) групи - пов'язані з поточним кадром (тобто "A"
), а НЕ пов'язані з поточним кадром (тобто "N"
). Групи є рамково-локальними, це означає, що кожен кадр може мати власну групування. Спеціальне групування можна скинути за допомогою C-c C-r
. Перехід між асоційованими та неасоційованими групами за допомогою C-tab
. Перейдіть на наступну вкладку / буфер у поточній групі за допомогою M-s-right
. Перейдіть на попередню вкладку / буфер у поточній групі за допомогою M-s-left
.
Вкладки / буфери можна додавати або видаляти програмно за допомогою my-add-buffer
та my-remove-buffer
. Для прикладу того, як відкрити певні буфери у вибраних кадрах, перегляньте відповідний потік під назвою Як перехопити файл перед його відкриттям та вирішити, який кадр : /programming//a/18371427/2112489 Функцію my-add-buffer
потрібно було б бути включеним у відповідні місця коду у вищенаведеному посиланні, якщо користувач вирішив реалізувати цю функцію.
Користувач, можливо, захоче створити запис у користувальницькому режимі, mode-line-format
який відображає ім'я поточної групи вкладок у рядку режиму, включивши такий фрагмент: (:eval (when tabbar-mode (format "%s" (tabbar-current-tabset t))))
Настроювання рядка режиму більш детально, однак виходить за межі цього прикладу.
Функція tabbar-add-tab
була змінена таким чином, щоб алфавітувати вкладки / буфери.
Функція tabbar-line-tab
була модифікована таким чином, щоб забезпечити чотири (4) різні грані залежно від ситуації. Якщо вкладка / буфер пов’язана з кадром та вибрано ІС, то використовуйте tabbar-selected-associated
обличчя. Якщо вкладка / буфер пов’язана з кадром, а НЕ вибрана, використовуйте tabbar-unselected-associated
обличчя. Якщо вкладка / буфер НЕ асоціюється з кадром і вибрано IS, використовуйте tabbar-selected-unassociated
обличчя. Якщо вкладка / буфер НЕ пов'язана з кадром і НЕ вибрана, використовуйте tabbar-unselected-unassociated
обличчя.
;; Download tabbar version 2.0.1 by David Ponce:
;; https://marmalade-repo.org/packages/tabbar
;; or use package-install for marmalade repositories.
;; Place tabbar-2.0.1.el in the `load-path` -- it is okay to rename it to tabbar.el
;; or add the directory (where `tabbar.el` resides) to the `load-path`.
;; EXAMPLE: (setq load-path (append '("/Users/HOME/.emacs.d/lisp/") load-path))
(require 'tabbar)
(setq tabbar-cycle-scope 'tabs)
(remove-hook 'kill-buffer-hook 'tabbar-buffer-track-killed)
(defun my-buffer-groups ()
"Function that gives the group names the current buffer belongs to.
It must return a list of group names, or nil if the buffer has no
group. Notice that it is better that a buffer belongs to one group."
(list
(cond
((memq (current-buffer) (my-buffer-list (selected-frame)))
"A")
(t
"N"))))
(setq tabbar-buffer-groups-function 'my-buffer-groups) ;; 'tabbar-buffer-groups
;; redefine tabbar-add-tab so that it alphabetizes / sorts the tabs
(defun tabbar-add-tab (tabset object &optional append)
"Add to TABSET a tab with value OBJECT if there isn't one there yet.
If the tab is added, it is added at the beginning of the tab list,
unless the optional argument APPEND is non-nil, in which case it is
added at the end."
(let ((tabs (tabbar-tabs tabset)))
(if (tabbar-get-tab object tabset)
tabs
(let* ((tab (tabbar-make-tab object tabset))
(tentative-new-tabset
(if append
(append tabs (list tab))
(cons tab tabs)))
(new-tabset
(sort
tentative-new-tabset
#'(lambda (e1 e2)
(string-lessp
(format "%s" (car e1)) (format "%s" (car e2)))))))
(tabbar-set-template tabset nil)
(set tabset new-tabset)))))
;; AUTHOR: Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-buffer-list (frame)
;; Remove dead buffers.
(set-frame-parameter frame 'frame-bufs-buffer-list
(delq nil (mapcar #'(lambda (x) (if (buffer-live-p x) x))
(frame-parameter frame 'frame-bufs-buffer-list))))
;; Return the associated-buffer list.
(frame-parameter frame 'frame-bufs-buffer-list))
(defun my-kill-buffer-fn ()
"This function is attached to a buffer-local `kill-buffer-hook'."
(let ((frame (selected-frame))
(current-buffer (current-buffer)))
(when (memq current-buffer (my-buffer-list frame))
(my-remove-buffer current-buffer frame))))
;; AUTHOR: Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-add-buffer (&optional buf frame)
"Add BUF to FRAME's associated-buffer list if not already present."
(interactive)
(let* ((buf (if buf buf (current-buffer)))
(frame (if frame frame (selected-frame)))
(associated-bufs (frame-parameter frame 'frame-bufs-buffer-list)))
(unless (bufferp buf)
(signal 'wrong-type-argument (list 'bufferp buf)))
(unless (memq buf associated-bufs)
(set-frame-parameter frame 'frame-bufs-buffer-list (cons buf associated-bufs)))
(with-current-buffer buf
(add-hook 'kill-buffer-hook 'my-kill-buffer-fn 'append 'local))
(when tabbar-mode (tabbar-display-update))))
;; AUTHOR: Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-remove-buffer (&optional buf frame)
"Remove BUF from FRAME's associated-buffer list."
(interactive)
(let ((buf (if buf buf (current-buffer)))
(frame (if frame frame (selected-frame))))
(set-frame-parameter frame 'frame-bufs-buffer-list
(delq buf (frame-parameter frame 'frame-bufs-buffer-list)))
(when tabbar-mode (tabbar-display-update))))
;; AUTHOR: Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-buffer-list-reset ()
"Wipe the entire slate clean for the selected frame."
(interactive)
(modify-frame-parameters (selected-frame) (list (cons 'frame-bufs-buffer-list nil)))
(when tabbar-mode (tabbar-display-update)))
(defun my-switch-tab-group ()
"Switch between tab group `A` and `N`."
(interactive)
(let ((current-group (format "%s" (tabbar-current-tabset t)))
(tab-buffer-list (mapcar
#'(lambda (b)
(with-current-buffer b
(list (current-buffer)
(buffer-name)
(funcall tabbar-buffer-groups-function))))
(funcall tabbar-buffer-list-function))))
(catch 'done
(mapc
#'(lambda (group)
(when (not (equal current-group
(format "%s" (car (car (cdr (cdr group)))))))
(throw 'done (switch-to-buffer (car (cdr group))))))
tab-buffer-list))))
(defface tabbar-selected-associated
'((t :background "black" :foreground "yellow" :box (:line-width 2 :color "yellow")))
"Face used for the selected tab -- associated with the `frame-bufs-buffer-list`."
:group 'tabbar)
(defface tabbar-unselected-associated
'((t :background "black" :foreground "white" :box (:line-width 2 :color "white")))
"Face used for unselected tabs -- associated with the `frame-bufs-buffer-list`."
:group 'tabbar)
(defface tabbar-selected-unassociated
'((t :background "black" :foreground "white" :box (:line-width 2 :color "firebrick")))
"Face used for the selected tab -- UNassociated with the `frame-bufs-buffer-list`."
:group 'tabbar)
(defface tabbar-unselected-unassociated
'((t :background "black" :foreground "white" :box (:line-width 2 :color "blue")))
"Face used for unselected tabs -- UNassociated with the `frame-bufs-buffer-list`."
:group 'tabbar)
(setq tabbar-background-color "black")
(defsubst tabbar-line-tab (tab)
"Return the display representation of tab TAB.
That is, a propertized string used as an `header-line-format' template
element.
Call `tabbar-tab-label-function' to obtain a label for TAB."
(concat
(propertize
(if tabbar-tab-label-function
(funcall tabbar-tab-label-function tab)
tab)
'tabbar-tab tab
'local-map (tabbar-make-tab-keymap tab)
'help-echo 'tabbar-help-on-tab
'mouse-face 'tabbar-highlight
'face
(cond
((and
(tabbar-selected-p tab (tabbar-current-tabset))
(memq (current-buffer) (my-buffer-list (selected-frame))))
'tabbar-selected-associated)
((and
(not (tabbar-selected-p tab (tabbar-current-tabset)))
(memq (current-buffer) (my-buffer-list (selected-frame))))
'tabbar-unselected-associated)
((and
(tabbar-selected-p tab (tabbar-current-tabset))
(not (memq (current-buffer) (my-buffer-list (selected-frame)))))
'tabbar-selected-unassociated)
((and
(not (tabbar-selected-p tab (tabbar-current-tabset)))
(not (memq (current-buffer) (my-buffer-list (selected-frame)))))
'tabbar-unselected-unassociated))
'pointer 'hand)
tabbar-separator-value))
(define-key global-map "\C-c\C-r" 'my-buffer-list-reset)
(define-key global-map "\C-c\C-a" 'my-add-buffer)
(define-key global-map "\C-c\C-n" 'my-remove-buffer)
(define-key global-map (kbd "<M-s-right>") 'tabbar-forward)
(define-key global-map (kbd "<M-s-left>") 'tabbar-backward)
(define-key global-map [C-tab] 'my-switch-tab-group)
(tabbar-mode 1)
На наступному скріншоті зображені дві можливі групування буфера / вкладок: (1) зліва - це група тих буферів / вкладок, які асоціюються з кадром з назвою SYSTEM
[жовті та білі вкладки], з великої літери "А", зазначеної у режим-лінія; і (2) праворуч - це група тих буферів / вкладок, які НЕ асоціюються з кадром з ім'ям SYSTEM
[сині та червоні вкладки], з великої літери "N", зазначеної в рядку режиму.