diff options
| author | Juri Linkov | 2019-09-25 23:21:37 +0300 |
|---|---|---|
| committer | Juri Linkov | 2019-09-25 23:21:37 +0300 |
| commit | e47c389cfd446f6ac36a240fd11134ad2b91fb81 (patch) | |
| tree | 45800e83091f667f6fb754e22029d2dd33889000 | |
| parent | 848e21b0491cb0b2f8e3a59e9f5cabd7210dca5e (diff) | |
| download | emacs-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.el | 182 | ||||
| -rw-r--r-- | lisp/tab-line.el | 68 |
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. | ||
| 157 | If t, start a new tab with the current buffer, i.e. the buffer | ||
| 158 | that was current before calling the command that adds a new tab | ||
| 159 | (this is the same what `make-frame' does by default). | ||
| 160 | If the value is a string, switch to a buffer if it exists, or switch | ||
| 161 | to a buffer visiting the file or directory that the string specifies. | ||
| 162 | If the value is a function, call it with no arguments and switch to | ||
| 163 | the buffer that it returns. | ||
| 164 | If nil, duplicate the contents of the tab that was active | ||
| 165 | before 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. | ||
| 187 | If t, show the close tab button on all tabs. | ||
| 188 | If `selected', show it only on the selected tab. | ||
| 189 | If `non-selected', show it only on non-selected tab. | ||
| 190 | If 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. | ||
| 218 | Function gets no arguments. | ||
| 219 | By 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'.") | |||
| 195 | Ensure the frame parameter `tabs' is pre-populated. | 238 | Ensure the frame parameter `tabs' is pre-populated. |
| 196 | Return its existing value or a new value." | 239 | Return 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. |
| 321 | If `leftmost', create as the first tab. | 378 | If `leftmost', create as the first tab. |
| 322 | If `left', create to the left from the current tab. | 379 | If `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. | |||
| 365 | If `right', select the adjacent right tab." | 433 | If `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." | |||
| 662 | Like \\[switch-to-buffer-other-frame] (which see), but creates a new tab." | 732 | Like \\[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 | 118 | If t, display a selection menu with all available buffers. |
| 119 | (if (char-displayable-p ?…) "…" "...")) | 119 | If the value is a function, call it with no arguments. |
| 120 | If 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. | ||
| 142 | If t, show the close tab button on all tabs. | ||
| 143 | If `selected', show it only on the selected tab. | ||
| 144 | If `non-selected', show it only on non-selected tab. | ||
| 145 | If 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. |