I am using (global-tab-bar-mode) in emacs, but almost all commands that have output (like shell commands) will split the current window and make another, ignoring tabs completely, which I do not want, I want everything to use tabs instead of opening new windows! My current tab config (mainly AI generated because my elisp is not good at all):
;; Tab management
(use-package tab-bar
:ensure nil
:init
(tab-bar-mode 1)
:config
(setq tab-bar-new-tab-choice "*scratch*"
tab-bar-close-button nil
tab-bar-new-button nil
tab-bar-format '(tab-bar-format-tabs tab-bar-separator))
;; Auto-close empty non-scratch tabs
(defun auto-close-empty-tab ()
"Close tab if it only contains an empty non-scratch buffer."
(when (and (eq (length (window-list)) 1)
(not (string-match-p "\\*scratch\\*" (buffer-name)))
(eq (buffer-size) 0))
(tab-bar-close-tab)))
(add-hook 'kill-buffer-hook 'auto-close-empty-tab)
;; Tab display function
(defun my/display-in-tab (buffer &optional _)
"Display BUFFER in a new tab reliably."
(let ((tab-bar-new-tab-choice t))
(tab-bar-new-tab)
(set-window-buffer (selected-window) buffer)
(selected-window)))
;; Set for all buffers
(setq display-buffer-base-action '((my/display-in-tab)))
(setq display-buffer-alist nil)
;; Window management overrides
(defun my/ignore-split (&rest _)
"Ignore split commands safely.")
(advice-add 'split-window :override #'my/ignore-split)
(advice-add 'split-window-right :override #'my/ignore-split)
(advice-add 'split-window-below :override #'my/ignore-split)
(defun my/safe-switch-to-buffer (buffer &optional norecord)
"Switch to BUFFER in new tab, handling special cases."
(cond
((minibufferp) (switch-to-buffer buffer norecord))
(t (my/display-in-tab buffer))))
(advice-add 'switch-to-buffer :override #'my/safe-switch-to-buffer)
(defun my/safe-delete-window (&optional window)
"Prevent deleting the sole window."
(unless (one-window-p)
(delete-window window)))
(advice-add 'delete-window :override #'my/safe-delete-window)
;; Tab protection
(defun protect-last-tab (&rest _)
"Prevent deleting the last remaining tab in a frame."
(when (<= (length (tab-bar-tabs)) 1)
(tab-bar-new-tab)))
(advice-add 'tab-bar-close-tab :before #'protect-last-tab)
(advice-add 'tab-close :before #'protect-last-tab))
;; Add this function to clone tabs
(defun clone-tab ()
"Clone current tab with its buffer."
(interactive)
(let* ((current-buf (current-buffer)))
(tab-bar-new-tab)
(switch-to-buffer current-buf)))
;; Modify the auto-close function to handle scratch buffers correctly
(defun auto-close-empty-tab ()
"Close tab if it only contains an empty non-scratch buffer."
(when (and (eq (length (window-list)) 1)
(not (string-match-p "\\*scratch\\*" (buffer-name)))
(eq (buffer-size) 0))
(tab-bar-close-tab)))
;; Update the display function to prevent automatic cloning
(defun my/display-in-tab (buffer &optional _)
"Display BUFFER in a new tab reliably."
(let ((tab-bar-new-tab-choice t))
(tab-bar-new-tab)
(set-window-buffer (selected-window) buffer)
(selected-window)))
;; Simplify the initial tab setup
(add-hook 'after-init-hook
(lambda ()
(tab-bar-close-other-tabs)
(switch-to-buffer "*scratch*")))
this attempts to hook onto splitting windows, but is completely broken and I cannot seem to find where, as it will duplicate the current tab and open a new scratch buffer tab when trying to run (tab-bar-new-tab), it will open multiple tabs on startup, and the new tabs do not correctly register content, so this solution does not really work. I am looking to do something similar, as it would be possible and reliable to add an advice to each individual command which would open a new window, but it would be a pain, and I feel like it would be possible to do something like this by hooking into split window functions. Can anyone help?
Edit for clarity: I am very new, but I want to do this not because I want the same thing I got from other editors, (I have worked tabless before), but because it is just a much nicer paradigm that I like, and while I intend to learn windows much more, I do want a primarily tab-based workflow, and it interrupts mine when the window splits unnecesarily.
You can probably ditch your code and just do this:
(setq display-buffer-base-action '(display-buffer-in-tab))
Personally I wouldn't recommend doing anything like this, as split windows are incredibly useful.
As a data point, consider that GNU Emacs existed for 35 years before it acquired any "tabs" functionality as standard (which happened in 2020). If tabs were the best UI for Emacs, they would have been added a long time before that.
I think you'll be better off in the long run learning how to make windows work for you; so my recommendation is that you get accustomed to them, and address any specific pain points individually. (If you can articulate what you currently find problematic, you could ask a separate question about that.)
Just my opinion, though.