changelog shortlog tags changeset files revisions annotate raw

tabbar.el

changeset 66: 5b737eefe5ea
author: kim.vanwyk
date: Wed Nov 10 15:19:03 2010 +0200 (18 months ago)
permissions: -rw-r--r--
description: Adding CSharp Mode and Google Weather
1;;; tabbar.el --- Display a tab bar in the header line
2
3;; Copyright (C) 2003 David Ponce
4
5;; Author: David Ponce <david@dponce.com>
6;; Maintainer: David Ponce <david@dponce.com>
7;; Created: 25 February 2003
8;; Keywords: convenience
9;; Revision: $Id: tabbar.el,v 1.20 2003/06/05 08:15:49 ponced Exp $
10
11(defconst tabbar-version "1.3")
12
13;; This file is not part of GNU Emacs.
14
15;; This program is free software; you can redistribute it and/or
16;; modify it under the terms of the GNU General Public License as
17;; published by the Free Software Foundation; either version 2, or (at
18;; your option) any later version.
19
20;; This program is distributed in the hope that it will be useful, but
21;; WITHOUT ANY WARRANTY; without even the implied warranty of
22;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23;; General Public License for more details.
24
25;; You should have received a copy of the GNU General Public License
26;; along with this program; see the file COPYING. If not, write to
27;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
28;; Boston, MA 02111-1307, USA.
29
30;;; Commentary:
31;;
32;; This library provides a minor mode to display tabs in the header
33;; line. It works only on GNU Emacs 21.
34;;
35;; M-x `tabbar-mode' toggle the display of the tab bar, globally.
36;;
37;; M-x `tabbar-local-mode' toggle the display of the tab bar, locally
38;; in the current buffer, when the global mode in on. This mode
39;; permit to see the tab bar in a buffer where the header line is
40;; already used by another mode (like `info' buffers). That command
41;; is particularly useful when it is given a keyboard shortcut, like
42;; this:
43;;
44;; (global-set-key [(control f10)] 'tabbar-local-mode)
45;;
46;; It is possible to navigate through tabs using commands (that is,
47;; using the keyboard). The main commands to cycle through tabs are:
48;;
49;; - `tabbar-forward' select the next available tab.
50;; - `tabbar-backward' select the previous available tab.
51;;
52;; It is worth defining keys for them. For example:
53;;
54;; (global-set-key [(control shift tab)] 'tabbar-backward)
55;; (global-set-key [(control tab)] 'tabbar-forward)
56;;
57;; The default cycle is to first try to select the tab just
58;; after/before the selected tab. If this is the last/first tab, then
59;; the first/last tab of the next/previous group of tabs is selected.
60;; That behavior is controlled by the `tabbar-cycling-scope' option.
61;;
62;; The following specialized commands can be useful too:
63;;
64;; - `tabbar-forward-tab'/`tabbar-backward-tab'
65;; Navigate through visible tabs only.
66;;
67;; - `tabbar-forward-group'/`tabbar-backward-group'
68;; Navigate through tab groups only.
69;;
70;; Core
71;; ----
72;;
73;; The content of the tab bar is represented by an internal data
74;; structure: a tab set. A tab set is a collection of tabs,
75;; identified by an unique name. In a tab set, at any time, one and
76;; only one tab is designated as selected within the tab set.
77;;
78;; A tab is a simple data structure giving: the value of the tab, and
79;; a reference to its tab set container. A tab value can be any Lisp
80;; object, even if the most common value is probably a string. Each
81;; tab object is guaranteed to be unique.
82;;
83;; A tab set is displayed on the tab bar through a "view" defined by
84;; the index of the leftmost tab shown. Thus, it is possible to
85;; scroll the tab bar horizontally, by changing the start index of the
86;; tab set view.
87;;
88;; The visual representation of a tab set is a list a
89;; `header-line-format' template elements. Each template element is
90;; the visual representation of a tab. When the visual representation
91;; of a tab is required, the function specified in the variable
92;; `tabbar-tab-label-function' is called to obtain a label (a text
93;; representation) for that tab. Also, the function specified in the
94;; variable `tabbar-help-on-tab-function' is called when the mouse is
95;; on a tab. That function is passed the tab and can return a help
96;; string to display. Finally, when a tab is selected by clicking on
97;; it, the function specified in the variable
98;; `tabbar-select-tab-function' is called with the mouse event
99;; received, and the tab.
100;;
101;; To increase performance, the tab set automatically maintains its
102;; visual representation in a cache. As far as possible, that cache
103;; is used to display the tab set, and refreshed only when necessary.
104;;
105;; Several tab sets can be maintained at the same time. Only one is
106;; displayed on the tab bar, it is obtained by calling the function
107;; specified in the variable `tabbar-current-tabset-function'.
108;;
109;; A special tab set is maintained, that contains the list of
110;; currently selected tabs, in existing tab sets. For example, a such
111;; tab set can be used to display a tab bar with a tab for each
112;; created tab set, allowing to switch to another tab set by clicking
113;; on the corresponding tab.
114;;
115;; Three buttons are displayed to the left, on the tab bar: the "home"
116;; button, the "scroll left" and the "scroll right" buttons. The
117;; "home" button is a general purpose button used to change something
118;; on the tab bar. The scroll left and scroll right buttons are used
119;; to scroll tabs horizontally. The following variables are
120;; available, for respectively the `home', `scroll-left' and
121;; `scroll-right' value of `<button>':
122;;
123;; `tabbar-<button>-function'
124;; Specify a function called when clicking on the button. The
125;; function is passed the mouse event received.
126;;
127;; `tabbar-<button>-help-function'
128;; Specify a function to obtain a help string displayed when the
129;; mouse is onto the button. The function is called with no
130;; arguments.
131;;
132;; The appearance of tabs and buttons is also customizable (see the
133;; code for more details).
134;;
135;; Buffer tabs
136;; -----------
137;;
138;; The default tab bar implementation provided, displays buffers in
139;; dedicated tabs. Selecting a tab, switch (mouse-1), or pop
140;; (mouse-2), to the buffer it contains.
141;;
142;; The list of buffers put in tabs is provided by the function
143;; specified in the variable `tabbar-buffer-list-function'. The
144;; default function: `tabbar-buffer-list', excludes buffers whose name
145;; starts with a space, when they are not visiting a file.
146;;
147;; Buffers are organized in groups, each one represented by a tab set.
148;; A buffer can have no group, or belong to more than one group. The
149;; function specified by the variable `tabbar-buffer-groups-function'
150;; is called for each buffer to obtain its groups. The default
151;; function provided: `tabbar-buffer-groups' organizes buffers
152;; depending on their major mode (see that function for details).
153;;
154;; The "home" button toggles display of buffer groups on the tab bar,
155;; allowing to easily choose another buffer group by clicking on its
156;; tab.
157;;
158;; The scroll buttons permit to scroll tabs when some of them are
159;; outside the tab bar visible area.
160
161;;; History:
162;;
163
164;;; Code:
165
166;;; Options
167;;
168(defgroup tabbar nil
169 "Display a tab bar in the header line."
170 :group 'convenience)
171
172(defcustom tabbar-cycling-scope nil
173 "*Specify the scope of cyclic navigation through tabs.
174The following scopes are possible:
175
176- `tabs'
177 Navigate through visible tabs only.
178- `groups'
179 Navigate through tab groups only.
180- default
181 Navigate through visible tabs, then through tab groups."
182 :group 'tabbar
183 :type '(choice :tag "Cycle through..."
184 (const :tag "Visible Tabs Only" tabs)
185 (const :tag "Tab Groups Only" groups)
186 (const :tag "Visible Tabs then Tab Groups" nil)))
187
188(defcustom tabbar-inhibit-functions
189 '(tabbar-default-inhibit-function)
190 "List of functions to be called before displaying the tab bar.
191Those functions are called one by one, with no arguments, until one of
192them returns a non-nil value, and thus, prevent to display the tab
193bar."
194 :group 'tabbar
195 :type 'hook)
196
197(defcustom tabbar-current-tabset-function
198 'tabbar-buffer-tabs
199 "Function called with no argument to obtain the current tab set.
200This is the tab set displayed on the tab bar."
201 :group 'tabbar
202 :type 'function)
203
204(defcustom tabbar-tab-label-function
205 'tabbar-buffer-tab-label
206 "Function that obtains a tab label displayed on the tab bar.
207The function is passed a tab and should return a string."
208 :group 'tabbar
209 :type 'function)
210
211(defcustom tabbar-select-tab-function
212 'tabbar-buffer-select-tab
213 "Function that select a tab.
214The function is passed a mouse event and a tab, and should make it the
215selected tab."
216 :group 'tabbar
217 :type 'function)
218
219(defcustom tabbar-help-on-tab-function
220 'tabbar-buffer-help-on-tab
221 "Function to obtain a help string for a tab.
222The help string is displayed when the mouse is onto the button. The
223function is passed the tab and should return a help string or nil for
224none."
225 :group 'tabbar
226 :type 'function)
227
228(defcustom tabbar-home-function
229 'tabbar-buffer-toggle-group-mode
230 "Function called when clicking on the tab bar home button.
231The function is passed the mouse event received."
232 :group 'tabbar
233 :type 'function)
234
235(defcustom tabbar-home-help-function
236 'tabbar-buffer-toggle-group-mode-help
237 "Function to obtain a help string for the tab bar home button.
238The help string is displayed when the mouse is onto the button.
239The function is called with no arguments."
240 :group 'tabbar
241 :type 'function)
242
243(defcustom tabbar-scroll-left-function
244 'tabbar-scroll-left
245 "Function that scrolls tabs on left.
246The function is passed the mouse event received when clicking on the
247scroll left button. It should scroll the current tab set."
248 :group 'tabbar
249 :type 'function)
250
251(defcustom tabbar-scroll-left-help-function
252 'tabbar-scroll-left-help
253 "Function to obtain a help string for the scroll left button.
254The help string is displayed when the mouse is onto the button.
255The function is called with no arguments."
256 :group 'tabbar
257 :type 'function)
258
259(defcustom tabbar-scroll-right-function
260 'tabbar-scroll-right
261 "Function that scrolls tabs on right.
262The function is passed the mouse event received when clicking on the
263scroll right button. It should scroll the current tab set."
264 :group 'tabbar
265 :type 'function)
266
267(defcustom tabbar-scroll-right-help-function
268 'tabbar-scroll-right-help
269 "Function to obtain a help string for the scroll right button.
270The help string is displayed when the mouse is onto the button.
271The function is called with no arguments."
272 :group 'tabbar
273 :type 'function)
274
275;;; Tab and tab set
276;;
277(defconst tabbar-tabsets-tabset-name "tabbar-tabsets-tabset"
278 "Name of the special tab set of existing tab sets.")
279
280(defsubst tabbar-make-tab (object tabset)
281 "Return a new tab with value OBJECT.
282TABSET is the tab set the tab belongs to."
283 (cons object tabset))
284
285(defsubst tabbar-tab-value (tab)
286 "Return the value of tab TAB."
287 (car tab))
288
289(defsubst tabbar-tab-tabset (tab)
290 "Return the tab set TAB belongs to."
291 (cdr tab))
292
293(defvar tabbar-tabsets nil
294 "The tab sets store.")
295
296(defvar tabbar-current-tabset nil
297 "The tab set currently displayed on the tab bar.")
298(make-variable-buffer-local 'tabbar-current-tabset)
299
300(defvar tabbar-last-selected-tab nil
301 "The last selected tab.")
302
303(defsubst tabbar-free-tabsets-store ()
304 "Free the tab set store."
305 (setq tabbar-tabsets nil
306 tabbar-current-tabset nil
307 tabbar-last-selected-tab nil))
308
309(defsubst tabbar-init-tabsets-store ()
310 "Initialize the tab set store."
311 (tabbar-free-tabsets-store)
312 (setq tabbar-tabsets (make-vector 31 0)))
313
314(defmacro tabbar-map-tabsets (function)
315 "Apply FUNCTION to each existing tab set.
316Return the list of the results."
317 (let ((result (make-symbol "result"))
318 (tabset (make-symbol "tabset")))
319 `(let (,result)
320 (mapatoms #'(lambda (,tabset)
321 (setq ,result
322 (cons (funcall ,function ,tabset)
323 ,result)))
324 tabbar-tabsets)
325 (nreverse ,result))))
326
327(defun tabbar-make-tabset (name &rest objects)
328 "Make a new tab set whose name is the string NAME.
329It is initialized with tabs build from the list of OBJECTS."
330 (let* ((tabset (intern name tabbar-tabsets))
331 (tabs (mapcar #'(lambda (object)
332 (tabbar-make-tab object tabset))
333 objects)))
334 (set tabset tabs)
335 (put tabset 'select (car tabs))
336 (put tabset 'start 0)
337 tabset))
338
339(defsubst tabbar-get-tabset (name)
340 "Return the tab set whose name is the string NAME.
341Return nil if not found."
342 (intern-soft name tabbar-tabsets))
343
344(defsubst tabbar-delete-tabset (tabset)
345 "Delete the tab set TABSET.
346That is, remove it from the tab sets store."
347 (unintern tabset tabbar-tabsets))
348
349(defsubst tabbar-tabs (tabset)
350 "Return the list of tabs in TABSET."
351 (symbol-value tabset))
352
353(defsubst tabbar-tab-values (tabset)
354 "Return the list of tab values in TABSET."
355 (mapcar 'tabbar-tab-value (tabbar-tabs tabset)))
356
357(defsubst tabbar-get-tab (object tabset)
358 "Search for a tab with value OBJECT in TABSET.
359Return the tab found, or nil if not found."
360 (assoc object (tabbar-tabs tabset)))
361
362(defsubst tabbar-member (tab tabset)
363 "Return non-nil if TAB is in TABSET."
364 (or (eq (tabbar-tab-tabset tab) tabset)
365 (memq tab (tabbar-tabs tabset))))
366
367(defsubst tabbar-template (tabset)
368 "Return the template to display TABSET in the header line."
369 (get tabset 'template))
370
371(defsubst tabbar-set-template (tabset template)
372 "Set the TABSET's header line format with TEMPLATE."
373 (put tabset 'template template))
374
375(defsubst tabbar-selected-tab (tabset)
376 "Return the tab selected in TABSET."
377 (get tabset 'select))
378
379(defsubst tabbar-selected-value (tabset)
380 "Return the value of the tab selected in TABSET."
381 (tabbar-tab-value (tabbar-selected-tab tabset)))
382
383(defsubst tabbar-selected-p (tab tabset)
384 "Return non-nil if TAB is the selected tab in TABSET."
385 (eq tab (tabbar-selected-tab tabset)))
386
387(defsubst tabbar-select-tab (tab tabset)
388 "Make TAB the selected tab in TABSET.
389Does nothing if TAB is not found in TABSET.
390Return TAB if selected, nil if not."
391 (when (tabbar-member tab tabset)
392 (or (tabbar-selected-p tab tabset)
393 (tabbar-set-template tabset nil))
394 (put tabset 'select tab)))
395
396(defsubst tabbar-select-tab-value (object tabset)
397 "Make the tab with value OBJECT, the selected tab in TABSET.
398Does nothing if a tab with value OBJECT is not found in TABSET.
399Return the tab selected, or nil if nothing was selected."
400 (tabbar-select-tab (tabbar-get-tab object tabset) tabset))
401
402(defsubst tabbar-start (tabset)
403 "Return the index of the first tab in the TABSET's view."
404 (get tabset 'start))
405
406(defsubst tabbar-view (tabset)
407 "Return the list of tabs in the TABSET's view."
408 (nthcdr (tabbar-start tabset) (tabbar-tabs tabset)))
409
410(defun tabbar-add-tab (tabset object &optional append)
411 "Add to TABSET a tab with value OBJECT if there isn't one there yet.
412If the tab is added, it is added at the beginning of the tab list,
413unless the optional argument APPEND is non-nil, in which case it is
414added at the end."
415 (let ((tabs (tabbar-tabs tabset)))
416 (if (tabbar-get-tab object tabset)
417 tabs
418 (let ((tab (tabbar-make-tab object tabset)))
419 (tabbar-set-template tabset nil)
420 (set tabset (if append
421 (append tabs (list tab))
422 (cons tab tabs)))))))
423
424(defun tabbar-delete-tab (tab)
425 "Remove TAB from its TABSET."
426 (let* ((tabset (tabbar-tab-tabset tab))
427 (tabs (tabbar-tabs tabset)))
428 (tabbar-set-template tabset nil)
429 (when (eq tab (tabbar-selected-tab tabset))
430 (tabbar-select-tab (car (or (cdr (memq tab tabs)) (last tabs)))
431 tabset))
432 (set tabset (delq tab tabs))))
433
434(defun tabbar-scroll (tabset count)
435 "Scroll the TABSET's view of COUNT tabs.
436If COUNT is positive move the view on right. If COUNT is negative,
437move the view on left."
438 (let ((start (min (max 0 (+ (tabbar-start tabset) count))
439 (1- (length (tabbar-tabs tabset))))))
440 (when (/= start (tabbar-start tabset))
441 (tabbar-set-template tabset nil)
442 (put tabset 'start start))))
443
444(defun tabbar-tab-next (tabset tab &optional before)
445 "Search in TABSET for the tab after TAB.
446If optional argument BEFORE is non-nil, search for the tab before
447TAB. Return the tab found, or nil otherwise."
448 (let* (last (tabs (tabbar-tabs tabset)))
449 (while (and tabs (not (eq tab (car tabs))))
450 (setq last (car tabs)
451 tabs (cdr tabs)))
452 (and tabs (if before last (nth 1 tabs)))))
453
454(defun tabbar-current-tabset (&optional update)
455 "Return the current tab set, that will be displayed on the tab bar.
456If optional argument UPDATE is non-nil, call the user defined function
457`tabbar-current-tabset-function' to obtain it. Otherwise return the
458current cached copy."
459 (when (and update tabbar-current-tabset-function)
460 (setq tabbar-current-tabset
461 (funcall tabbar-current-tabset-function))
462 (or tabbar-last-selected-tab
463 (setq tabbar-last-selected-tab
464 (tabbar-selected-tab tabbar-current-tabset))))
465 tabbar-current-tabset)
466
467(defun tabbar-get-tabsets-tabset ()
468 "Return the tab set of selected tabs in existing tab sets."
469 (let ((tabsets-tabset
470 (or (tabbar-get-tabset tabbar-tabsets-tabset-name)
471 (tabbar-make-tabset tabbar-tabsets-tabset-name))))
472 (set tabsets-tabset
473 (delq t
474 (tabbar-map-tabsets
475 #'(lambda (tabset)
476 (or (eq tabset tabsets-tabset)
477 (tabbar-selected-tab tabset))))))
478 (tabbar-scroll tabsets-tabset 0)
479 (tabbar-set-template tabsets-tabset nil)
480 tabsets-tabset))
481
482;;; Buttons and separators
483;;
484(defun tabbar-find-image (specs)
485 "Find an image, choosing one of a list of image specifications.
486SPECS is a list of image specifications. See also `find-image'."
487 (when (display-images-p)
488 (condition-case nil
489 (find-image specs)
490 (error nil))))
491
492(defconst tabbar-separator-widget
493 '(cons (string)
494 (repeat :tag "Image"
495 :extra-offset 2
496 (restricted-sexp :tag "Spec"
497 :match-alternatives (listp))))
498 "Widget for editing a tab bar separator.
499A separator is specified as a pair (STRING . IMAGE) where STRING is a
500string value, and IMAGE a list of image specifications.
501If IMAGE is non-nil, try to use that image, else use STRING.
502The value (\"\") hide separators.")
503
504(defun tabbar-setup-separator (variable value)
505 "Set VARIABLE with specification of tab separator in VALUE.
506Initialize `VARIABLE-value' with the template element to use in header
507line, to display a separator on the tab bar."
508 (let ((text (intern (format "%s-value" variable)))
509 (image (tabbar-find-image (cdr value))))
510 (set text (propertize (if image " " (car value))
511 'face 'tabbar-separator-face
512 'display image))
513 (custom-set-default variable value)
514 ))
515
516(defvar tabbar-separator-value nil
517 "Text of the separator used between tabs.")
518
519(defcustom tabbar-separator (list " ")
520 "Separator used between tabs.
521See the variable `tabbar-separator-widget' for details."
522 :group 'tabbar
523 :type tabbar-separator-widget
524 :set 'tabbar-setup-separator)
525
526(defconst tabbar-button-widget
527 '(cons
528 (cons :tag "Enabled"
529 (string)
530 (repeat :tag "Image"
531 :extra-offset 2
532 (restricted-sexp :tag "Spec"
533 :match-alternatives (listp))))
534 (cons :tag "Disabled"
535 (string)
536 (repeat :tag "Image"
537 :extra-offset 2
538 (restricted-sexp :tag "Spec"
539 :match-alternatives (listp))))
540 )
541 "Widget for editing a tab bar button.
542A button is specified as a pair (ENABLED-BUTTON . DISABLED-BUTTON),
543where ENABLED-BUTTON and DISABLED-BUTTON specify the value used when
544the button is respectively enabled and disabled. Each button value is
545a pair (STRING . IMAGE) where STRING is a string value, and IMAGE a
546list of image specifications.
547If IMAGE is non-nil, try to use that image, else use STRING.")
548
549(defun tabbar-setup-button (variable value)
550 "Set VARIABLE with the button specification in VALUE.
551Initialize `VARIABLE-enable' and `VARIABLE-disable' with the template
552elements to use in the header line, to respectively display an enabled
553and a disabled button on the tab bar.
554The variable `VARIABLE-keymap' must be set with the keymap used for the
555enabled button.
556The function `VARIABLE-help' must be defined to return the `help-echo'
557string shown when the mouse is on the button."
558 (let ((enabled (intern (format "%s-enabled" variable)))
559 (disabled (intern (format "%s-disabled" variable)))
560 (keymap (intern (format "%s-keymap" variable)))
561 (help (intern (format "%s-help" variable)))
562 (image-en (tabbar-find-image (cdar value)))
563 (image-di (tabbar-find-image (cddr value))))
564 (set enabled (propertize (if image-en " " (caar value))
565 'display image-en
566 'face 'tabbar-button-face
567 'local-map (symbol-value keymap)
568 'help-echo help))
569 (set disabled (propertize (if image-di " " (cadr value))
570 'display image-di
571 'face 'tabbar-button-face))
572 (custom-set-default variable value)
573 ))
574
575(defun tabbar-make-button-keymap (callback)
576 "Return a button keymap that call CALLBACK on mouse events.
577CALLBACK is passed the received mouse event."
578 (let ((keymap (make-sparse-keymap)))
579 ;; Pass mouse-1, mouse-2 and mouse-3 events to CALLBACK.
580 (define-key keymap [header-line down-mouse-1] 'ignore)
581 (define-key keymap [header-line mouse-1] callback)
582 (define-key keymap [header-line down-mouse-2] 'ignore)
583 (define-key keymap [header-line mouse-2] callback)
584 (define-key keymap [header-line down-mouse-3] 'ignore)
585 (define-key keymap [header-line mouse-3] callback)
586 keymap))
587
588(defvar tabbar-home-button-enabled nil
589 "Text of the enabled home button.")
590
591(defvar tabbar-home-button-disabled nil
592 "Text of the disabled home button.")
593
594(defconst tabbar-home-button-keymap
595 (tabbar-make-button-keymap 'tabbar-home-button-callback)
596 "Keymap of the home button.")
597
598(defun tabbar-home-button-callback (event)
599 "Handle a mouse EVENT on the home button.
600Call `tabbar-home-function'."
601 (interactive "e")
602 (when tabbar-home-function
603 (save-selected-window
604 (select-window (posn-window (event-start event)))
605 (funcall tabbar-home-function event)
606 (force-mode-line-update)
607 (sit-for 0)
608 )))
609
610(defun tabbar-home-button-help (window object position)
611 "Return a help string or nil for none, for the home button.
612Call `tabbar-home-help-function'.
613Arguments WINDOW, OBJECT and POSITION, are not used."
614 (when tabbar-home-help-function
615 (funcall tabbar-home-help-function)))
616
617(defconst tabbar-home-button-enabled-image
618 '((:type pbm :ascent center :data "\
619P2
62010 10
621255
622184 184 184 184 0 184 184 184 184 184 184 184 184 0 0 0 184 184 184 184
623184 184 0 0 0 0 0 184 184 184 184 0 0 0 0 0 0 0 184 184 184 184 255 0 0
6240 255 255 255 184 184 0 0 0 0 0 0 0 184 184 184 184 0 0 0 0 0 255 255 184
625184 184 184 0 0 0 255 255 184 184 184 184 184 184 0 255 255 184 184 184
626184 184 184 184 184 255 184 184 184 184
627"))
628 "Default image for the enabled home button.")
629
630(defconst tabbar-home-button-disabled-image
631 '((:type pbm :ascent center :data "\
632P2
63310 10
634255
635184 184 184 184 120 184 184 184 184 184 184 184 184 120 120 120 184 184
636184 184 184 184 120 184 184 184 120 184 184 184 184 120 120 160 184 160
637120 120 184 184 184 184 255 120 184 120 255 255 255 184 184 120 120 160
638184 160 120 120 184 184 184 184 120 184 184 184 120 255 255 184 184 184
639184 120 120 120 255 255 184 184 184 184 184 184 120 255 255 184 184 184
640184 184 184 184 184 255 184 184 184 184
641"))
642 "Default image for the disabled home button.")
643
644(defcustom tabbar-home-button
645 (cons (cons "[o]" tabbar-home-button-enabled-image)
646 (cons "[x]" tabbar-home-button-disabled-image))
647 "The home button.
648See the variable `tabbar-button-widget' for details."
649 :group 'tabbar
650 :type tabbar-button-widget
651 :set 'tabbar-setup-button)
652
653(defvar tabbar-scroll-left-button-enabled nil
654 "Text of the enabled scroll left button.")
655
656(defvar tabbar-scroll-left-button-disabled nil
657 "Text of the disabled scroll left button.")
658
659(defconst tabbar-scroll-left-button-keymap
660 (tabbar-make-button-keymap 'tabbar-scroll-left-button-callback)
661 "Keymap of the scroll left button.")
662
663(defun tabbar-scroll-left-button-callback (event)
664 "Handle a mouse EVENT on the scroll left button.
665Call `tabbar-scroll-left-function'."
666 (interactive "e")
667 (when tabbar-scroll-left-function
668 (save-selected-window
669 (select-window (posn-window (event-start event)))
670 (funcall tabbar-scroll-left-function event)
671 (force-mode-line-update)
672 (sit-for 0)
673 )))
674
675(defun tabbar-scroll-left-button-help (window object position)
676 "Return a help string or nil for none, for the scroll left button.
677Call `tabbar-scroll-left-help-function'.
678Arguments WINDOW, OBJECT and POSITION, are not used."
679 (when tabbar-scroll-left-help-function
680 (funcall tabbar-scroll-left-help-function)))
681
682(defconst tabbar-scroll-left-button-enabled-image
683 '((:type pbm :ascent center :data "\
684P2
6858 10
686255
687184 184 184 184 184 184 184 184 184 184 184 184 184 0 184 184 184 184 184
688184 0 0 255 184 184 184 184 0 0 0 255 184 184 184 0 0 0 0 255 184 184 184
689184 0 0 0 255 184 184 184 184 184 0 0 255 184 184 184 184 184 184 0 255
690184 184 184 184 184 184 184 255 184 184 184 184 184 184 184 184 184
691"))
692 "Default image for the enabled scroll left button.")
693
694(defconst tabbar-scroll-left-button-disabled-image
695 '((:type pbm :ascent center :data "\
696P2
6978 10
698255
699184 184 184 184 184 184 184 184 184 184 184 184 184 120 184 184 184 184
700184 184 120 120 255 184 184 184 184 120 184 120 255 184 184 184 120 184
701184 120 255 184 184 184 184 120 184 120 255 184 184 184 184 184 120 120
702255 184 184 184 184 184 184 120 255 184 184 184 184 184 184 184 255 184
703184 184 184 184 184 184 184 184
704"))
705 "Default image for the disabled scroll left button.")
706
707(defcustom tabbar-scroll-left-button
708 (cons (cons " <" tabbar-scroll-left-button-enabled-image)
709 (cons " =" tabbar-scroll-left-button-disabled-image))
710 "The scroll left button.
711See the variable `tabbar-button-widget' for details."
712 :group 'tabbar
713 :type tabbar-button-widget
714 :set 'tabbar-setup-button)
715
716(defvar tabbar-scroll-right-button-enabled nil
717 "Text of the enabled scroll right button.")
718
719(defvar tabbar-scroll-right-button-disabled nil
720 "Text of the disabled scroll right button.")
721
722(defconst tabbar-scroll-right-button-keymap
723 (tabbar-make-button-keymap 'tabbar-scroll-right-button-callback)
724 "Keymap of the scroll right button.")
725
726(defun tabbar-scroll-right-button-callback (event)
727 "Handle a mouse EVENT on the scroll right button.
728Call `tabbar-scroll-right-function'."
729 (interactive "e")
730 (when tabbar-scroll-right-function
731 (save-selected-window
732 (select-window (posn-window (event-start event)))
733 (funcall tabbar-scroll-right-function event)
734 (force-mode-line-update)
735 (sit-for 0)
736 )))
737
738(defun tabbar-scroll-right-button-help (window object position)
739 "Return a help string or nil for none, for the scroll right button.
740Call `tabbar-scroll-right-help-function'.
741Arguments WINDOW, OBJECT and POSITION, are not used."
742 (when tabbar-scroll-right-help-function
743 (funcall tabbar-scroll-right-help-function)))
744
745(defconst tabbar-scroll-right-button-enabled-image
746 '((:type pbm :ascent center :data "\
747P2
7488 10
749255
750184 184 184 184 184 184 184 184 184 0 184 184 184 184 184 184 184 0 0 184
751184 184 184 184 184 0 0 0 184 184 184 184 184 0 0 0 0 184 184 184 184 0
7520 0 255 255 184 184 184 0 0 255 255 184 184 184 184 0 255 255 184 184 184
753184 184 184 255 184 184 184 184 184 184 184 184 184 184 184 184 184
754"))
755 "Default image for the enabled scroll right button.")
756
757(defconst tabbar-scroll-right-button-disabled-image
758 '((:type pbm :ascent center :data "\
759P2
7608 10
761255
762184 184 184 184 184 184 184 184 184 120 184 184 184 184 184 184 184 120
763120 184 184 184 184 184 184 120 184 120 184 184 184 184 184 120 184 184
764120 184 184 184 184 120 184 120 255 255 184 184 184 120 120 255 255 184
765184 184 184 120 255 255 184 184 184 184 184 184 255 184 184 184 184 184
766184 184 184 184 184 184 184 184
767"))
768 "Default image for the disabled scroll right button.")
769
770(defcustom tabbar-scroll-right-button
771 (cons (cons " >" tabbar-scroll-right-button-enabled-image)
772 (cons " =" tabbar-scroll-right-button-disabled-image))
773 "The scroll right button.
774See the variable `tabbar-button-widget' for details."
775 :group 'tabbar
776 :type tabbar-button-widget
777 :set 'tabbar-setup-button)
778
779;;; Faces
780;;
781(defface tabbar-default-face
782 '(
783 (t
784 (:inherit variable-pitch
785 :height 0.8
786 :foreground "gray60"
787 :background "gray72"
788 )
789 )
790 )
791 "Default face used in the tab bar."
792 :group 'tabbar)
793
794(defface tabbar-unselected-face
795 '(
796 (t
797 (:inherit tabbar-default-face
798 :box (:line-width 2 :color "white" :style pressed-button)
799 )
800 )
801 )
802 "Face used for uselected tabs."
803 :group 'tabbar)
804
805(defface tabbar-selected-face
806 '(
807 (t
808 (:inherit tabbar-default-face
809 :box (:line-width 2 :color "white" :style released-button)
810 :foreground "blue"
811 )
812 )
813 )
814 "Face used for the selected tab."
815 :group 'tabbar)
816
817(defface tabbar-separator-face
818 '(
819 (t
820 (:inherit tabbar-default-face
821 :height 0.2
822 )
823 )
824 )
825 "Face used for the select mode button."
826 :group 'tabbar)
827
828(defface tabbar-button-face
829 '(
830 (t
831 (:inherit tabbar-default-face
832 :box (:line-width 2 :color "white" :style released-button)
833 :foreground "dark red"
834 )
835 )
836 )
837 "Face used for the select mode button."
838 :group 'tabbar)
839
840;;; Wrappers
841;;
842(defun tabbar-scroll-left (event)
843 "On mouse EVENT, scroll current tab set on left."
844 (when (eq (event-basic-type event) 'mouse-1)
845 (tabbar-scroll (tabbar-current-tabset) -1)
846 ))
847
848(defun tabbar-scroll-left-help ()
849 "Return the help string shown when mouse is onto the scroll left button."
850 "mouse-1: scroll tabs left.")
851
852(defun tabbar-scroll-right (event)
853 "On mouse EVENT, scroll current tab set on right."
854 (when (eq (event-basic-type event) 'mouse-1)
855 (tabbar-scroll (tabbar-current-tabset) 1)
856 ))
857
858(defun tabbar-scroll-right-help ()
859 "Return the help string shown when mouse is onto the scroll right button."
860 "mouse-1: scroll tabs right.")
861
862 ;; These functions can be called at compilation time.
863(eval-and-compile
864
865 (defun tabbar-make-select-tab-command (tab)
866 "Return a command to handle TAB selection.
867That command calls `tabbar-select-tab-function' with the received
868mouse event and TAB."
869 (let ((event (make-symbol "event")))
870 `(lambda (,event)
871 (interactive "e")
872 (setq tabbar-last-selected-tab ,tab)
873 (when tabbar-select-tab-function
874 (select-window (posn-window (event-start ,event)))
875 (funcall tabbar-select-tab-function ,event ,tab)
876 (force-mode-line-update)
877 (sit-for 0)))))
878
879 (defun tabbar-make-help-on-tab-function (tab)
880 "Return a function that return a help string on TAB.
881That command calls `tabbar-help-on-tab-function' with TAB."
882 (let ((window (make-symbol "window"))
883 (object (make-symbol "object"))
884 (position (make-symbol "position"))
885 )
886 `(lambda (,window ,object ,position)
887 (when tabbar-help-on-tab-function
888 (funcall tabbar-help-on-tab-function ,tab)))))
889
890 )
891
892(defun tabbar-line-element (tab)
893 "Return an `header-line-format' template element from TAB.
894Call `tabbar-tab-label-function' to obtain a label for TAB."
895 (let* ((keymap (make-sparse-keymap))
896 (qtab (list 'quote tab))
897 (select (tabbar-make-select-tab-command qtab))
898 (help (tabbar-make-help-on-tab-function qtab))
899 (label (if tabbar-tab-label-function
900 (funcall tabbar-tab-label-function tab)
901 tab)))
902 ;; Call `tabbar-select-tab-function' on mouse events.
903 (define-key keymap [header-line down-mouse-1] 'ignore)
904 (define-key keymap [header-line mouse-1] select)
905 (define-key keymap [header-line down-mouse-2] 'ignore)
906 (define-key keymap [header-line mouse-2] select)
907 (define-key keymap [header-line down-mouse-3] 'ignore)
908 (define-key keymap [header-line mouse-3] select)
909 ;; Return the tab followed by a separator.
910 (list (propertize label 'local-map keymap 'help-echo help
911 'face (if (tabbar-selected-p
912 tab(tabbar-current-tabset))
913 'tabbar-selected-face
914 'tabbar-unselected-face))
915 tabbar-separator-value)))
916
917(defun tabbar-line ()
918 "Return the header line templates that represent the tab bar.
919Call `tabbar-current-tabset-function' to obtain the current tab set to
920display. Then call `tabbar-line-element' on each tab in current tab
921set's view to build a list of template elements for
922`header-line-format'."
923 (if (run-hook-with-args-until-success 'tabbar-inhibit-functions)
924 (setq header-line-format nil)
925 (let ((tabset (tabbar-current-tabset t))
926 (padcolor (face-background 'tabbar-default-face)))
927 (when tabset
928 (list (format "%s%s%s"
929 (if tabbar-home-function
930 tabbar-home-button-enabled
931 tabbar-home-button-disabled)
932 (if (> (tabbar-start tabset) 0)
933 tabbar-scroll-left-button-enabled
934 tabbar-scroll-left-button-disabled)
935 (if (< (tabbar-start tabset)
936 (1- (length (tabbar-tabs tabset))))
937 tabbar-scroll-right-button-enabled
938 tabbar-scroll-right-button-disabled))
939 tabbar-separator-value
940 (or
941 ;; If a cached template exists, use it.
942 (tabbar-template tabset)
943 ;; Otherwise use a refeshed value.
944 (tabbar-set-template tabset
945 (mapcar 'tabbar-line-element
946 (tabbar-view tabset))))
947 (propertize "%-" 'face (list :background padcolor
948 :foreground padcolor))))
949 )))
950
951;;; Cyclic navigation through tabs
952;;
953(defsubst tabbar-make-mouse-event (&optional type)
954 "Return a basic mouse event.
955Optional argument TYPE is a mouse event type. That is one of the
956symbols `mouse-1', `mouse-2' or `mouse-3'. The default is `mouse-1'."
957 (list (or (memq type '(mouse-2 mouse-3)) 'mouse-1)
958 (or (event-start nil) ;; Emacs 21.4
959 (list (selected-window) (point) '(0 . 0) 0))))
960
961(defmacro tabbar-click-on-tab (tab &optional type)
962 "Simulate a mouse click event on tab TAB.
963Optional argument TYPE is a mouse event type (see the function
964`tabbar-make-mouse-event' for details)."
965 `(,(tabbar-make-select-tab-command tab)
966 (tabbar-make-mouse-event ,type)))
967
968(defun tabbar-cycle (&optional backward)
969 "Cycle to the next available tab.
970If optional argument BACKWARD is non-nil, cycle to the previous tab
971instead.
972The scope of the cyclic navigation through tabs is specified by the
973option `tabbar-cycling-scope'."
974 (let ((tabset (tabbar-current-tabset t))
975 selected tab)
976 (when tabset
977 (setq selected (tabbar-selected-tab tabset))
978 (cond
979 ;; Cycle through visible tabs only.
980 ((eq tabbar-cycling-scope 'tabs)
981 (setq tab (tabbar-tab-next tabset selected backward))
982 ;; When there is no tab after/before the selected one, cycle
983 ;; to the first/last visible tab.
984 (unless tab
985 (setq tabset (tabbar-tabs tabset)
986 tab (car (if backward (last tabset) tabset))))
987 )
988 ;; Cycle through tab groups only.
989 ((eq tabbar-cycling-scope 'groups)
990 (setq tabset (tabbar-get-tabsets-tabset)
991 tab (tabbar-tab-next tabset selected backward))
992 ;; When there is no group after/before the selected one, cycle
993 ;; to the first/last available group.
994 (unless tab
995 (setq tabset (tabbar-tabs tabset)
996 tab (car (if backward (last tabset) tabset))))
997 )
998 (t
999 ;; Cycle through visible tabs then tab groups.
1000 (setq tab (tabbar-tab-next tabset selected backward))
1001 ;; When there is no visible tab after/before the selected one,
1002 ;; cycle to the next/previous available group.
1003 (unless tab
1004 (setq tabset (tabbar-get-tabsets-tabset)
1005 tab (tabbar-tab-next tabset selected backward))
1006 ;; When there is no next/previous group, cycle to the
1007 ;; first/last available group.
1008 (unless tab
1009 (setq tabset (tabbar-tabs tabset)
1010 tab (car (if backward (last tabset) tabset))))
1011 ;; Select the first/last visible tab of the new group.
1012 (setq tabset (tabbar-tabs (tabbar-tab-tabset tab))
1013 tab (car (if backward (last tabset) tabset))))
1014 ))
1015 (tabbar-click-on-tab tab))))
1016
1017;;;###autoload
1018(defun tabbar-backward ()
1019 "Select the previous available tab.
1020Depend on the setting of the option `tabbar-cycling-scope'."
1021 (interactive)
1022 (tabbar-cycle t))
1023
1024;;;###autoload
1025(defun tabbar-forward ()
1026 "Select the next available tab.
1027Depend on the setting of the option `tabbar-cycling-scope'."
1028 (interactive)
1029 (tabbar-cycle))
1030
1031;;;###autoload
1032(defun tabbar-backward-group ()
1033 "Go to selected tab in the previous available group."
1034 (interactive)
1035 (let ((tabbar-cycling-scope 'groups))
1036 (tabbar-cycle t)))
1037
1038;;;###autoload
1039(defun tabbar-forward-group ()
1040 "Go to selected tab in the next available group."
1041 (interactive)
1042 (let ((tabbar-cycling-scope 'groups))
1043 (tabbar-cycle)))
1044
1045;;;###autoload
1046(defun tabbar-backward-tab ()
1047 "Select the previous visible tab."
1048 (interactive)
1049 (let ((tabbar-cycling-scope 'tabs))
1050 (tabbar-cycle t)))
1051
1052;;;###autoload
1053(defun tabbar-forward-tab ()
1054 "Select the next visible tab."
1055 (interactive)
1056 (let ((tabbar-cycling-scope 'tabs))
1057 (tabbar-cycle)))
1058
1059;;; Minor modes
1060;;
1061(defvar tabbar-old-global-hlf nil
1062 "Global value of the header line when entering tab bar mode.")
1063
1064(defconst tabbar-header-line-format '(:eval (tabbar-line))
1065 "The tab bar header line format.")
1066
1067;;;###autoload
1068(define-minor-mode tabbar-mode
1069 "Toggle display of a tab bar in the header line.
1070With prefix argument ARG, turn on if positive, otherwise off.
1071Returns non-nil if the new state is enabled."
1072 :global t
1073 :group 'tabbar
1074 (if tabbar-mode
1075;;; ON
1076 (unless (eq header-line-format tabbar-header-line-format)
1077 ;; Save current default value of `header-line-format'.
1078 (setq tabbar-old-global-hlf (default-value 'header-line-format))
1079 (add-hook 'kill-buffer-hook 'tabbar-buffer-kill-buffer-hook)
1080 (tabbar-init-tabsets-store)
1081 (setq-default header-line-format tabbar-header-line-format))
1082;;; OFF
1083 ;; Restore previous `header-line-format', if it has not changed.
1084 (when (eq (default-value 'header-line-format)
1085 tabbar-header-line-format)
1086 (setq-default header-line-format tabbar-old-global-hlf))
1087 (remove-hook 'kill-buffer-hook 'tabbar-buffer-kill-buffer-hook)
1088 (tabbar-free-tabsets-store)
1089 ;; Turn off locals tab bar mode
1090 (mapc #'(lambda (b)
1091 (with-current-buffer b
1092 (tabbar-local-mode -1)))
1093 (buffer-list))
1094 ))
1095
1096(defvar tabbar-old-local-hlf nil
1097 "Local value of the header line when entering tab bar local mode.")
1098(make-variable-buffer-local 'tabbar-old-local-hlf)
1099
1100;;;###autoload
1101(define-minor-mode tabbar-local-mode
1102 "Toggle local display of the tab bar.
1103With prefix argument ARG, turn on if positive, otherwise off.
1104Returns non-nil if the new state is enabled.
1105When on and tab bar global mode is on, if a buffer local value of
1106`header-line-format' exists, it is saved, then the local header line
1107is killed to show the tab bar. When off, the saved local value of the
1108header line is restored, hiding the tab bar."
1109 :global nil
1110 :group 'tabbar
1111;;; ON
1112 (if tabbar-local-mode
1113 (if (and tabbar-mode (local-variable-p 'header-line-format)
1114 (not (local-variable-p 'tabbar-old-local-hlf)))
1115 (progn
1116 (setq tabbar-old-local-hlf header-line-format)
1117 (kill-local-variable 'header-line-format))
1118 (setq tabbar-local-mode nil))
1119;;; OFF
1120 (when (local-variable-p 'tabbar-old-local-hlf)
1121 (setq header-line-format tabbar-old-local-hlf)
1122 (kill-local-variable 'tabbar-old-local-hlf))
1123 ))
1124
1125;;; Hooks
1126;;
1127(defun tabbar-default-inhibit-function ()
1128 "Inhibit display of the tab bar in specified windows.
1129That is dedicated windows, and `checkdoc' status windows."
1130 (or (window-dedicated-p (selected-window))
1131 (member (buffer-name)
1132 '(" *Checkdoc Status*"))))
1133
1134(defun tabbar-buffer-kill-buffer-hook ()
1135 "Hook run just before actually killing a buffer.
1136In tab bar mode, try to switch to a buffer in the current tab bar,
1137after the current buffer has been killed. Try first the buffer in tab
1138after the current one, then the buffer in tab before. On success, put
1139the sibling buffer in front of the buffer list, so it will be selected
1140first."
1141 (and tabbar-mode
1142 (eq tabbar-current-tabset-function 'tabbar-buffer-tabs)
1143 (eq (current-buffer) (window-buffer (selected-window)))
1144 (let ((bl (tabbar-tab-values (tabbar-current-tabset)))
1145 (bn (buffer-name))
1146 found sibling)
1147 (while (and bl (not found))
1148 (if (equal bn (car bl))
1149 (setq found t)
1150 (setq sibling (car bl)))
1151 (setq bl (cdr bl)))
1152 (when (setq sibling (or (car bl) sibling))
1153 ;; Move sibling buffer in front of the buffer list.
1154 (save-current-buffer
1155 (switch-to-buffer sibling))))))
1156
1157;;; Buffer tabs
1158;;
1159(defcustom tabbar-buffer-list-function
1160 'tabbar-buffer-list
1161 "*Function that returns the list of buffers to show in tabs.
1162That function is called with no arguments and must return a list of
1163buffers."
1164 :group 'tabbar
1165 :type 'function)
1166
1167(defcustom tabbar-buffer-groups-function
1168 'tabbar-buffer-groups
1169 "*Function that gives the group names a buffer belongs to.
1170That function is passed a buffer and must return a list of group
1171names, or nil if the buffer has no group.
1172Notice that it is better that a buffer belongs to one group."
1173 :group 'tabbar
1174 :type 'function)
1175
1176(defun tabbar-buffer-list ()
1177 "Return the list of buffers to show in tabs.
1178Exclude buffers whose name starts with a space, when they are not
1179visiting a file."
1180 (delq t
1181 (mapcar #'(lambda (b)
1182 (cond
1183 ((buffer-file-name b) b)
1184 ((char-equal ?\ (aref (buffer-name b) 0)))
1185 (b)))
1186 (buffer-list))))
1187
1188(defun tabbar-buffer-groups (buffer)
1189 "Return the list of group names BUFFER belongs to.
1190Return only one group for each buffer."
1191 (with-current-buffer (get-buffer buffer)
1192 (cond
1193 ((or (get-buffer-process (current-buffer))
1194 (memq major-mode
1195 '(comint-mode compilation-mode)))
1196 '("Process")
1197 )
1198 ((member (buffer-name)
1199 '("*scratch*" "*Messages*"))
1200 '("Common")
1201 )
1202 ((eq major-mode 'dired-mode)
1203 '("Dired")
1204 )
1205 ((memq major-mode
1206 '(help-mode apropos-mode Info-mode Man-mode))
1207 '("Help")
1208 )
1209 ((memq major-mode
1210 '(rmail-mode
1211 rmail-edit-mode vm-summary-mode vm-mode mail-mode
1212 mh-letter-mode mh-show-mode mh-folder-mode
1213 gnus-summary-mode message-mode gnus-group-mode
1214 gnus-article-mode score-mode gnus-browse-killed-mode))
1215 '("Mail")
1216 )
1217 (t
1218 (list
1219 (if (and (stringp mode-name) (string-match "[^ ]" mode-name))
1220 mode-name
1221 (symbol-name major-mode)))
1222 )
1223 )))
1224
1225;;; Group buffers in tab sets.
1226;;
1227(defun tabbar-buffer-cleanup-tabsets (buffers)
1228 "Remove obsolete tabs from existing tab sets.
1229That is tabs whose value is a killed buffer or a buffer not in
1230BUFFERS. Delete tab sets that no more contain tabs."
1231 (mapc 'tabbar-delete-tabset
1232 (tabbar-map-tabsets
1233 #'(lambda (tabset)
1234 (mapc #'(lambda (tab)
1235 (let ((b (get-buffer (tabbar-tab-value tab))))
1236 (unless (and b (memq b buffers))
1237 (tabbar-delete-tab tab))))
1238 (tabbar-tabs tabset))
1239 (unless (tabbar-tabs tabset)
1240 tabset)))))
1241
1242(defun tabbar-buffer-update-groups ()
1243 "Update group of buffers.
1244Return the the first group where the current buffer is."
1245 ;; Ensure that the current buffer will always have a tab!
1246 (let ((buffers (cons (current-buffer)
1247 (funcall tabbar-buffer-list-function)))
1248 current-group)
1249 (mapc
1250 #'(lambda (buffer)
1251 (let* ((name (buffer-name buffer))
1252 (groups (funcall tabbar-buffer-groups-function name)))
1253 (when (eq buffer (current-buffer))
1254 (setq current-group (car groups)))
1255 (mapc #'(lambda (group)
1256 (let ((tabset (tabbar-get-tabset group)))
1257 (if tabset
1258 (tabbar-add-tab tabset name t)
1259 (tabbar-make-tabset group name))))
1260 groups)))
1261 buffers)
1262 (tabbar-buffer-cleanup-tabsets buffers)
1263 current-group))
1264
1265;;; Tab bar callbacks
1266;;
1267(defvar tabbar-buffer-group-mode nil
1268 "Display tabs for group of buffers, when non-nil.")
1269(make-variable-buffer-local 'tabbar-buffer-group-mode)
1270
1271(defun tabbar-buffer-tabs ()
1272 "Return the buffers to display on the tab bar, in a tab set."
1273 (let ((group (tabbar-buffer-update-groups))
1274 (buffer (buffer-name))
1275 tabset curtab)
1276 (if tabbar-buffer-group-mode
1277 (progn
1278 (setq tabset (tabbar-get-tabsets-tabset)
1279 curtab (tabbar-selected-tab (tabbar-current-tabset)))
1280 (unless (and (equal buffer (tabbar-tab-value curtab))
1281 (tabbar-select-tab curtab tabset))
1282 (tabbar-select-tab-value buffer tabset)))
1283 (setq tabset (tabbar-tab-tabset tabbar-last-selected-tab))
1284 (unless (and tabset (tabbar-get-tab buffer tabset))
1285 (setq tabset (tabbar-get-tabset group)))
1286 (tabbar-select-tab-value buffer tabset))
1287 tabset))
1288
1289(defun tabbar-buffer-tab-label (tab)
1290 "Return the label to display TAB.
1291Must be a valid `header-line-format' template element."
1292 (if tabbar-buffer-group-mode
1293 (format "[%s]" (tabbar-tab-tabset tab))
1294 (format " %s " (tabbar-tab-value tab))))
1295
1296(defun tabbar-buffer-help-on-tab (tab)
1297 "Return the help string shown when mouse is onto TAB."
1298 (if tabbar-buffer-group-mode
1299 "mouse-1: switch to selected tab in group"
1300 "\
1301mouse-1: switch to buffer, \
1302mouse-2: pop to buffer, \
1303mouse-3: delete other windows"
1304 ))
1305
1306(defun tabbar-buffer-select-tab (event tab)
1307 "On mouse EVENT, select TAB."
1308 (let ((mouse-button (event-basic-type event))
1309 (buffer (tabbar-tab-value tab)))
1310 (cond
1311 ((eq mouse-button 'mouse-1)
1312 (switch-to-buffer buffer))
1313 ((eq mouse-button 'mouse-2)
1314 (pop-to-buffer buffer t))
1315 ((eq mouse-button 'mouse-3)
1316 (delete-other-windows)))
1317 ;; Disable group mode.
1318 (setq tabbar-buffer-group-mode nil)
1319 ))
1320
1321(defun tabbar-buffer-toggle-group-mode (event)
1322 "On mouse EVENT, toggle group mode.
1323When enabled, display tabs for group of buffers, instead of buffer
1324tabs."
1325 (setq tabbar-buffer-group-mode (not tabbar-buffer-group-mode)))
1326
1327(defun tabbar-buffer-toggle-group-mode-help ()
1328 "Return the help string shown when mouse is onto the toggle button."
1329 (if tabbar-buffer-group-mode
1330 "mouse-1: show buffers in selected group"
1331 "mouse-1: show groups of buffers"
1332 ))
1333
1334(provide 'tabbar)
1335
1336;;; tabbar.el ends here