feat(emacs): Tab control

- Removes default "implicit naming" behaviour.
- Adds keybinds.
This commit is contained in:
Madeleine Sydney
2025-02-17 02:51:21 -07:00
parent 7a8b0c4fe1
commit 584cff0bd2
3 changed files with 68 additions and 0 deletions

View File

@@ -61,6 +61,7 @@
(require 'syd-projects)
(require 'syd-scratch)
(require 'syd-smartparens)
(require 'syd-tabs)
(require 'syd-tooling)
(require 'syd-tramp)
(require 'syd-ui)

View File

@@ -87,6 +87,7 @@ KEYS is an alist of the parsed keywords."
nil)
(defmacro with-transient-after (hook-or-function &rest forms)
(declare (indent defun))
(let ((hook-name (gensym "transient-hook"))
(hook-or-function* (gensym "hook-or-function")))
`(let* ((,hook-or-function* ,hook-or-function))

View File

@@ -0,0 +1,66 @@
;;; syd-tabs.el -*- lexical-binding: t; -*-
;; Many themes neglect tab-bar customisation, leaving it completely unstyled.
;; `vim-tab-bar' will style it to look like Vim's tab-bar, but more importantly,
;; it will colour it to match the current theme.
(use-package vim-tab-bar
:commands vim-tab-bar-mode)
(with-eval-after-load 'tab-bar
(setq tab-bar-new-tab-to 'rightmost)
(defun syd-tab-bar-make-free-name ()
(cl-loop for i from 1
with candidate = nil
do (setq candidate (format "#%d" i))
while (tab-bar--tab-index-by-name candidate)
finally return candidate))
(defun syd-tab-bar-rename-tab (tab new-name)
;; HACK: Using `tab-bar-rename-tab' doesn't work, for some reason. This
;; relies on the internal representation of tabs.
(setf (alist-get 'name tab) new-name
(alist-get 'explicit-name tab) t))
(defvar syd-tab-bar-name-function #'syd-tab-bar-make-free-name
"Nullary function expected to return the name for a new tab.")
(syd-add-hook 'tab-bar-tab-post-open-functions
(defun syd-tab-bar--name-new-tab-h (tab)
"Hooks to `tab-bar-tab-post-open-functions' such that new tabs will be
given \"explicit names\" that are static."
(syd-tab-bar-rename-tab tab (funcall syd-tab-bar-name-function)))
(defun syd-tab-bar--show-tab-bar-h (_tab)
"Show the tab-bar if it is not already visible. See
`syd-tab-bar-hide-tab-bar-h'."
(unless vim-tab-bar-mode
(vim-tab-bar-mode 1))))
(syd-add-hook 'tab-bar-tab-pre-close-functions
(defun syd-tab-bar-hide-tab-bar-h (_tab _final-tab-p)
"Hide the tab-bar when there is only a single tab to show. See
`syd-tab-bar--show-tab-bar-h'."
(when (<= (length (tab-bar-tabs)) 2) ; The tab hasn't yet been removed.
(tab-bar-mode -1))))
(defun syd-tab-bar-new-named-tab (name)
(interactive (list (read-string "Tab name: ")))
;; Relies on `syd-tab-bar--name-new-tab-h'.
(let ((syd-tab-bar-name-function (lambda () name)))
(tab-bar-new-tab)))
(general-def
:prefix-map 'syd-leader-tab-map
"[" #'tab-previous
"]" #'tab-next
"r" #'tab-rename
"R" #'tab-rename
"n" #'tab-new
"N" #'syd-tab-bar-new-named-tab
"d" #'tab-close)
(general-def
:keymaps 'syd-leader-map
"TAB" `("Tabs" . ,syd-leader-tab-map)
"<tab>" `("Tabs" . ,syd-leader-tab-map)))
(provide 'syd-tabs)