emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Enable persistent naming for tabs


From: Robert Cochran
Subject: Re: [PATCH] Enable persistent naming for tabs
Date: Fri, 25 Oct 2019 08:47:47 -0700
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

Hi all,

Juri Linkov <address@hidden> writes:

>> C) Disable tab-bar-mode
>
> While implementing tab closing undo, I added disabling tab-bar-mode
> because it was easier to just add this line:
>
>                (or (<= (length tabs) 1) ; closed the last tab
>
> But please remove this from the default behavior because
> I noticed that it disables tab-bar on all frames, whereas
> it would make more sense to disable tab-bar only on the
> selected frame.

Sorry, I didn't quite understand what you wanted me to do there, so I
didn't try to address it.

>> #+BEGIN_SRC elisp
>> (defcustom tab-bar-close-tab-choice nil
>>   "Defines what to show in a new tab.
>> If nil, do not close the tab.
>> If close-frame, close the entire containing frame, as a web
>> browser would do.
>> If disable-tab-bar, turn off tab-bar-mode so that tabs no longer
>> show in the frame.
>> If the value is a function, call that function with the tab to be
>> closed as the argument."
>>   :type '(choice (const    :tag "Do nothing" nil)
>>                  (const    :tag "Close frame" 'close-frame)
>>                  (const    :tag "Disable tab-bar-mode" 'disable-tab-bar)
>>                  (function :tag "Function"))
>>   :group 'tab-bar
>>   :version "27.1")
>> #+END_SRC
>>
>> And then we can go from there. If that sounds like a workable solution,
>> then I'll provide a patch in the next few days that implements the
>> defcustom and all the appropriate behavior.
>
> Please implement this defcustom (with the nil default value) because
> we need to improve the current logic of closing the last tab (maybe
> the name should be tab-bar-close-last-tab-choice to suggest that
> it applies to closing only the last tab, not to every tab close).

Implemented in the attached patch. Please let me know what you all
think.

It occurred to me in the process of writing this up that it might be
useful to provide hook variables for creating and closing tabs -
'tab-bar-tab-open-hook' and 'tab-bar-tab-close-hook' perhaps? Standard
fare on those - a list of functions that take the tab as an argument,
probably called as the last task of tab creation and the first task of
tab closing? Thoughts?

Thanks,
-- 
~Robert Cochran

>From 81666f09d51aaa36e7d20ee5e1e038fe22feca0a Mon Sep 17 00:00:00 2001
From: Robert Cochran <address@hidden>
Date: Wed, 23 Oct 2019 17:34:24 -0700
Subject: [PATCH] Add customization option for what do when the last tab is
 closed

* lisp/tab-bar.el (tab-bar-close-last-tab-choice): New custom
variable.
(tab-bar-close-tab): Handle closing the last tab specially, referring to
tab-bar-close-last-tab-choice.
---
 lisp/tab-bar.el | 71 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 49 insertions(+), 22 deletions(-)

diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 8350b4e694..5c64386f55 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -613,6 +613,19 @@ tab-bar-close-tab-select
   :group 'tab-bar
   :version "27.1")
 
+(defcustom tab-bar-close-last-tab-choice nil
+  "Defines what to do when the last tab is closed.
+If nil, do nothing and show a message, like closing the last window or frame.
+If `close-frame', delete the containing frame, as a web browser would do.
+If `disable-tab-bar', disable tab-bar-mode so that tabs no longer show in the 
frame.
+If the value is a function, call that function with the tab to be closed as an 
argument."
+  :type '(choice (const    :tag "Do nothing and show message" nil)
+                 (const    :tag "Delete the containing frame" close-frame)
+                 (const    :tag "Disable tab-bar-mode" disable-tab-bar)
+                 (function :tag "Function"))
+  :group 'tab-bar
+  :version "27.1")
+
 (defun tab-bar-close-tab (&optional arg to-index)
   "Close the tab specified by its absolute position ARG.
 If no ARG is specified, then close the current tab and switch
@@ -627,29 +640,43 @@ tab-bar-close-tab
          (current-index (tab-bar--current-tab-index tabs))
          (close-index (if (integerp arg) (1- arg) current-index)))
 
-    ;; Select another tab before deleting the current tab
-    (when (eq current-index close-index)
-      (let ((to-index (or (if to-index (1- to-index))
-                          (pcase tab-bar-close-tab-select
-                            ('left (1- current-index))
-                            ('right (if (> (length tabs) (1+ current-index))
-                                        (1+ current-index)
-                                      (1- current-index)))))))
-        (setq to-index (max 0 (min (or to-index 0) (1- (length tabs)))))
-        (tab-bar-select-tab (1+ to-index))
-        ;; Re-read tabs after selecting another tab
-        (setq tabs (funcall tab-bar-tabs-function))))
-
-    (set-frame-parameter nil 'tabs (delq (nth close-index tabs) tabs))
-
-    (when (and tab-bar-mode
-               (and (natnump tab-bar-show)
-                    (<= (length tabs) tab-bar-show)))
-      (tab-bar-mode -1))
+    (if (= 1 (length tabs))
+      (pcase tab-bar-close-last-tab-choice
+        ('nil
+         (signal 'user-error '("Attempt to delete the sole tab in a frame")))
+        ('close-frame
+         (delete-frame))
+        ('disable-tab-bar
+         (tab-bar-mode -1))
+        ((pred functionp)
+         ;; Give the handler function the full extent of the tab's
+         ;; data, not just it's name and explicit-name flag.
+         (funcall tab-bar-close-last-tab-choice (tab-bar--tab))))
+
+      ;;; More than one tab still open
+      ;; Select another tab before deleting the current tab
+      (when (eq current-index close-index)
+        (let ((to-index (or (if to-index (1- to-index))
+                            (pcase tab-bar-close-tab-select
+                              ('left (1- current-index))
+                              ('right (if (> (length tabs) (1+ current-index))
+                                          (1+ current-index)
+                                        (1- current-index)))))))
+          (setq to-index (max 0 (min (or to-index 0) (1- (length tabs)))))
+          (tab-bar-select-tab (1+ to-index))
+          ;; Re-read tabs after selecting another tab
+          (setq tabs (funcall tab-bar-tabs-function))))
+
+      (set-frame-parameter nil 'tabs (delq (nth close-index tabs) tabs))
 
-    (force-mode-line-update)
-    (unless tab-bar-mode
-      (message "Deleted tab and switched to %s" tab-bar-close-tab-select))))
+      (when (and tab-bar-mode
+                 (and (natnump tab-bar-show)
+                      (<= (length tabs) tab-bar-show)))
+        (tab-bar-mode -1))
+
+      (force-mode-line-update)
+      (unless tab-bar-mode
+        (message "Deleted tab and switched to %s" tab-bar-close-tab-select)))))
 
 (defun tab-bar-close-tab-by-name (name)
   "Close the tab by NAME."
-- 
2.21.0


reply via email to

[Prev in Thread] Current Thread [Next in Thread]