aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuri Linkov2019-09-22 23:40:04 +0300
committerJuri Linkov2019-09-22 23:40:04 +0300
commit39255b9b4de0b036568b64d7170ba8076d96be1d (patch)
tree66e9ca5f71b1f1f47e1cf35106ebc1e0454f3aef
parentab2f42cad5259db6626f0da1eb01421c5214c799 (diff)
downloademacs-39255b9b4de0b036568b64d7170ba8076d96be1d.tar.gz
emacs-39255b9b4de0b036568b64d7170ba8076d96be1d.zip
Improve customizability and better tab separators.
* lisp/tab-bar.el (tab-bar-tabs-function): New defvar. * lisp/tab-line.el (tab-line-tab-name-function) (tab-line-tabs-function): New defvars.
-rw-r--r--etc/images/tabs/close.xpm2
-rw-r--r--lisp/tab-bar.el45
-rw-r--r--lisp/tab-line.el69
-rw-r--r--src/xdisp.c2
4 files changed, 67 insertions, 51 deletions
diff --git a/etc/images/tabs/close.xpm b/etc/images/tabs/close.xpm
index 48f063fa43b..1c3f4d8fd7d 100644
--- a/etc/images/tabs/close.xpm
+++ b/etc/images/tabs/close.xpm
@@ -2,7 +2,7 @@
2static char * close_xpm[] = { 2static char * close_xpm[] = {
3"9 9 4 1", 3"9 9 4 1",
4" c None", 4" c None",
5". c #CCCCCC", 5". c #BFBFBF",
6"+ c #000000", 6"+ c #000000",
7"@ c #808080", 7"@ c #808080",
8" ..... ", 8" ..... ",
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 7afb39a0dda..3b6415ad13d 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -1,4 +1,4 @@
1;;; tab-bar.el --- frame-local tab bar with named persistent window configurations -*- lexical-binding: t; -*- 1;;; tab-bar.el --- frame-local tabs with named persistent window configurations -*- lexical-binding: t; -*-
2 2
3;; Copyright (C) 2019 Free Software Foundation, Inc. 3;; Copyright (C) 2019 Free Software Foundation, Inc.
4 4
@@ -23,7 +23,7 @@
23 23
24;;; Commentary: 24;;; Commentary:
25 25
26;; Provides `tab-bar-mode' to control display of the tab-bar and 26;; Provides `tab-bar-mode' to control display of the tab bar and
27;; bindings for the global tab bar. 27;; bindings for the global tab bar.
28 28
29;; The normal global binding for [tab-bar] (below) uses the value of 29;; The normal global binding for [tab-bar] (below) uses the value of
@@ -36,7 +36,7 @@
36 36
37 37
38(defgroup tab-bar nil 38(defgroup tab-bar nil
39 "Frame-local tab bar." 39 "Frame-local tabs."
40 :group 'convenience 40 :group 'convenience
41 :version "27.1") 41 :version "27.1")
42 42
@@ -79,13 +79,6 @@
79 :version "27.1" 79 :version "27.1"
80 :group 'tab-bar-faces) 80 :group 'tab-bar-faces)
81 81
82(defface tab-bar-separator
83 '((t
84 :inverse-video nil))
85 "Tab bar face for separator."
86 :version "27.1"
87 :group 'tab-bar-faces)
88
89 82
90(define-minor-mode tab-bar-mode 83(define-minor-mode tab-bar-mode
91 "Toggle the tab bar in all graphical frames (Tab Bar mode)." 84 "Toggle the tab bar in all graphical frames (Tab Bar mode)."
@@ -108,8 +101,8 @@
108 (global-set-key [(control tab)] 'tab-bar-switch-to-next-tab))) 101 (global-set-key [(control tab)] 'tab-bar-switch-to-next-tab)))
109 102
110(defun tab-bar-handle-mouse (event) 103(defun tab-bar-handle-mouse (event)
111 "Text-mode emulation of switching tabs on the tab-bar. 104 "Text-mode emulation of switching tabs on the tab bar.
112This command is used when you click the mouse in the tab-bar 105This command is used when you click the mouse in the tab bar
113on a console which has no window system but does have a mouse." 106on a console which has no window system but does have a mouse."
114 (interactive "e") 107 (interactive "e")
115 (let* ((x-position (car (posn-x-y (event-start event)))) 108 (let* ((x-position (car (posn-x-y (event-start event))))
@@ -159,8 +152,7 @@ Its main job is to show tabs in the tab bar."
159 (puthash key tab-bar-map tab-bar-keymap-cache))))) 152 (puthash key tab-bar-map tab-bar-keymap-cache)))))
160 153
161 154
162(defvar tab-bar-separator 155(defvar tab-bar-separator nil)
163 (propertize " " 'face 'tab-bar-separator))
164 156
165(defvar tab-bar-button-new 157(defvar tab-bar-button-new
166 (propertize " + " 158 (propertize " + "
@@ -173,7 +165,7 @@ Its main job is to show tabs in the tab bar."
173 "Button for creating a new tab.") 165 "Button for creating a new tab.")
174 166
175(defvar tab-bar-button-close 167(defvar tab-bar-button-close
176 (propertize "x" 168 (propertize " x"
177 'display `(image :type xpm 169 'display `(image :type xpm
178 :file ,(expand-file-name 170 :file ,(expand-file-name
179 "images/tabs/close.xpm" 171 "images/tabs/close.xpm"
@@ -188,9 +180,16 @@ Its main job is to show tabs in the tab bar."
188 "Generate tab name in the context of the selected frame." 180 "Generate tab name in the context of the selected frame."
189 (mapconcat 181 (mapconcat
190 (lambda (w) (buffer-name (window-buffer w))) 182 (lambda (w) (buffer-name (window-buffer w)))
191 (window-list) 183 (window-list-1 (frame-first-window) 'nomini)
192 ", ")) 184 ", "))
193 185
186(defvar tab-bar-tabs-function #'tab-bar-tabs
187 "Function to get a list of tabs to display in the tab bar.
188This function should return a list of alists with parameters
189that include at least the element (name . TAB-NAME).
190For example, '((tab (name . \"Tab 1\")) (current-tab (name . \"Tab 2\")))
191By default, use function `tab-bar-tabs'.")
192
194(defun tab-bar-tabs () 193(defun tab-bar-tabs ()
195 "Return a list of tabs belonging to the selected frame. 194 "Return a list of tabs belonging to the selected frame.
196Ensure the frame parameter `tabs' is pre-populated. 195Ensure the frame parameter `tabs' is pre-populated.
@@ -203,13 +202,15 @@ Return its existing value or a new value."
203 202
204(defun tab-bar-make-keymap-1 () 203(defun tab-bar-make-keymap-1 ()
205 "Generate an actual keymap from `tab-bar-map', without caching." 204 "Generate an actual keymap from `tab-bar-map', without caching."
206 (let ((i 0)) 205 (let ((separator (or tab-bar-separator (if window-system " " "|")))
206 (i 0))
207 (append 207 (append
208 '(keymap (mouse-1 . tab-bar-handle-mouse)) 208 '(keymap (mouse-1 . tab-bar-handle-mouse))
209 (mapcan 209 (mapcan
210 (lambda (tab) 210 (lambda (tab)
211 (setq i (1+ i)) 211 (setq i (1+ i))
212 (append 212 (append
213 `((,(intern (format "sep-%i" i)) menu-item ,separator ignore))
213 (cond 214 (cond
214 ((eq (car tab) 'current-tab) 215 ((eq (car tab) 'current-tab)
215 `((current-tab 216 `((current-tab
@@ -233,13 +234,11 @@ Return its existing value or a new value."
233 menu-item "" 234 menu-item ""
234 ,(lambda () 235 ,(lambda ()
235 (interactive) 236 (interactive)
236 (tab-bar-close-tab tab)))) 237 (tab-bar-close-tab tab))))))
237 (when (and (stringp tab-bar-separator) 238 (funcall tab-bar-tabs-function))
238 (> (length tab-bar-separator) 0))
239 `((,(intern (format "sep-%i" i)) menu-item ,tab-bar-separator ignore)))))
240 (tab-bar-tabs))
241 (when tab-bar-button-new 239 (when tab-bar-button-new
242 `((add-tab menu-item ,tab-bar-button-new tab-bar-add-tab 240 `((sep-add-tab menu-item ,separator ignore)
241 (add-tab menu-item ,tab-bar-button-new tab-bar-add-tab
243 :help "New tab")))))) 242 :help "New tab"))))))
244 243
245 244
diff --git a/lisp/tab-line.el b/lisp/tab-line.el
index 6b1ce03d26e..169f7b82042 100644
--- a/lisp/tab-line.el
+++ b/lisp/tab-line.el
@@ -1,4 +1,4 @@
1;;; tab-line.el --- window-local tab line with window buffers -*- lexical-binding: t; -*- 1;;; tab-line.el --- window-local tabs with window buffers -*- lexical-binding: t; -*-
2 2
3;; Copyright (C) 2019 Free Software Foundation, Inc. 3;; Copyright (C) 2019 Free Software Foundation, Inc.
4 4
@@ -31,7 +31,7 @@
31 31
32 32
33(defgroup tab-line nil 33(defgroup tab-line nil
34 "Window-local tab line." 34 "Window-local tabs."
35 :group 'convenience 35 :group 'convenience
36 :version "27.1") 36 :version "27.1")
37 37
@@ -70,7 +70,7 @@
70 :background "grey75") 70 :background "grey75")
71 (t 71 (t
72 :inverse-video t)) 72 :inverse-video t))
73 "Tab line face for non-selected tabs." 73 "Tab line face for non-selected tab."
74 :version "27.1" 74 :version "27.1"
75 :group 'tab-line-faces) 75 :group 'tab-line-faces)
76 76
@@ -82,7 +82,7 @@
82 82
83(defface tab-line-close-highlight 83(defface tab-line-close-highlight
84 '((t :foreground "red")) 84 '((t :foreground "red"))
85 "Tab line face for highlighting." 85 "Tab line face for highlighting of the close button."
86 :version "27.1" 86 :version "27.1"
87 :group 'tab-line-faces) 87 :group 'tab-line-faces)
88 88
@@ -90,11 +90,10 @@
90(defvar tab-line-tab-map 90(defvar tab-line-tab-map
91 (let ((map (make-sparse-keymap))) 91 (let ((map (make-sparse-keymap)))
92 (define-key map [tab-line mouse-1] 'tab-line-select-tab) 92 (define-key map [tab-line mouse-1] 'tab-line-select-tab)
93 (define-key map [tab-line mouse-2] 'tab-line-select-tab) 93 (define-key map [tab-line mouse-2] 'tab-line-close-tab)
94 (define-key map [tab-line mouse-4] 'tab-line-switch-to-prev-tab) 94 (define-key map [tab-line mouse-4] 'tab-line-switch-to-prev-tab)
95 (define-key map [tab-line mouse-5] 'tab-line-switch-to-next-tab) 95 (define-key map [tab-line mouse-5] 'tab-line-switch-to-next-tab)
96 (define-key map "\C-m" 'tab-line-select-tab) 96 (define-key map "\C-m" 'tab-line-select-tab)
97 (define-key map [follow-link] 'mouse-face)
98 map) 97 map)
99 "Local keymap for `tab-line-mode' window tabs.") 98 "Local keymap for `tab-line-mode' window tabs.")
100 99
@@ -103,7 +102,6 @@
103 (define-key map [tab-line mouse-1] 'tab-line-add-tab) 102 (define-key map [tab-line mouse-1] 'tab-line-add-tab)
104 (define-key map [tab-line mouse-2] 'tab-line-add-tab) 103 (define-key map [tab-line mouse-2] 'tab-line-add-tab)
105 (define-key map "\C-m" 'tab-line-add-tab) 104 (define-key map "\C-m" 'tab-line-add-tab)
106 (define-key map [follow-link] 'mouse-face)
107 map) 105 map)
108 "Local keymap to add `tab-line-mode' window tabs.") 106 "Local keymap to add `tab-line-mode' window tabs.")
109 107
@@ -111,12 +109,11 @@
111 (let ((map (make-sparse-keymap))) 109 (let ((map (make-sparse-keymap)))
112 (define-key map [tab-line mouse-1] 'tab-line-close-tab) 110 (define-key map [tab-line mouse-1] 'tab-line-close-tab)
113 (define-key map [tab-line mouse-2] 'tab-line-close-tab) 111 (define-key map [tab-line mouse-2] 'tab-line-close-tab)
114 (define-key map [follow-link] 'mouse-face)
115 map) 112 map)
116 "Local keymap to close `tab-line-mode' window tabs.") 113 "Local keymap to close `tab-line-mode' window tabs.")
117 114
118 115
119(defvar tab-line-separator " ") 116(defvar tab-line-separator nil)
120 117
121(defvar tab-line-tab-name-ellipsis 118(defvar tab-line-tab-name-ellipsis
122 (if (char-displayable-p ?…) "…" "...")) 119 (if (char-displayable-p ?…) "…" "..."))
@@ -135,7 +132,7 @@
135 "Button for creating a new tab.") 132 "Button for creating a new tab.")
136 133
137(defvar tab-line-button-close 134(defvar tab-line-button-close
138 (propertize "x" 135 (propertize " x"
139 'display `(image :type xpm 136 'display `(image :type xpm
140 :file ,(expand-file-name 137 :file ,(expand-file-name
141 "images/tabs/close.xpm" 138 "images/tabs/close.xpm"
@@ -148,9 +145,16 @@
148 "Button for closing the clicked tab.") 145 "Button for closing the clicked tab.")
149 146
150 147
148(defvar tab-line-tab-name-function #'tab-line-tab-name
149 "Function to get a tab name.
150Function gets two arguments: tab to get name for and a list of tabs
151to display. By default, use function `tab-line-tab-name'.")
152
151(defun tab-line-tab-name (buffer &optional buffers) 153(defun tab-line-tab-name (buffer &optional buffers)
152 "Generate tab name from BUFFER. 154 "Generate tab name from BUFFER.
153Reduce tab width proportionally to space taken by other tabs." 155Reduce tab width proportionally to space taken by other tabs.
156This function can be overridden by changing the default value of the
157variable `tab-line-tab-name-function'."
154 (let ((tab-name (buffer-name buffer)) 158 (let ((tab-name (buffer-name buffer))
155 (limit (when buffers 159 (limit (when buffers
156 (max 1 (- (/ (window-width) (length buffers)) 3))))) 160 (max 1 (- (/ (window-width) (length buffers)) 3)))))
@@ -161,10 +165,22 @@ Reduce tab width proportionally to space taken by other tabs."
161 'help-echo tab-name)))) 165 'help-echo tab-name))))
162 166
163(defvar tab-line-tabs-limit 15 167(defvar tab-line-tabs-limit 15
164 "Maximum number of buffer tabs displayed in the window tab-line.") 168 "Maximum number of buffer tabs displayed in the tab line.")
165 169
166(defun tab-line-tabs (&optional window) 170(defvar tab-line-tabs-function #'tab-line-tabs
167 (let* ((buffer (window-buffer window)) 171 "Function to get a list of tabs to display in the tab line.
172This function should return either a list of buffers whose names will
173be displayed, or just a list of strings to display in the tab line.
174By default, use function `tab-line-tabs'.")
175
176(defun tab-line-tabs ()
177 "Return a list of tabs that should be displayed in the tab line.
178By default returns a list of window buffers, i.e. buffers previously
179shown in the same window where the tab line is displayed.
180This list can be overridden by changing the default value of the
181variable `tab-line-tabs-function'."
182 (let* ((window (selected-window))
183 (buffer (window-buffer window))
168 (next-buffers (seq-remove (lambda (b) (eq b buffer)) 184 (next-buffers (seq-remove (lambda (b) (eq b buffer))
169 (window-next-buffers window))) 185 (window-next-buffers window)))
170 (next-buffers (seq-filter #'buffer-live-p next-buffers)) 186 (next-buffers (seq-filter #'buffer-live-p next-buffers))
@@ -191,25 +207,26 @@ Reduce tab width proportionally to space taken by other tabs."
191(defun tab-line-format () 207(defun tab-line-format ()
192 "Template for displaying tab line for selected window." 208 "Template for displaying tab line for selected window."
193 (let* ((window (selected-window)) 209 (let* ((window (selected-window))
194 (buffer (window-buffer window)) 210 (selected-buffer (window-buffer window))
195 (buffer-tabs (tab-line-tabs window))) 211 (tabs (funcall tab-line-tabs-function))
212 (separator (or tab-line-separator (if window-system " " "|"))))
196 (append 213 (append
197 (mapcar 214 (mapcar
198 (lambda (b) 215 (lambda (tab)
199 (concat 216 (concat
200 (or tab-line-separator "") 217 separator
201 (apply 'propertize (concat (propertize 218 (apply 'propertize (concat (propertize
202 (tab-line-tab-name b buffer-tabs) 219 (funcall tab-line-tab-name-function tab tabs)
203 'keymap tab-line-tab-map) 220 'keymap tab-line-tab-map)
204 tab-line-button-close) 221 tab-line-button-close)
205 `( 222 `(
206 buffer ,b 223 tab ,tab
207 face ,(if (eq b buffer) 224 face ,(if (eq tab selected-buffer)
208 'tab-line-tab 225 'tab-line-tab
209 'tab-line-tab-inactive) 226 'tab-line-tab-inactive)
210 mouse-face tab-line-highlight)))) 227 mouse-face tab-line-highlight))))
211 buffer-tabs) 228 tabs)
212 (list (concat tab-line-separator tab-line-button-new))))) 229 (list (concat separator tab-line-button-new)))))
213 230
214 231
215(defun tab-line-add-tab (&optional e) 232(defun tab-line-add-tab (&optional e)
@@ -227,7 +244,7 @@ using the `previous-buffer' command."
227 (interactive "e") 244 (interactive "e")
228 (let* ((posnp (event-start e)) 245 (let* ((posnp (event-start e))
229 (window (posn-window posnp)) 246 (window (posn-window posnp))
230 (buffer (get-pos-property 1 'buffer (car (posn-string posnp)))) 247 (buffer (get-pos-property 1 'tab (car (posn-string posnp))))
231 (window-buffer (window-buffer window)) 248 (window-buffer (window-buffer window))
232 (next-buffers (seq-remove (lambda (b) (eq b window-buffer)) 249 (next-buffers (seq-remove (lambda (b) (eq b window-buffer))
233 (window-next-buffers window))) 250 (window-next-buffers window)))
@@ -260,7 +277,7 @@ using the `previous-buffer' command."
260 (interactive "e") 277 (interactive "e")
261 (let* ((posnp (event-start e)) 278 (let* ((posnp (event-start e))
262 (window (posn-window posnp)) 279 (window (posn-window posnp))
263 (buffer (get-pos-property 1 'buffer (car (posn-string posnp))))) 280 (buffer (get-pos-property 1 'tab (car (posn-string posnp)))))
264 (with-selected-window window 281 (with-selected-window window
265 (if (eq buffer (current-buffer)) 282 (if (eq buffer (current-buffer))
266 (bury-buffer) 283 (bury-buffer)
diff --git a/src/xdisp.c b/src/xdisp.c
index 197493bfbb8..0fc387b8ffb 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12764,7 +12764,7 @@ build_desired_tab_bar_string (struct frame *f)
12764 caption = Qnil; 12764 caption = Qnil;
12765 12765
12766 /* Prepare F->desired_tab_bar_string. Make a new string. */ 12766 /* Prepare F->desired_tab_bar_string. Make a new string. */
12767 fset_desired_tab_bar_string (f, build_string (" ")); 12767 fset_desired_tab_bar_string (f, build_string (""));
12768 12768
12769 /* Put a `display' property on the string for the captions to display, 12769 /* Put a `display' property on the string for the captions to display,
12770 put a `menu_item' property on tab-bar items with a value that 12770 put a `menu_item' property on tab-bar items with a value that