Browser-ähnliche 'Tabs' für Emacs?

22

Ich möchte Tabs wie Firefox, aber für Emacs.

Ich habe folgendes gefunden: http://emacswiki.org/emacs/TabBarMode

Aber es wird nur zu jedem Puffer ( Fenster) hinzugefügt in der Emacs-Terminologie) wird jedoch nur eine Leiste in der die aktuell geöffneten Puffer angezeigt werden.

Ich möchte, dass ein Tab mehrere Puffer ( Fenster in der Emacs-Teminologie) enthält, die ich nach Wunsch aufteilen kann. Dh jeder Reiter sollte einem "Fensterzustand" entsprechen (im Sinne von window-state-get).

Ich hätte eine Registerkarte für meine Aufgaben, eine andere für Code, eine andere zum Lesen im Internet usw.

Ist das möglich? Kann die Tab-Leiste dafür angepasst werden?

[edit2]
Diese Frage hat mehr Aufmerksamkeit auf sich gezogen als ich erwartet hatte. Es sieht so aus, als gäbe es eine Lösung, die jedoch ein wenig Nachforschungen und Optimierungen erfordert. Während diese / nächste Woche ein bisschen beschäftigt für mich ist, werde ich die Antworten durchgehen und versuchen, etwas zu bauen, das funktioniert, und dann werde ich diese Frage bearbeiten, um meine Ergebnisse widerzuspiegeln. Bitte warten =)

[edit]
Ähnlich wie:
/programming/24157754/make-frames-in-emacs-gui-behaves-like-frames-in-terminal

Ich würde mich auch mit mehreren Frames in einer einzigen GUI-Sitzung begnügen.

