diff --git a/modules/ui/tabbar/autoload.el b/modules/ui/tabbar/autoload.el new file mode 100644 index 000000000..81935d0ee --- /dev/null +++ b/modules/ui/tabbar/autoload.el @@ -0,0 +1,103 @@ +;;; ui/tabbar/autoload.el -*- lexical-binding: t; -*- + +;;;###autoload +(defun +tabbar-buffer-predicate (buffer) + "TODO" + (or (memq buffer (window-parameter nil 'tabbar-buffers)) + (eq buffer (doom-fallback-buffer)))) + +;;;###autoload +(defun +tabbar-window-tab-list () + (+tabbar-window-buffer-list)) + +;;;###autoload +(defun +tabbar-window-buffer-list () + (cl-delete-if-not #'buffer-live-p (window-parameter nil 'tabbar-buffers))) + +;;;###autoload +(defun +tabbar-buffer-groups () + (list + (cond ((or (string-equal "*" (substring (buffer-name) 0 1)) + (memq major-mode '(magit-process-mode + magit-status-mode + magit-diff-mode + magit-log-mode + magit-file-mode + magit-blob-mode + magit-blame-mode + ))) + "Emacs") + ((derived-mode-p 'eshell-mode) + "EShell") + ((derived-mode-p 'dired-mode) + "Dired") + ((centaur-tabs-get-group-name (current-buffer)))))) + + +;; +;;; Commands + +;;;###autoload +(defun +tabbar/close-tab-or-window () + "TODO" + (interactive) + (call-interactively + (cond ((cdr (window-parameter nil 'tabbar-buffers)) + #'kill-current-buffer) + ((fboundp '+workspace/close-window-or-workspace) + #'+workspace/close-window-or-workspace) + (#'delete-window)))) + + +;; +;;; Advice + +;;;###autoload +(defun +tabbar*kill-current-buffer (&rest _) + (+tabbar|remove-buffer)) + +;;;###autoload +(defun +tabbar*bury-buffer (orig-fn &rest args) + (if centaur-tabs-mode + (let ((b (current-buffer))) + (apply orig-fn args) + (unless (eq b (current-buffer)) + (with-current-buffer b + (+tabbar|remove-buffer)))) + (apply orig-fn args))) + +;;;###autoload +(defun +tabbar*kill-tab-maybe (tab) + (let ((buffer (centaur-tabs-tab-value tab))) + (with-current-buffer buffer + ;; `kill-current-buffer' is advised not to kill buffers visible in another + ;; window, so it behaves better than `kill-buffer'. + (kill-current-buffer)) + (centaur-tabs-display-update))) + + +;; +;;; Hooks + +;;;###autoload +(defun +tabbar|add-buffer () + (when (and centaur-tabs-mode + (doom-real-buffer-p (current-buffer))) + (let* ((this-buf (current-buffer)) + (buffers (window-parameter nil 'tabbar-buffers))) + (cl-pushnew this-buf buffers) + (add-hook 'kill-buffer-hook #'+tabbar|remove-buffer nil t) + (set-window-parameter nil 'tabbar-buffers buffers)))) + +;;;###autoload +(defun +tabbar|remove-buffer () + (when centaur-tabs-mode + (set-window-parameter + nil + 'tabbar-buffers (delete (current-buffer) (window-parameter nil 'tabbar-buffers))))) + +;;;###autoload +(defun +tabbar|new-window () + (when centaur-tabs-mode + (unless (window-parameter nil 'tabbar-buffers) + (+tabbar|add-buffer)))) diff --git a/modules/ui/tabbar/config.el b/modules/ui/tabbar/config.el index a39cf5ab0..2ae46db9c 100644 --- a/modules/ui/tabbar/config.el +++ b/modules/ui/tabbar/config.el @@ -1,94 +1,39 @@ ;;; ui/tabbar/config.el -*- lexical-binding: t; -*- -;; This is here for reference. It is incomplete, buggy, and may be removed one -;; day. It shows window-local buffer lists. +(def-package! centaur-tabs + :after-call (after-find-file dired-initial-position-hook) + :config + (setq centaur-tabs-height 28 + centaur-tabs-set-bar 'left + centaur-tabs-set-modified-marker t) -(defvar +tabbar-mode-map - (let ((map (make-sparse-keymap))) - (define-key map [remap delete-window] #'+tabbar/close-tab-or-window) - (define-key map [remap +workspace/close-window-or-workspace] #'+tabbar/close-tab-or-window) - map) - "TODO") + (defun +tabbar|init-frames () + (dolist (frame (frame-list)) + (if (not centaur-tabs-mode) + (set-frame-parameter frame 'buffer-predicate (frame-parameter frame 'old-buffer-predicate)) + (set-frame-parameter frame 'old-buffer-predicate (frame-parameter frame 'buffer-predicate)) + (set-frame-parameter frame 'buffer-predicate #'+tabbar-buffer-predicate)))) + (add-hook 'centaur-tabs-mode-hook #'+tabbar|init-frames) -(after! persp-mode - (define-key persp-mode-map [remap delete-window] #'+tabbar/close-tab-or-window) - (define-key persp-mode-map [remap +workspace/close-window-or-workspace] #'+tabbar/close-tab-or-window)) + (setq centaur-tabs-buffer-list-function #'+tabbar-window-buffer-list + centaur-tabs-buffer-groups-function #'+tabbar-buffer-groups) + (remove-hook 'post-command-hook centaur-tabs-adjust-buffer-order-function) + (add-hook 'doom-switch-buffer-hook #'centaur-tabs-adjust-buffer-order) -(define-minor-mode +tabbar-mode - "TODO" - :global t - :keymap +tabbar-mode-map - (if +tabbar-mode - (setq-default header-line-format '((:eval (+tabbar-line)))) - (setq-default header-line-format nil))) -(+tabbar-mode +1) + (advice-add #'centaur-tabs-buffer-close-tab :override #'+tabbar*kill-tab-maybe) + (advice-add #'bury-buffer :around #'+tabbar*bury-buffer) + (advice-add #'kill-current-buffer :before #'+tabbar*kill-current-buffer) + (add-hook 'doom-switch-buffer-hook #'+tabbar|add-buffer) + (add-hook 'doom-switch-window-hook #'+tabbar|new-window) -(defun make-xpm (&rest _)) + (add-hook '+doom-dashboard-mode-hook #'centaur-tabs-local-mode) + (map! (:map centaur-tabs-mode-map + [remap delete-window] #'+tabbar/close-tab-or-window + [remap +workspace/close-window-or-workspace] #'+tabbar/close-tab-or-window) + (:after persp-mode + :map persp-mode-map + [remap delete-window] #'+tabbar/close-tab-or-window + [remap +workspace/close-window-or-workspace] #'+tabbar/close-tab-or-window)) -;; -(add-hook! 'doom-load-theme-hook - (defconst +tabbar-bar (make-xpm (face-background 'highlight) 3 26)) - (defconst +tabbar-hidden-bar (make-xpm nil 1 26)) - (setq-default header-line-format `(,+tabbar-hidden-bar (:eval (+tabbar-line)))) - - (add-to-list 'default-frame-alist '(buffer-predicate . +tabbar-buffer-predicate)) - (dolist (frame (frame-list)) - (set-frame-parameter frame 'buffer-predicate #'+tabbar-buffer-predicate))) - -(defun +tabbar-buffer-predicate (buffer) - (or (memq buffer (window-parameter nil 'tabbar-buffers)) - (eq buffer (doom-fallback-buffer)))) - - -(defun +tabbar-line () - (unless (or (window-dedicated-p) - (null mode-line-format)) - (concat (cl-loop for buf in (window-parameter nil 'tabbar-buffers) - if (eq (get-buffer buf) (current-buffer)) - concat (propertize (format "%s %s " +tabbar-bar buf) - 'face 'default) - else - concat (propertize (format " %s " buf) 'face 'mode-line-inactive)) - +tabbar-hidden-bar))) - -(defun +tabbar*bury-buffer (orig-fn &rest args) - (let ((b (current-buffer))) - (apply orig-fn args) - (unless (eq b (current-buffer)) - (with-current-buffer b - (+tabbar|remove-buffer))))) -(advice-add #'bury-buffer :around #'+tabbar*bury-buffer) - -(defun +tabbar*kill-current-buffer (&rest _) - (+tabbar|remove-buffer)) -(advice-add #'kill-current-buffer :before #'+tabbar*kill-current-buffer) - -(defun +tabbar|remove-buffer () - (set-window-parameter - nil - 'tabbar-buffers (delete (current-buffer) (window-parameter nil 'tabbar-buffers)))) - -(defun +tabbar/close-tab-or-window () - (interactive) - (call-interactively - (cond ((cdr (window-parameter nil 'tabbar-buffers)) - #'kill-current-buffer) - ((fboundp '+workspace/close-window-or-workspace) - #'+workspace/close-window-or-workspace) - (#'delete-window)))) - -(defun +tabbar|add-buffer () - (when (doom-real-buffer-p (current-buffer)) - (let* ((this-buf (current-buffer)) - (buffers (window-parameter nil 'tabbar-buffers))) - (unless (memq this-buf buffers) - (setq buffers (append buffers (list this-buf)))) - (add-hook 'kill-buffer-hook #'+tabbar|remove-buffer nil t) - (set-window-parameter nil 'tabbar-buffers buffers)))) -(add-hook 'doom-switch-buffer-hook #'+tabbar|add-buffer) - -(defun +tabbar|new-window () - (unless (window-parameter nil 'tabbar-buffers) - (+tabbar|add-buffer))) -(add-hook 'doom-switch-window-hook #'+tabbar|new-window) + (centaur-tabs-mode +1)) diff --git a/modules/ui/tabbar/packages.el b/modules/ui/tabbar/packages.el index 19ba8c35a..294f434f3 100644 --- a/modules/ui/tabbar/packages.el +++ b/modules/ui/tabbar/packages.el @@ -1,2 +1,4 @@ ;; -*- no-byte-compile: t; -*- ;;; ui/tabbar/packages.el + +(package! centaur-tabs)