aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuri Linkov2019-09-25 23:21:37 +0300
committerJuri Linkov2019-09-25 23:21:37 +0300
commite47c389cfd446f6ac36a240fd11134ad2b91fb81 (patch)
tree45800e83091f667f6fb754e22029d2dd33889000
parent848e21b0491cb0b2f8e3a59e9f5cabd7210dca5e (diff)
downloademacs-e47c389cfd446f6ac36a240fd11134ad2b91fb81.tar.gz
emacs-e47c389cfd446f6ac36a240fd11134ad2b91fb81.zip
Improve customization.
* lisp/tab-bar.el (tab-bar-new-tab-choice) (tab-bar-close-button-show): New defcustoms. (tab-bar-tab-name-function): New defvar. * lisp/tab-line.el (tab-line-new-tab-choice) (tab-line-close-button-show): New defcustoms.
-rw-r--r--lisp/tab-bar.el182
-rw-r--r--lisp/tab-line.el68
2 files changed, 178 insertions, 72 deletions
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 3b6415ad13d..fb13ff4178b 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -121,7 +121,7 @@ on a console which has no window system but does have a mouse."
121 (setq column (+ column (length (nth 1 binding)))))) 121 (setq column (+ column (length (nth 1 binding))))))
122 keymap)) 122 keymap))
123 ;; Clicking anywhere outside existing tabs will add a new tab 123 ;; Clicking anywhere outside existing tabs will add a new tab
124 (tab-bar-add-tab))))) 124 (tab-bar-new-tab)))))
125 125
126;; Used in the Show/Hide menu, to have the toggle reflect the current frame. 126;; Used in the Show/Hide menu, to have the toggle reflect the current frame.
127(defun toggle-tab-bar-mode-from-frame (&optional arg) 127(defun toggle-tab-bar-mode-from-frame (&optional arg)
@@ -152,9 +152,27 @@ Its main job is to show tabs in the tab bar."
152 (puthash key tab-bar-map tab-bar-keymap-cache))))) 152 (puthash key tab-bar-map tab-bar-keymap-cache)))))
153 153
154 154
155(defvar tab-bar-separator nil) 155(defcustom tab-bar-new-tab-choice t
156 "Defines what to show in a new tab.
157If t, start a new tab with the current buffer, i.e. the buffer
158that was current before calling the command that adds a new tab
159(this is the same what `make-frame' does by default).
160If the value is a string, switch to a buffer if it exists, or switch
161to a buffer visiting the file or directory that the string specifies.
162If the value is a function, call it with no arguments and switch to
163the buffer that it returns.
164If nil, duplicate the contents of the tab that was active
165before calling the command that adds a new tab."
166 :type '(choice (const :tag "Current buffer" t)
167 (directory :tag "Directory" :value "~/")
168 (file :tag "File" :value "~/.emacs")
169 (string :tag "Buffer" "*scratch*")
170 (function :tag "Function")
171 (const :tag "Duplicate tab" nil))
172 :group 'tab-bar
173 :version "27.1")
156 174
157(defvar tab-bar-button-new 175(defvar tab-bar-new-button
158 (propertize " + " 176 (propertize " + "
159 'display `(image :type xpm 177 'display `(image :type xpm
160 :file ,(expand-file-name 178 :file ,(expand-file-name
@@ -164,7 +182,23 @@ Its main job is to show tabs in the tab bar."
164 :ascent center)) 182 :ascent center))
165 "Button for creating a new tab.") 183 "Button for creating a new tab.")
166 184
167(defvar tab-bar-button-close 185(defcustom tab-bar-close-button-show t
186 "Defines where to show the close tab button.
187If t, show the close tab button on all tabs.
188If `selected', show it only on the selected tab.
189If `non-selected', show it only on non-selected tab.
190If nil, don't show it at all."
191 :type '(choice (const :tag "On all tabs" t)
192 (const :tag "On selected tab" selected)
193 (const :tag "On non-selected tabs" non-selected)
194 (const :tag "None" nil))
195 :set (lambda (sym val)
196 (set sym val)
197 (force-mode-line-update))
198 :group 'tab-bar
199 :version "27.1")
200
201(defvar tab-bar-close-button
168 (propertize " x" 202 (propertize " x"
169 'display `(image :type xpm 203 'display `(image :type xpm
170 :file ,(expand-file-name 204 :file ,(expand-file-name
@@ -176,12 +210,21 @@ Its main job is to show tabs in the tab bar."
176 :help "Click to close tab") 210 :help "Click to close tab")
177 "Button for closing the clicked tab.") 211 "Button for closing the clicked tab.")
178 212
213(defvar tab-bar-separator nil)
214
215
216(defvar tab-bar-tab-name-function #'tab-bar-tab-name
217 "Function to get a tab name.
218Function gets no arguments.
219By default, use function `tab-bar-tab-name'.")
220
179(defun tab-bar-tab-name () 221(defun tab-bar-tab-name ()
180 "Generate tab name in the context of the selected frame." 222 "Generate tab name in the context of the selected frame."
181 (mapconcat 223 (mapconcat #'buffer-name
182 (lambda (w) (buffer-name (window-buffer w))) 224 (delete-dups (mapcar #'window-buffer
183 (window-list-1 (frame-first-window) 'nomini) 225 (window-list-1 (frame-first-window)
184 ", ")) 226 'nomini)))
227 ", "))
185 228
186(defvar tab-bar-tabs-function #'tab-bar-tabs 229(defvar tab-bar-tabs-function #'tab-bar-tabs
187 "Function to get a list of tabs to display in the tab bar. 230 "Function to get a list of tabs to display in the tab bar.
@@ -195,8 +238,12 @@ By default, use function `tab-bar-tabs'.")
195Ensure the frame parameter `tabs' is pre-populated. 238Ensure the frame parameter `tabs' is pre-populated.
196Return its existing value or a new value." 239Return its existing value or a new value."
197 (let ((tabs (frame-parameter nil 'tabs))) 240 (let ((tabs (frame-parameter nil 'tabs)))
198 (unless tabs 241 (if tabs
199 (setq tabs `((current-tab (name . ,(tab-bar-tab-name))))) 242 ;; Update current tab name
243 (let ((name (assq 'name (assq 'current-tab tabs))))
244 (when name (setcdr name (funcall tab-bar-tab-name-function))))
245 ;; Create default tabs
246 (setq tabs `((current-tab (name . ,(funcall tab-bar-tab-name-function)))))
200 (set-frame-parameter nil 'tabs tabs)) 247 (set-frame-parameter nil 'tabs tabs))
201 tabs)) 248 tabs))
202 249
@@ -216,7 +263,10 @@ Return its existing value or a new value."
216 `((current-tab 263 `((current-tab
217 menu-item 264 menu-item
218 ,(propertize (concat (cdr (assq 'name tab)) 265 ,(propertize (concat (cdr (assq 'name tab))
219 (or tab-bar-button-close "")) 266 (or (and tab-bar-close-button-show
267 (not (eq tab-bar-close-button-show
268 'non-selected))
269 tab-bar-close-button) ""))
220 'face 'tab-bar-tab) 270 'face 'tab-bar-tab)
221 ignore 271 ignore
222 :help "Current tab"))) 272 :help "Current tab")))
@@ -224,21 +274,28 @@ Return its existing value or a new value."
224 `((,(intern (format "tab-%i" i)) 274 `((,(intern (format "tab-%i" i))
225 menu-item 275 menu-item
226 ,(propertize (concat (cdr (assq 'name tab)) 276 ,(propertize (concat (cdr (assq 'name tab))
227 (or tab-bar-button-close "")) 277 (or (and tab-bar-close-button-show
278 (not (eq tab-bar-close-button-show
279 'selected))
280 tab-bar-close-button) ""))
228 'face 'tab-bar-tab-inactive) 281 'face 'tab-bar-tab-inactive)
229 ,(lambda () 282 ,(or
230 (interactive) 283 (cdr (assq 'binding tab))
231 (tab-bar-select-tab tab)) 284 (lambda ()
285 (interactive)
286 (tab-bar-select-tab tab)))
232 :help "Click to visit tab")))) 287 :help "Click to visit tab"))))
233 `((,(if (eq (car tab) 'current-tab) 'C-current-tab (intern (format "C-tab-%i" i))) 288 `((,(if (eq (car tab) 'current-tab) 'C-current-tab (intern (format "C-tab-%i" i)))
234 menu-item "" 289 menu-item ""
235 ,(lambda () 290 ,(or
236 (interactive) 291 (cdr (assq 'close-binding tab))
237 (tab-bar-close-tab tab)))))) 292 (lambda ()
293 (interactive)
294 (tab-bar-close-tab tab)))))))
238 (funcall tab-bar-tabs-function)) 295 (funcall tab-bar-tabs-function))
239 (when tab-bar-button-new 296 (when tab-bar-new-button
240 `((sep-add-tab menu-item ,separator ignore) 297 `((sep-add-tab menu-item ,separator ignore)
241 (add-tab menu-item ,tab-bar-button-new tab-bar-add-tab 298 (add-tab menu-item ,tab-bar-new-button tab-bar-new-tab
242 :help "New tab")))))) 299 :help "New tab"))))))
243 300
244 301
@@ -255,9 +312,9 @@ Return its existing value or a new value."
255 (when (equal (cdr (assq 'name tab)) tab-name) 312 (when (equal (cdr (assq 'name tab)) tab-name)
256 (throw 'done tab)))))) 313 (throw 'done tab))))))
257 314
258(defun tab-bar-new-tab () 315(defun tab-bar-tab-default ()
259 (let ((tab `(tab 316 (let ((tab `(tab
260 (name . ,(tab-bar-tab-name)) 317 (name . ,(funcall tab-bar-tab-name-function))
261 (time . ,(time-convert nil 'integer)) 318 (time . ,(time-convert nil 'integer))
262 (wc . ,(current-window-configuration)) 319 (wc . ,(current-window-configuration))
263 (ws . ,(window-state-get 320 (ws . ,(window-state-get
@@ -278,7 +335,7 @@ Return its existing value or a new value."
278 (interactive (list (tab-bar-read-tab-name "Select tab by name: "))) 335 (interactive (list (tab-bar-read-tab-name "Select tab by name: ")))
279 (when (and tab (not (eq (car tab) 'current-tab))) 336 (when (and tab (not (eq (car tab) 'current-tab)))
280 (let* ((tabs (tab-bar-tabs)) 337 (let* ((tabs (tab-bar-tabs))
281 (new-tab (tab-bar-new-tab)) 338 (new-tab (tab-bar-tab-default))
282 (wc (cdr (assq 'wc tab)))) 339 (wc (cdr (assq 'wc tab))))
283 ;; During the same session, use window-configuration to switch 340 ;; During the same session, use window-configuration to switch
284 ;; tabs, because window-configurations are more reliable 341 ;; tabs, because window-configurations are more reliable
@@ -293,11 +350,11 @@ Return its existing value or a new value."
293 (while tabs 350 (while tabs
294 (cond 351 (cond
295 ((eq (car tabs) tab) 352 ((eq (car tabs) tab)
296 (setcar tabs `(current-tab (name . ,(tab-bar-tab-name))))) 353 (setcar tabs `(current-tab (name . ,(funcall tab-bar-tab-name-function)))))
297 ((eq (car (car tabs)) 'current-tab) 354 ((eq (car (car tabs)) 'current-tab)
298 (setcar tabs new-tab))) 355 (setcar tabs new-tab)))
299 (setq tabs (cdr tabs))) 356 (setq tabs (cdr tabs)))
300 (force-window-update)))) 357 (force-mode-line-update))))
301 358
302(defun tab-bar-switch-to-prev-tab (&optional _arg) 359(defun tab-bar-switch-to-prev-tab (&optional _arg)
303 "Switch to ARGth previous tab." 360 "Switch to ARGth previous tab."
@@ -316,7 +373,7 @@ Return its existing value or a new value."
316 (tab-bar-select-tab (car (cdr tabs)))))) 373 (tab-bar-select-tab (car (cdr tabs))))))
317 374
318 375
319(defcustom tab-bar-add-tab-to 'right 376(defcustom tab-bar-new-tab-to 'right
320 "Defines where to create a new tab. 377 "Defines where to create a new tab.
321If `leftmost', create as the first tab. 378If `leftmost', create as the first tab.
322If `left', create to the left from the current tab. 379If `left', create to the left from the current tab.
@@ -326,35 +383,46 @@ If `rightmost', create as the last tab."
326 (const :tag "To the left" left) 383 (const :tag "To the left" left)
327 (const :tag "To the right" right) 384 (const :tag "To the right" right)
328 (const :tag "Last tab" rightmost)) 385 (const :tag "Last tab" rightmost))
386 :group 'tab-bar
329 :version "27.1") 387 :version "27.1")
330 388
331(defun tab-bar-add-tab () 389(defun tab-bar-new-tab ()
332 "Clone the current tab to the position specified by `tab-bar-add-tab-to'." 390 "Clone the current tab to the position specified by `tab-bar-new-tab-to'."
333 (interactive) 391 (interactive)
334 (unless tab-bar-mode 392 (unless tab-bar-mode
335 (tab-bar-mode 1)) 393 (tab-bar-mode 1))
336 (let* ((tabs (tab-bar-tabs)) 394 (let* ((tabs (tab-bar-tabs))
337 ;; (i-tab (- (length tabs) (length (memq tab tabs)))) 395 ;; (i-tab (- (length tabs) (length (memq tab tabs))))
338 (new-tab (tab-bar-new-tab))) 396 (new-tab (tab-bar-tab-default)))
339 (cond 397 (cond
340 ((eq tab-bar-add-tab-to 'leftmost) 398 ((eq tab-bar-new-tab-to 'leftmost)
341 (setq tabs (cons new-tab tabs))) 399 (setq tabs (cons new-tab tabs)))
342 ((eq tab-bar-add-tab-to 'rightmost) 400 ((eq tab-bar-new-tab-to 'rightmost)
343 (setq tabs (append tabs (list new-tab)))) 401 (setq tabs (append tabs (list new-tab))))
344 (t 402 (t
345 (let ((prev-tab (tab-bar-find-prev-tab tabs))) 403 (let ((prev-tab (tab-bar-find-prev-tab tabs)))
346 (cond 404 (cond
347 ((eq tab-bar-add-tab-to 'left) 405 ((eq tab-bar-new-tab-to 'left)
348 (if prev-tab 406 (if prev-tab
349 (setcdr prev-tab (cons new-tab (cdr prev-tab))) 407 (setcdr prev-tab (cons new-tab (cdr prev-tab)))
350 (setq tabs (cons new-tab tabs)))) 408 (setq tabs (cons new-tab tabs))))
351 ((eq tab-bar-add-tab-to 'right) 409 ((eq tab-bar-new-tab-to 'right)
352 (if prev-tab 410 (if prev-tab
353 (setq prev-tab (cdr prev-tab)) 411 (setq prev-tab (cdr prev-tab))
354 (setq prev-tab tabs)) 412 (setq prev-tab tabs))
355 (setcdr prev-tab (cons new-tab (cdr prev-tab)))))))) 413 (setcdr prev-tab (cons new-tab (cdr prev-tab))))))))
356 (set-frame-parameter nil 'tabs tabs) 414 (set-frame-parameter nil 'tabs tabs)
357 (tab-bar-select-tab new-tab) 415 (tab-bar-select-tab new-tab)
416 (when tab-bar-new-tab-choice
417 (delete-other-windows)
418 (let ((buffer
419 (if (functionp tab-bar-new-tab-choice)
420 (funcall tab-bar-new-tab-choice)
421 (if (stringp tab-bar-new-tab-choice)
422 (or (get-buffer tab-bar-new-tab-choice)
423 (find-file-noselect tab-bar-new-tab-choice))))))
424 (when (buffer-live-p buffer)
425 (switch-to-buffer buffer))))
358 (unless tab-bar-mode 426 (unless tab-bar-mode
359 (message "Added new tab with the current window configuration")))) 427 (message "Added new tab with the current window configuration"))))
360 428
@@ -365,6 +433,7 @@ If `left', select the adjacent left tab.
365If `right', select the adjacent right tab." 433If `right', select the adjacent right tab."
366 :type '(choice (const :tag "Select left tab" left) 434 :type '(choice (const :tag "Select left tab" left)
367 (const :tag "Select right tab" right)) 435 (const :tag "Select right tab" right))
436 :group 'tab-bar
368 :version "27.1") 437 :version "27.1")
369 438
370(defun tab-bar-close-current-tab (&optional tab select-tab) 439(defun tab-bar-close-current-tab (&optional tab select-tab)
@@ -407,29 +476,30 @@ specified by `tab-bar-close-tab-select'."
407 (tab-bar-close-current-tab tab) 476 (tab-bar-close-current-tab tab)
408 ;; Close non-current tab, no need to switch to another tab 477 ;; Close non-current tab, no need to switch to another tab
409 (set-frame-parameter nil 'tabs (delq tab (tab-bar-tabs))) 478 (set-frame-parameter nil 'tabs (delq tab (tab-bar-tabs)))
410 (force-window-update)))) 479 (force-mode-line-update))))
411 480
412 481
413;;; Non-graphical access to frame-local tabs (named window configurations) 482;;; Non-graphical access to frame-local tabs (named window configurations)
414 483
415(defun make-tab () 484(defun tab-make ()
416 "Create a new named window configuration without having to click a tab." 485 "Create a new named window configuration without having to click a tab."
417 (interactive) 486 (interactive)
418 (tab-bar-add-tab) 487 (tab-bar-new-tab)
419 (unless tab-bar-mode 488 (unless tab-bar-mode
420 (message "Added new tab with the current window configuration"))) 489 (message "Added new tab with the current window configuration")))
421 490
422(defun delete-tab () 491(defun tab-delete ()
423 "Delete the current window configuration without clicking a close button." 492 "Delete the current window configuration without clicking a close button."
424 (interactive) 493 (interactive)
425 (tab-bar-close-current-tab) 494 (tab-bar-close-current-tab)
426 (unless tab-bar-mode 495 (unless tab-bar-mode
427 (message "Deleted the current tab"))) 496 (message "Deleted the current tab")))
428 497
429(defalias 'list-tabs 'tab-bar-list) 498;; Short aliases
430(defalias 'switch-to-tab 'tab-bar-select-tab) 499;; (defalias 'tab-switch 'tab-bar-switch-to-next-tab)
431(defalias 'previous-tab 'tab-bar-switch-to-prev-tab) 500(defalias 'tab-select 'tab-bar-select-tab)
432(defalias 'next-tab 'tab-bar-switch-to-next-tab) 501(defalias 'tab-previous 'tab-bar-switch-to-prev-tab)
502(defalias 'tab-next 'tab-bar-switch-to-next-tab)
433 503
434(defun tab-bar-list () 504(defun tab-bar-list ()
435 "Display a list of named window configurations. 505 "Display a list of named window configurations.
@@ -445,7 +515,7 @@ marked for deletion."
445 (let ((dir default-directory) 515 (let ((dir default-directory)
446 (minibuf (minibuffer-selected-window))) 516 (minibuf (minibuffer-selected-window)))
447 (let ((tab-bar-mode t)) ; don't enable tab-bar-mode if it's disabled 517 (let ((tab-bar-mode t)) ; don't enable tab-bar-mode if it's disabled
448 (tab-bar-add-tab)) 518 (tab-bar-new-tab))
449 ;; Handle the case when it's called in the active minibuffer. 519 ;; Handle the case when it's called in the active minibuffer.
450 (when minibuf (select-window (minibuffer-selected-window))) 520 (when minibuf (select-window (minibuffer-selected-window)))
451 (delete-other-windows) 521 (delete-other-windows)
@@ -541,9 +611,9 @@ Letters do not insert themselves; instead, they are commands.
541(defun tab-bar-list-current-tab (error-if-non-existent-p) 611(defun tab-bar-list-current-tab (error-if-non-existent-p)
542 "Return window configuration described by this line of the list." 612 "Return window configuration described by this line of the list."
543 (let* ((where (save-excursion 613 (let* ((where (save-excursion
544 (beginning-of-line) 614 (beginning-of-line)
545 (+ 2 (point) tab-bar-list-column))) 615 (+ 2 (point) tab-bar-list-column)))
546 (tab (and (not (eobp)) (get-text-property where 'tab)))) 616 (tab (and (not (eobp)) (get-text-property where 'tab))))
547 (or tab 617 (or tab
548 (if error-if-non-existent-p 618 (if error-if-non-existent-p
549 (user-error "No window configuration on this line") 619 (user-error "No window configuration on this line")
@@ -621,16 +691,16 @@ Then move up one line. Prefix arg means move that many lines."
621 (while (re-search-forward 691 (while (re-search-forward
622 (format "^%sD" (make-string tab-bar-list-column ?\040)) 692 (format "^%sD" (make-string tab-bar-list-column ?\040))
623 nil t) 693 nil t)
624 (forward-char -1) 694 (forward-char -1)
625 (let ((tab (tab-bar-list-current-tab nil))) 695 (let ((tab (tab-bar-list-current-tab nil)))
626 (when tab 696 (when tab
627 (tab-bar-list-delete-from-list tab) 697 (tab-bar-list-delete-from-list tab)
628 (beginning-of-line) 698 (beginning-of-line)
629 (delete-region (point) (progn (forward-line 1) (point)))))))) 699 (delete-region (point) (progn (forward-line 1) (point))))))))
630 (beginning-of-line) 700 (beginning-of-line)
631 (move-to-column tab-bar-list-column) 701 (move-to-column tab-bar-list-column)
632 (when tab-bar-mode 702 (when tab-bar-mode
633 (force-window-update))) 703 (force-mode-line-update)))
634 704
635(defun tab-bar-list-select () 705(defun tab-bar-list-select ()
636 "Select this line's window configuration. 706 "Select this line's window configuration.
@@ -662,7 +732,7 @@ in the selected frame."
662Like \\[switch-to-buffer-other-frame] (which see), but creates a new tab." 732Like \\[switch-to-buffer-other-frame] (which see), but creates a new tab."
663 (interactive 733 (interactive
664 (list (read-buffer-to-switch "Switch to buffer in other tab: "))) 734 (list (read-buffer-to-switch "Switch to buffer in other tab: ")))
665 (tab-bar-add-tab) 735 (tab-bar-new-tab)
666 (delete-other-windows) 736 (delete-other-windows)
667 (switch-to-buffer buffer-or-name norecord)) 737 (switch-to-buffer buffer-or-name norecord))
668 738
@@ -674,14 +744,14 @@ Like \\[find-file-other-frame] (which see), but creates a new tab."
674 (confirm-nonexistent-file-or-buffer))) 744 (confirm-nonexistent-file-or-buffer)))
675 (let ((value (find-file-noselect filename nil nil wildcards))) 745 (let ((value (find-file-noselect filename nil nil wildcards)))
676 (if (listp value) 746 (if (listp value)
677 (progn 747 (progn
678 (setq value (nreverse value)) 748 (setq value (nreverse value))
679 (switch-to-buffer-other-tab (car value)) 749 (switch-to-buffer-other-tab (car value))
680 (mapc 'switch-to-buffer (cdr value)) 750 (mapc 'switch-to-buffer (cdr value))
681 value) 751 value)
682 (switch-to-buffer-other-tab value)))) 752 (switch-to-buffer-other-tab value))))
683 753
684(define-key ctl-x-6-map "2" 'tab-bar-add-tab) 754(define-key ctl-x-6-map "2" 'tab-bar-new-tab)
685(define-key ctl-x-6-map "0" 'tab-bar-close-current-tab) 755(define-key ctl-x-6-map "0" 'tab-bar-close-current-tab)
686(define-key ctl-x-6-map "b" 'switch-to-buffer-other-tab) 756(define-key ctl-x-6-map "b" 'switch-to-buffer-other-tab)
687(define-key ctl-x-6-map "f" 'find-file-other-tab) 757(define-key ctl-x-6-map "f" 'find-file-other-tab)
diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index cbe418a5a2c..ee9ec023ffd 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -99,9 +99,9 @@
99 99
100(defvar tab-line-add-map 100(defvar tab-line-add-map
101 (let ((map (make-sparse-keymap))) 101 (let ((map (make-sparse-keymap)))
102 (define-key map [tab-line mouse-1] 'tab-line-add-tab) 102 (define-key map [tab-line mouse-1] 'tab-line-new-tab)
103 (define-key map [tab-line mouse-2] 'tab-line-add-tab) 103 (define-key map [tab-line mouse-2] 'tab-line-new-tab)
104 (define-key map "\C-m" 'tab-line-add-tab) 104 (define-key map "\C-m" 'tab-line-new-tab)
105 map) 105 map)
106 "Local keymap to add `tab-line-mode' window tabs.") 106 "Local keymap to add `tab-line-mode' window tabs.")
107 107
@@ -113,12 +113,18 @@
113 "Local keymap to close `tab-line-mode' window tabs.") 113 "Local keymap to close `tab-line-mode' window tabs.")
114 114
115 115
116(defvar tab-line-separator nil) 116(defcustom tab-line-new-tab-choice t
117 117 "Defines what to show in a new tab.
118(defvar tab-line-tab-name-ellipsis 118If t, display a selection menu with all available buffers.
119 (if (char-displayable-p ?…) "…" "...")) 119If the value is a function, call it with no arguments.
120If nil, don't show the new tab button."
121 :type '(choice (const :tag "Buffer menu" t)
122 (function :tag "Function")
123 (const :tag "No button" nil))
124 :group 'tab-line
125 :version "27.1")
120 126
121(defvar tab-line-button-new 127(defvar tab-line-new-button
122 (propertize " + " 128 (propertize " + "
123 'display `(image :type xpm 129 'display `(image :type xpm
124 :file ,(expand-file-name 130 :file ,(expand-file-name
@@ -131,7 +137,23 @@
131 'help-echo "Click to add tab") 137 'help-echo "Click to add tab")
132 "Button for creating a new tab.") 138 "Button for creating a new tab.")
133 139
134(defvar tab-line-button-close 140(defcustom tab-line-close-button-show t
141 "Defines where to show the close tab button.
142If t, show the close tab button on all tabs.
143If `selected', show it only on the selected tab.
144If `non-selected', show it only on non-selected tab.
145If nil, don't show it at all."
146 :type '(choice (const :tag "On all tabs" t)
147 (const :tag "On selected tab" selected)
148 (const :tag "On non-selected tabs" non-selected)
149 (const :tag "None" nil))
150 :set (lambda (sym val)
151 (set sym val)
152 (force-mode-line-update))
153 :group 'tab-line
154 :version "27.1")
155
156(defvar tab-line-close-button
135 (propertize " x" 157 (propertize " x"
136 'display `(image :type xpm 158 'display `(image :type xpm
137 :file ,(expand-file-name 159 :file ,(expand-file-name
@@ -144,6 +166,11 @@
144 'help-echo "Click to close tab") 166 'help-echo "Click to close tab")
145 "Button for closing the clicked tab.") 167 "Button for closing the clicked tab.")
146 168
169(defvar tab-line-separator nil)
170
171(defvar tab-line-tab-name-ellipsis
172 (if (char-displayable-p ?…) "…" "..."))
173
147 174
148(defvar tab-line-tab-name-function #'tab-line-tab-name 175(defvar tab-line-tab-name-function #'tab-line-tab-name
149 "Function to get a tab name. 176 "Function to get a tab name.
@@ -218,7 +245,12 @@ variable `tab-line-tabs-function'."
218 (apply 'propertize (concat (propertize 245 (apply 'propertize (concat (propertize
219 (funcall tab-line-tab-name-function tab tabs) 246 (funcall tab-line-tab-name-function tab tabs)
220 'keymap tab-line-tab-map) 247 'keymap tab-line-tab-map)
221 tab-line-button-close) 248 (or (and tab-line-close-button-show
249 (not (eq tab-line-close-button-show
250 (if (eq tab selected-buffer)
251 'non-selected
252 'selected)))
253 tab-line-close-button) ""))
222 `( 254 `(
223 tab ,tab 255 tab ,tab
224 face ,(if (eq tab selected-buffer) 256 face ,(if (eq tab selected-buffer)
@@ -226,15 +258,19 @@ variable `tab-line-tabs-function'."
226 'tab-line-tab-inactive) 258 'tab-line-tab-inactive)
227 mouse-face tab-line-highlight)))) 259 mouse-face tab-line-highlight))))
228 tabs) 260 tabs)
229 (list (concat separator tab-line-button-new))))) 261 (list (concat separator (when tab-line-new-tab-choice
262 tab-line-new-button))))))
230 263
231 264
232(defun tab-line-add-tab (&optional e) 265(defun tab-line-new-tab (&optional e)
266 "Add a new tab."
233 (interactive "e") 267 (interactive "e")
234 (if window-system ; (display-popup-menus-p) 268 (if (functionp tab-line-new-tab-choice)
235 (mouse-buffer-menu e) ; like (buffer-menu-open) 269 (funcall tab-line-new-tab-choice)
236 ;; tty menu doesn't support mouse clicks, so use tmm 270 (if window-system ; (display-popup-menus-p)
237 (tmm-prompt (mouse-buffer-menu-keymap)))) 271 (mouse-buffer-menu e) ; like (buffer-menu-open)
272 ;; tty menu doesn't support mouse clicks, so use tmm
273 (tmm-prompt (mouse-buffer-menu-keymap)))))
238 274
239(defun tab-line-select-tab (&optional e) 275(defun tab-line-select-tab (&optional e)
240 "Switch to the selected tab. 276 "Switch to the selected tab.