Leo Ufimtsev
quelle
2
"Ich möchte, dass ein Tab mehrere Puffer enthält, die ich nach Belieben aufteilen kann." Meinen Sie mehrere Fenster ?
Malabarba,
1
Es ist eher so, als ob ich sehr dyanmische Tabs haben möchte. Ich würde sie erstellen und dann mit Fenstern füllen. Dh ich möchte, dass ein Tabulator ein Rahmen ist. Dann ein neuer Tab, ein neuer Frame. In jedem Tab / Frame konnte ich die gewünschten Fenster / (Puffer) öffnen. Ist das machbar? (Dh, keine fest codierten
Puffernamen
1
Es gibt eine Variable, die mit bestimmten Fenstern verknüpft ist, aber es ist ein oder zwei Monate her, dass ich einen Thread gesehen habe, der darüber gesprochen hat, und ich weiß nicht, wie er eigenhändig heißt. Möglicherweise möchten Sie ein System verwenden, das Frame-Bufs ähnelt, bei dem eine Liste die mit einem Frame verknüpften Puffer enthält und diese Liste in den Frame-Parameter aufgenommen wird. Sie können die mit einem bestimmten Fenster verknüpfte Variable verwenden und daraus eine Liste erstellen, Puffer zur Liste hinzufügen / daraus entfernen. Diese Liste ist eine Puffergruppe, die von der Registerkartenleiste verwendet wird. Das ist alles theoretisch, aber ich glaube, es würde funktionieren.
Gesetzesliste
1
Ich denke, Sie können sich beziehen auf: stackoverflow.com/questions/24157754/…, aber dieser Beitrag scheint keine solide Antwort zu haben: - /
Leo Ufimtsev
1
Ich würde empfehlen, einen Blick auf das elscreen-Paket zu werfen.
Blarghmatey

Antworten:

8

Puffer in Gruppen aufteilen

Dies ist mit der Tabbar möglich. Sie können Gruppenpuffern in Gruppen Regeln hinzufügen. Hier ist ein grundlegender Ausschnitt:

(defun tabbar-buffer-groups ()
  "Returns the list of group names the current buffer belongs to."
  (list
   (cond

    ;; ADD RULES TO SPLIT BUFFERS IN GROUPS HERE!

    ;; if buffer is not grouped by the rules you would add above 
    ;; put it in the "General" group:
    (t
       "General"
     ))))

Beispielregeln:

  1. Puffernamen auflisten:
    ((member (buffer-name)
             '("*scratch*" "*Messages*" "*Help*"))
     "Common" ;; this is a group name
     )
  1. In Bezug auf gemeinsame Puffer ziehe ich es vor, jeden Puffer, dessen Name mit einem Stern beginnt, in "Common" zu setzen. Dies ist ein Beispiel für das Erstellen eines Puffers für diese Regel:
    ((string-equal "*" (substring (buffer-name) 0 1))
     "Common"
     )
  1. Hier ist ein Beispiel für das Gruppieren von Puffern nach Hauptmodus:
    ((memq major-mode
           '(org-mode text-mode rst-mode))
     "Text"
     )
  1. Hier ist ein Beispiel für das Gruppieren von Puffern anhand des Modus, aus dem sie abgeleitet sind:
    ((or (get-buffer-process (current-buffer))
         ;; Check if the major mode derives from `comint-mode' or
         ;; `compilation-mode'.
         (tabbar-buffer-mode-derived-p
          major-mode '(comint-mode compilation-mode)))
     "Process"
     )
  1. Hier ist ein Beispiel für das Gruppieren von Registerkarten nach regulären Ausdrücken:
    ((string-match "^__" (buffer-name))
     "Templates"
     )
  1. Gruppenpuffer nach Hauptmodus:
    (if (and (stringp mode-name)
                  ;; Take care of preserving the match-data because this
                  ;; function is called when updating the header line.
                  (save-match-data (string-match "[^ ]" mode-name)))
             mode-name
           (symbol-name major-mode))

Sobald Sie die Regeln erstellt haben, können Sie auf der Tab-Leiste auf + oder - drücken, um die Gruppen umzuschalten, und auch auf ◀ und ▶, um zwischen den Puffern zu wechseln. Oder binden Sie einfach die folgenden Defuns:

tabbar-forward
tabbar-backward
tabbar-forward-group
tabbar-backward-group

und mit der Tastatur zwischen Registerkarten und Registerkartengruppen wechseln.

Persönlich gruppiere ich Registerkarten, damit ich sehe, was geöffnet ist, navigiere sie aber mit ido-switch-buffer.

Zwischen Regeln wechseln

Man kann auch verschiedene Sätze von Puffergruppierungsregeln definieren und zwischen diesen wechseln. Hier ist ein Beispiel für das Wechseln zwischen zwei Gruppen von Puffergruppierungsregeln:

;; tab-groups!
(setq tbbr-md "common")
(defun toggle-tabbar-mode ()
  "Toggles tabbar modes - all buffers vs. defined in the `tabbar-buffer-groups'."
  (interactive)
  (if (string= tbbr-md "groups")
      (progn ;; then
        (setq tabbar-buffer-groups-function 'tabbar-buffer-groups-common)
        (setq tbbr-md "common"))
    (progn ;; else
      (setq tabbar-buffer-groups-function 'tabbar-buffer-groups)
      (setq tbbr-md "groups"))))
;; by default - all tabs:
(setq tabbar-buffer-groups-function 'tabbar-buffer-groups-common)

Dies schaltet zwischen den Defuns tabbar-buffer-groups-commonund tabbar-buffer-groupsTab-Gruppierungen um.

Sortieren Sie die Registerkartenpuffer nach Namen

Ich finde es vorteilhaft, Tabbar-Puffer nach Namen zu sortieren. So bekommen Sie es:

(defun tabbar-add-tab (tabset object &optional append_ignored)
  "Add to TABSET a tab with value OBJECT if there isn't one there yet.
If the tab is added, it is added at the beginning of the tab list,
unless the optional argument APPEND is non-nil, in which case it is
added at the end."
  (let ((tabs (tabbar-tabs tabset)))
    (if (tabbar-get-tab object tabset)
        tabs
      (let ((tab (tabbar-make-tab object tabset)))
        (tabbar-set-template tabset nil)
        (set tabset (sort (cons tab tabs)
                          (lambda (a b) (string< (buffer-name (car a)) (buffer-name (car b))))))))))
Adobe
quelle
Vielen Dank für die ausführliche Antwort. Ich werde versuchen, das oben
Genannte
Das OP möchte jedoch nicht "eine Tab-Leiste pro Fenster", sondern eine Tab-Leiste pro Frame, und jede Registerkarte in der Tab-Leiste sollte eine "Fensterkonfiguration" (dh mehrere Fenster) anstelle eines Puffers darstellen, sodass das Gruppieren von Puffern nicht das Problem ist .
Stefan
6

ATTRIBUT: Die Gruppierung von Puffern auf Frame-Basis ist eine direkte Implementierung der von Alp Aker entwickelten / geschriebenen Konzepte und ausgewählten Codeteile in der Bibliothek frame-bufs: https://github.com/alpaker/Frame-Bufs

Im Folgenden finden Sie ein Beispiel für die tabbar.eldynamische Verwendung der Bibliothek und der Gruppierung von Registerkarten / Puffern pro Frame, indem entweder Registerkarten / Puffern hinzugefügt C-c C-aoder Registerkarten / Puffern entfernt werden C-c C-n. Es gibt nur zwei (2) Gruppen - die dem aktuellen Frame (dh "A") und NICHT dem aktuellen Frame (dh "N") zugeordnet sind. Die Gruppen sind rahmenlokal, was bedeutet, dass jeder Rahmen eine eigene Gruppierung haben kann. Die benutzerdefinierte Gruppierung kann mit zurückgesetzt werden C-c C-r. Wechseln zwischen assoziierten und nicht assoziierten Gruppen mit C-tab. Mit zum nächsten Tab / Puffer in der aktuellen Gruppe wechseln M-s-right. Mit zum vorherigen Tab / Puffer in der aktuellen Gruppe wechseln M-s-left.

Tabs / Puffer können mit my-add-bufferund programmgesteuert hinzugefügt oder entfernt werden my-remove-buffer. Ein Beispiel zum Öffnen bestimmter Puffer in ausgewählten Frames finden Sie in dem verwandten Thread mit dem Titel Abfangen einer Datei vor dem Öffnen und Entscheiden, welcher Frame geöffnet werden soll : /programming//a/18371427/2112489 Die Funktion my-add-buffermüsste an den entsprechenden Stellen des Codes in den obigen Link eingefügt werden, wenn ein Benutzer diese Funktion implementieren möchte.

Der Benutzer möchte möglicherweise einen Eintrag in einem benutzerdefinierten mode-line-formatFormat erstellen, in dem der Name der aktuellen Registerkartengruppe in der Moduszeile angezeigt wird, indem das folgende Snippet eingefügt wird: Eine (:eval (when tabbar-mode (format "%s" (tabbar-current-tabset t)))) detailliertere Anpassung der Moduszeile würde den Rahmen dieses Beispiels jedoch sprengen.

Die Funktion tabbar-add-tabwurde geändert, um die Registerkarten / Puffer zu alphabetisieren.

Die Funktion tabbar-line-tabwurde so geändert, dass je nach Situation vier (4) verschiedene Gesichter zur Verfügung stehen. Wenn die Registerkarte / der Puffer mit dem Frame verknüpft ist und ausgewählt ist, verwenden Sie tabbar-selected-associatedface. Wenn die Registerkarte / der Puffer mit dem Frame verknüpft und NICHT ausgewählt ist, verwenden Sie tabbar-unselected-associatedface. Wenn der Tabulator / Puffer NICHT mit dem Frame verknüpft ist und ausgewählt ist, verwenden Sie tabbar-selected-unassociatedface. Wenn der Tabulator / Puffer NICHT mit dem Frame verknüpft und NICHT ausgewählt ist, verwenden Sie tabbar-unselected-unassociatedface.

;; Download tabbar version 2.0.1 by David Ponce:
;;   https://marmalade-repo.org/packages/tabbar
;; or use package-install for marmalade repositories.

;; Place tabbar-2.0.1.el in the `load-path` -- it is okay to rename it to tabbar.el
;; or add the directory (where `tabbar.el` resides) to the `load-path`.
;; EXAMPLE:  (setq load-path (append '("/Users/HOME/.emacs.d/lisp/") load-path))

(require 'tabbar)

(setq tabbar-cycle-scope 'tabs)

(remove-hook 'kill-buffer-hook 'tabbar-buffer-track-killed)

(defun my-buffer-groups ()
  "Function that gives the group names the current buffer belongs to.
It must return a list of group names, or nil if the buffer has no
group.  Notice that it is better that a buffer belongs to one group."
  (list
    (cond
      ((memq (current-buffer) (my-buffer-list (selected-frame)))
        "A")
      (t
        "N"))))

(setq tabbar-buffer-groups-function 'my-buffer-groups) ;; 'tabbar-buffer-groups

;; redefine tabbar-add-tab so that it alphabetizes / sorts the tabs
(defun tabbar-add-tab (tabset object &optional append)
  "Add to TABSET a tab with value OBJECT if there isn't one there yet.
If the tab is added, it is added at the beginning of the tab list,
unless the optional argument APPEND is non-nil, in which case it is
added at the end."
  (let ((tabs (tabbar-tabs tabset)))
    (if (tabbar-get-tab object tabset)
        tabs
      (let* ((tab (tabbar-make-tab object tabset))
             (tentative-new-tabset
               (if append
                 (append tabs (list tab))
                 (cons tab tabs)))
             (new-tabset
               (sort
                  tentative-new-tabset
                  #'(lambda (e1 e2)
                     (string-lessp
                       (format "%s" (car e1)) (format "%s" (car e2)))))))
        (tabbar-set-template tabset nil)
        (set tabset new-tabset)))))

;; AUTHOR:  Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-buffer-list (frame)
  ;; Remove dead buffers.
  (set-frame-parameter frame 'frame-bufs-buffer-list
    (delq nil (mapcar #'(lambda (x) (if (buffer-live-p x) x))
      (frame-parameter frame 'frame-bufs-buffer-list))))
  ;; Return the associated-buffer list.
  (frame-parameter frame 'frame-bufs-buffer-list))

(defun my-kill-buffer-fn ()
"This function is attached to a buffer-local `kill-buffer-hook'."
  (let ((frame (selected-frame))
        (current-buffer (current-buffer)))
    (when (memq current-buffer (my-buffer-list frame))
      (my-remove-buffer current-buffer frame))))

;; AUTHOR:  Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-add-buffer (&optional buf frame)
"Add BUF to FRAME's associated-buffer list if not already present."
(interactive)
  (let* ((buf (if buf buf (current-buffer)))
         (frame (if frame frame (selected-frame)))
         (associated-bufs (frame-parameter frame 'frame-bufs-buffer-list)))
    (unless (bufferp buf)
      (signal 'wrong-type-argument (list 'bufferp buf)))
    (unless (memq buf associated-bufs)
      (set-frame-parameter frame 'frame-bufs-buffer-list (cons buf associated-bufs)))
    (with-current-buffer buf
      (add-hook 'kill-buffer-hook 'my-kill-buffer-fn 'append 'local))
    (when tabbar-mode (tabbar-display-update))))

;; AUTHOR:  Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-remove-buffer (&optional buf frame)
"Remove BUF from FRAME's associated-buffer list."
(interactive)
  (let ((buf (if buf buf (current-buffer)))
        (frame (if frame frame (selected-frame))))
    (set-frame-parameter frame 'frame-bufs-buffer-list
      (delq buf (frame-parameter frame 'frame-bufs-buffer-list)))
    (when tabbar-mode (tabbar-display-update))))

;; AUTHOR:  Alp Aker -- https://github.com/alpaker/Frame-Bufs
;; @lawlist extracted/revised the function(ality) from said library.
(defun my-buffer-list-reset ()
    "Wipe the entire slate clean for the selected frame."
  (interactive)
    (modify-frame-parameters (selected-frame) (list (cons 'frame-bufs-buffer-list nil)))
    (when tabbar-mode (tabbar-display-update)))

(defun my-switch-tab-group ()
"Switch between tab group `A` and `N`."
(interactive)
  (let ((current-group (format "%s" (tabbar-current-tabset t)))
        (tab-buffer-list (mapcar
            #'(lambda (b)
                (with-current-buffer b
                  (list (current-buffer)
                        (buffer-name)
                        (funcall tabbar-buffer-groups-function))))
                 (funcall tabbar-buffer-list-function))))
    (catch 'done
      (mapc
        #'(lambda (group)
            (when (not (equal current-group
                          (format "%s" (car (car (cdr (cdr group)))))))
              (throw 'done (switch-to-buffer (car (cdr group))))))
        tab-buffer-list))))

(defface tabbar-selected-associated
  '((t :background "black" :foreground "yellow" :box (:line-width 2 :color "yellow")))
  "Face used for the selected tab -- associated with the `frame-bufs-buffer-list`."
  :group 'tabbar)

(defface tabbar-unselected-associated
  '((t :background "black" :foreground "white" :box (:line-width 2 :color "white")))
  "Face used for unselected tabs  -- associated with the `frame-bufs-buffer-list`."
  :group 'tabbar)

(defface tabbar-selected-unassociated
  '((t :background "black" :foreground "white" :box (:line-width 2 :color "firebrick")))
  "Face used for the selected tab -- UNassociated with the `frame-bufs-buffer-list`."
  :group 'tabbar)

(defface tabbar-unselected-unassociated
  '((t :background "black" :foreground "white" :box (:line-width 2 :color "blue")))
  "Face used for unselected tabs -- UNassociated with the `frame-bufs-buffer-list`."
  :group 'tabbar)

(setq tabbar-background-color "black")

(defsubst tabbar-line-tab (tab)
  "Return the display representation of tab TAB.
That is, a propertized string used as an `header-line-format' template
element.
Call `tabbar-tab-label-function' to obtain a label for TAB."
  (concat
    (propertize
      (if tabbar-tab-label-function
          (funcall tabbar-tab-label-function tab)
        tab)
      'tabbar-tab tab
      'local-map (tabbar-make-tab-keymap tab)
      'help-echo 'tabbar-help-on-tab
      'mouse-face 'tabbar-highlight
      'face
        (cond
          ((and
              (tabbar-selected-p tab (tabbar-current-tabset))
              (memq (current-buffer) (my-buffer-list (selected-frame))))
            'tabbar-selected-associated)
          ((and
              (not (tabbar-selected-p tab (tabbar-current-tabset)))
              (memq (current-buffer) (my-buffer-list (selected-frame))))
            'tabbar-unselected-associated)
          ((and
              (tabbar-selected-p tab (tabbar-current-tabset))
              (not (memq (current-buffer) (my-buffer-list (selected-frame)))))
            'tabbar-selected-unassociated)
          ((and
              (not (tabbar-selected-p tab (tabbar-current-tabset)))
              (not (memq (current-buffer) (my-buffer-list (selected-frame)))))
            'tabbar-unselected-unassociated))
      'pointer 'hand)
    tabbar-separator-value))

(define-key global-map "\C-c\C-r" 'my-buffer-list-reset)

(define-key global-map "\C-c\C-a" 'my-add-buffer)

(define-key global-map "\C-c\C-n" 'my-remove-buffer)

(define-key global-map (kbd "<M-s-right>") 'tabbar-forward)

(define-key global-map (kbd "<M-s-left>") 'tabbar-backward)

(define-key global-map [C-tab] 'my-switch-tab-group)

(tabbar-mode 1)

Der folgende Screenshot zeigt die zwei möglichen Puffer- / Registerkartengruppierungen: (1) Auf der linken Seite befindet sich eine Gruppierung der Puffer / Registerkarten, die dem Rahmen mit dem Namen SYSTEM[gelbe und weiße Registerkarten] zugeordnet sind Mode-Line; und (2) auf der rechten Seite ist eine Gruppierung der Puffer / Tabs, die NICHT dem Rahmen mit dem Namen SYSTEM[blaue und rote Tabs] zugeordnet sind, wobei ein Großbuchstabe "N" in der Moduszeile angegeben ist.

Beispiel

Gesetzesliste
quelle
Das OP möchte jedoch nicht "eine Registerkarte pro Fenster", sondern eine Registerkarte pro Frame, und jede Registerkarte in der Registerkarte sollte eine "Fensterkonfiguration" (dh mehrere Fenster) anstelle eines Puffers darstellen.
Stefan
5

Betrachten Sie das Auschecken von elscreen , obwohl es Puffer nicht wirklich gruppiert.

Es gruppiert Fenster und bietet Zugriff auf mehrere Layouts (Registerkarten), zwischen denen Sie schnell wechseln können. In meinem Workflow befinden sich häufig Ruby-Code und zugehörige Tests auf einem Bildschirm, während sich meine Aufgaben- und Organisationsnotizen auf einem anderen befinden und sich in einem dritten möglicherweise ein Arbeitspuffer zum Erstellen von SQL-Abfragen befindet. Auf diese Weise kann ich problemlos zwischen Aufgaben und Projekten wechseln, obwohl sich jeder Bildschirm auf denselben Pufferpool stützt.

RP Dillon
quelle
3

Wie wäre es mit meinem Plugin, Centaur-Tabs? Es hat viele Konfigurationsoptionen, ist sehr funktional, wird von sehr beliebten Themen wie Kaolin-Themen unterstützt und ist insgesamt ein wirklich gut aussehendes und ästhetisches Paket (je nach Feedback des Benutzers). Es ist in MELPA verfügbar und sieht folgendermaßen aus:

Bildbeschreibung hier eingeben

Emmanuel Bustos
quelle
Dies scheint eine weitere Nicht-Lösung zu sein: "Jeder Tab repräsentiert einen Puffer und jedes Fenster hat eine eigene Tab-Leiste."
Stefan
Ich habe gerade eine Anpassung hinzugefügt, um Registerkartengruppen anstelle von Registerkartennamen anzuzeigen, damit in einer Funktion Regeln festgelegt werden (dh Gruppen-Elisp und -Lisp in einer Gruppe, Gruppe c und c ++ in einer anderen usw.) und in den Registerkarten werden diese Gruppen angezeigt.
Emmanuel Bustos
Es ist immer noch nicht die Frage beantwortet, wo es eine Registerkarte pro Frame (anstatt pro Fenster) geben soll und jede Registerkarte eine Fensterkonfiguration darstellt.
Stefan
Ok, ich habe nicht verstanden. Ich werde nachforschen und daran arbeiten!
Emmanuel Bustos
0

Hier ist meine Konfiguration, für was es sich lohnt. Es verfügt über:

  • Mausbedienung auf Registerkarten ( mouse-2zum Schließen, wie in Browsern , mouse-3 zum Öffnen in einem neuen Emacs-Fenster, wie in i3 )
  • Tastatursteuerung ( M-left& rechte Schalter-Tabs, wie in TMux / Screen )
  • Farben (im Einklang mit "Moe theme / moe-dark" config enthalten)
  • Gruppierung (derzeit Emacs *buffers*und "normal")
  • Automatisch aktualisiert (mit Use-Package )

Tab-Leiste

(use-package tabbar
  :ensure t
  :bind
  ("<M-left>" . tabbar-backward)
  ("<M-right>" . tabbar-forward)

  :config
  (set-face-attribute
   'tabbar-button nil
   :box '(:line-width 1 :color "gray19"))

  (set-face-attribute
   'tabbar-selected nil
   :foreground "orange"
   :background "gray19"
   :box '(:line-width 1 :color "gray19"))

  (set-face-attribute
   'tabbar-unselected nil
   :foreground "gray75"
   :background "gray25"
   :box '(:line-width 1 :color "gray19"))

  (set-face-attribute
   'tabbar-highlight nil
   :foreground "black"
   :background "orange"
   :underline nil
   :box '(:line-width 1 :color "gray19" :style nil))

  (set-face-attribute
   'tabbar-modified nil
   :foreground "orange red"
   :background "gray25"
   :box '(:line-width 1 :color "gray19"))

  (set-face-attribute
   'tabbar-selected-modified nil
   :foreground "orange red"
   :background "gray19"
   :box '(:line-width 1 :color "gray19"))

  (custom-set-variables
   '(tabbar-separator (quote (0.2))))

  (defun tabbar-buffer-tab-label (tab)
    "Return a label for TAB.
  That is, a string used to represent it on the tab bar."
    (let ((label  (if tabbar--buffer-show-groups
                      (format " [%s] " (tabbar-tab-tabset tab))
                    (format " %s " (tabbar-tab-value tab)))))
      (if tabbar-auto-scroll-flag
          label
        (tabbar-shorten
         label (max 1 (/ (window-width)
                         (length (tabbar-view
                                  (tabbar-current-tabset)))))))))

  (defun px-tabbar-buffer-select-tab (event tab)
    "On mouse EVENT, select TAB."
    (let ((mouse-button (event-basic-type event))
          (buffer (tabbar-tab-value tab)))
      (cond
       ((eq mouse-button 'mouse-2) (with-current-buffer buffer (kill-buffer)))
       ((eq mouse-button 'mouse-3) (pop-to-buffer buffer t))
       (t (switch-to-buffer buffer)))
      (tabbar-buffer-show-groups nil)))

  (defun px-tabbar-buffer-help-on-tab (tab)
    "Return the help string shown when mouse is onto TAB."
    (if tabbar--buffer-show-groups
        (let* ((tabset (tabbar-tab-tabset tab))
               (tab (tabbar-selected-tab tabset)))
          (format "mouse-1: switch to buffer %S in group [%s]"
                  (buffer-name (tabbar-tab-value tab)) tabset))
      (format "\
mouse-1: switch to %S\n\
mouse-2: kill %S\n\
mouse-3: Open %S in another window"
              (buffer-name (tabbar-tab-value tab))
              (buffer-name (tabbar-tab-value tab))
              (buffer-name (tabbar-tab-value tab)))))

  (defun px-tabbar-buffer-groups ()
    "Sort tab groups."
    (list (cond ((or
                  (eq major-mode 'dired-mode)
                  (string-equal "*" (substring (buffer-name) 0 1))) "emacs")
                (t "user"))))
  (setq tabbar-help-on-tab-function 'px-tabbar-buffer-help-on-tab
        tabbar-select-tab-function 'px-tabbar-buffer-select-tab
        tabbar-buffer-groups-function 'px-tabbar-buffer-groups)

  :init
  (tabbar-mode 1))

Anhang 1 - Thema Moe

(use-package moe-theme
  :ensure t
  :config
  (progn
    (load-theme 'moe-dark :no-confirm)
    (set-face-attribute 'fringe nil :background "gray19")))

Anhang 2 - Die letzten 2 Puffer umschalten (KB-Makro)

(define-key global-map [(control tab)] (kbd "C-x b <return>")) 
yPhil
quelle