;;; tab-conf.el --- My configurations of the tabs -*- lexical-binding: t; -*- (require 'tab-bar) (setq tab-bar-format nil) (define-key tab-switcher-mode-map (vector ?n) 'tab-switcher-next-or-first) (define-key tab-switcher-mode-map (vector ?p) 'tab-switcher-prev-or-last) (define-key tab-prefix-map (vector 'tab) 'tab-switcher) (define-key global-map (vector ?\s-t) #'durand-switch-tab-dwim) (define-key global-map (vector ?\s-T) #'tab-switcher) ;;;###autoload (defun durand-switch-tab-dwim (&optional arg) "Do what I mean if I want to switch tabs. If there is only one tab, or if ARG is '(4), create another one, prompting me for the buffer to display in the new tab. If there are two tabs and ARG is not '(4) or '(16) or 0, just switch between them. If ARG is 0, then use `completing-read' to read an action from `find-file-other-tab', `dired-other-tab', `tab-rename'. If there are more than two tabs and if ARG is not '(4) or '(16) or 0, then use `completing-read' to ask for a tab to switch to. If ARG is '(16), then use `completing-read' to ask for a tab to delete. The default is the current tab. However, if there is only one tab, create another one, prompting me for the buffer to display in the new tab." (interactive "P") (let ((tabs (seq-sort (lambda (t1 t2) (cond ((null (assoc 'time t1))) ((null (assoc 'time t2)) nil) (t (> (alist-get 'time t1) (alist-get 'time t2))))) (tab-bar-tabs)))) (cond ((equal arg 0) (let* ((action-list (list (cons"f: file" 'find-file-other-tab) (cons "d: dired" 'dired-other-tab) (cons "r: rename" 'tab-rename))) (action (cdr (assoc (minibuffer-with-setup-hook 'durand-headlong-minibuffer-setup-hook (completing-read "Choose an action: " action-list nil t)) action-list #'string=))) (current-prefix-arg nil)) (call-interactively action))) ((or (equal arg (cons 4 nil)) (null (cdr tabs))) (switch-to-buffer-other-tab (read-buffer "Switch to buffer in a new tab" (other-buffer)))) ((and (cdr tabs) (null (cddr tabs)) (not (or (equal arg (cons 4 nil)) (equal arg (cons 16 nil)) (equal arg 0)))) (tab-bar-switch-to-tab (cdr (assoc 'name (cadr tabs))))) ((not (or (equal arg (cons 4 nil)) (equal arg (cons 16 nil)) (equal arg 0))) (tab-bar-switch-to-tab (completing-read (format "Switch to tab by name (default %s): " (cdr (assoc 'name (cadr tabs)))) (mapcar (lambda (tab) (cdr (assoc 'name tab))) tabs) nil nil nil nil (cdr (assoc 'name (cadr tabs)))))) ((equal arg (cons 16 nil)) (tab-bar-close-tab-by-name (completing-read (format "Close tab (default %s) : " (cdr (assoc 'name (car tabs)))) (mapcar (lambda (tab) (cdr (assoc 'name tab))) tabs) nil nil nil nil (cdr (assoc 'name (car tabs))))))))) ;;;###autoload (defun tab-switcher-first () "Go to the first window configuration line." (interactive) (goto-char (point-min)) (skip-chars-forward "[:space:]\n") (forward-char -1)) ;;;###autoload (defun tab-switcher-last () "Go to the last window configuration line." (interactive) (goto-char (point-max)) (skip-chars-backward "[:space:]\n") (goto-char (line-beginning-position)) (skip-chars-forward "[:space:]") (forward-char -1)) ;;;###autoload (defun tab-switcher-next-or-first () "Go to the next configuration line. If the next line is not a configuration line, then go to the first configuration line." (interactive) (forward-line 1) (cond ((looking-at "^\\s-*$") (tab-switcher-first)) (t (skip-chars-forward "[:space:]") (forward-char -1)))) ;;;###autoload (defun tab-switcher-prev-or-last () "Go to the previous configuration line. If the previous line is not a configuration line, then go to the last configuration line." (interactive) (forward-line -1) (cond ((looking-at "^\\s-*$") (tab-switcher-last)) (t (skip-chars-forward "[:space:]") (forward-char -1))))