'Tab' ala peramban untuk emacs?

22

Saya ingin tab seperti firefox tetapi untuk emacs.

Saya menemukan ini: http://emacswiki.org/emacs/TabBarMode

Tapi itu hanya menambah setiap buffer ( jendela dalam terminologi Emacs) sebuah bar yang menunjukkan buffer saat ini terbuka.

Saya ingin tab dapat menampung beberapa buffer ( windows di Emacs teminology), yang dapat saya bagi sesuai keinginan. Yaitu setiap tab harus sesuai dengan "keadaan jendela" (dalam arti window-state-get).

Saya memiliki satu tab untuk tugas saya, satu lagi untuk kode, satu lagi untuk membaca web dll.

Apakah ini mungkin? Bisakah tabbar disesuaikan untuk melakukan ini?

[edit2]
Pertanyaan ini telah menarik lebih banyak perhatian daripada yang saya perkirakan. Sepertinya ada solusi, tetapi yang akan membutuhkan sedikit riset dan penyesuaian. Walaupun minggu ini / minggu depan agak sibuk untuk saya, saya akan menguraikan jawaban dan akan mencoba untuk membangun sesuatu yang berhasil dan kemudian saya akan mengedit pertanyaan ini untuk mencerminkan temuan saya. Silakan tunggu =)

[edit]
Semacam mirip dengan:
/programming/24157754/make-frames-in-emacs-gui-behaves-like-frames-in-terminal

Saya akan puas dengan beberapa frame dalam satu sesi GUI juga.

Leo Ufimtsev
sumber
2
"Saya ingin tab dapat menampung beberapa buffer, yang dapat saya bagi sesuai keinginan." Apakah maksud Anda beberapa jendela ?
Malabarba
1
Ini lebih seperti saya ingin memiliki tab yang sangat dyanmic. Saya akan membuatnya dan mengisinya dengan windows. Yaitu saya ingin tab menjadi bingkai. Kemudian tab baru bingkai baru. Di dalam setiap tab / bingkai saya bisa membuka windows / (buffer) yang diinginkan. Apakah ini bisa dilakukan? (Yaitu, tidak ada nama buffer yang dikodekan, dll.)
Leo Ufimtsev
1
Ada variabel yang terkait dengan jendela tertentu, tetapi sudah satu atau dua bulan sejak saya melihat utas yang membicarakannya dan saya tidak tahu apa itu namanya begitu saja. Anda mungkin tertarik menggunakan sistem yang mirip dengan frame-bufs di mana daftar menampung buffer yang terkait dengan bingkai dan daftar itu dimasukkan ke dalam parameter frame. Anda bisa menggunakan variabel yang dikaitkan dengan jendela tertentu dan dan membuatnya menjadi daftar, tambahkan / hapus buffer dari daftar - daftar itu akan menjadi kelompok penyangga yang akan digunakan oleh tabbar. Ini semua teoretis, tapi saya yakin ini akan berhasil.
hukum
1
Saya pikir Anda dapat merujuk ke: stackoverflow.com/questions/24157754/… tetapi postingan itu tampaknya tidak memiliki jawaban yang solid: - /
Leo Ufimtsev
1
Saya akan merekomendasikan untuk melihat paket elscreen.
blarghmatey

Jawaban:

8

Pisahkan buffer dalam kelompok

Mungkin dengan tabbar. Anda dapat menambahkan aturan ke buffer grup dalam grup. Berikut cuplikan dasar:

(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"
     ))))

Aturan contoh:

  1. Daftar nama penyangga:
    ((member (buffer-name)
             '("*scratch*" "*Messages*" "*Help*"))
     "Common" ;; this is a group name
     )
  1. Mengenai buffer umum, saya lebih suka memasukkan "Biasa" setiap buffer yang namanya dimulai dengan bintang. Ini memberikan contoh membuat buffer untuk aturan ini:
    ((string-equal "*" (substring (buffer-name) 0 1))
     "Common"
     )
  1. Berikut adalah contoh pengelompokan buffer berdasarkan mode utama:
    ((memq major-mode
           '(org-mode text-mode rst-mode))
     "Text"
     )
  1. Berikut adalah contoh pengelompokan buffer berdasarkan mode dari mana mereka berasal:
    ((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. Berikut adalah contoh pengelompokan tab berdasarkan regexp:
    ((string-match "^__" (buffer-name))
     "Templates"
     )
  1. Grup buffer berdasarkan mode utama:
    (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))

Setelah Anda membuat aturan, Anda dapat menekan + atau - pada baris tab tabbar untuk beralih grup, dan juga ◀ dan ▶ untuk beralih di antara buffer. Atau cukup ikatkan pertahanan berikut:

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

dan berpindah di antara tab dan grup tab dengan keyboard.

Secara pribadi saya mengelompokkan tab, sehingga saya melihat apa yang terbuka, tetapi menavigasi dengan mereka ido-switch-buffer.

Beralih di antara seperangkat aturan

Kita juga dapat mendefinisikan serangkaian aturan pengelompokan buffer dan siklus di antaranya. Berikut adalah contoh bersepeda antara dua set aturan pengelompokan buffer:

;; 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)

Ini beralih di antara tabbar-buffer-groups-commondan tabbar-buffer-groupspengelompokan defune tab.

Urutkan buffer tabbar berdasarkan nama

Saya merasa bermanfaat untuk menyortir buffer tabbar berdasarkan nama. Berikut cara mendapatkannya:

(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
sumber
Terima kasih atas jawaban terincinya. Saya akan mencoba untuk mencoba di atas dan akan memberi tahu Anda ~ akhirnya :)
Leo Ufimtsev
Tetapi OP tidak ingin "satu tabbar per jendela", ia ingin satu tabbar per bingkai dan setiap tab di tabbar harus mewakili "konfigurasi jendela" (yaitu beberapa jendela) daripada buffer, jadi pengelompokan buffer bukan masalah. .
Stefan
6

ATTRIBUT: Pengelompokan buffer berdasarkan per frame adalah implementasi langsung dari konsep-konsep dan bagian-bagian tertentu dari kode yang dikembangkan / ditulis oleh Alp Aker di library frame-bufs: https://github.com/alpaker/Frame-Bufs

Berikut ini adalah contoh cara menggunakan perpustakaan tabbar.eldan grup tab / buffer secara dinamis berdasarkan per-frame dengan menambahkan tab / buffer dengan C-c C-aatau menghapus tab / buffer dengan C-c C-n. Hanya ada dua (2) kelompok - yang terkait dengan bingkai saat ini (yaitu, "A"), dan TIDAK terkait dengan bingkai saat ini (yaitu, "N"). Grup adalah frame-lokal, yang berarti bahwa setiap frame dapat memiliki pengelompokan sendiri. Pengelompokan khusus dapat diatur ulang dengan C-c C-r. Beralih antara grup terkait dan tidak terkait dengan C-tab. Beralih ke tab / buffer berikutnya dalam grup saat ini dengan M-s-right. Beralih ke tab / buffer sebelumnya di grup saat ini dengan M-s-left.

Tab / buffer dapat ditambahkan atau dihapus secara pemrograman dengan my-add-bufferdan my-remove-buffer. Untuk contoh cara membuka buffer tertentu dalam bingkai tertentu, silakan lihat utas terkait yang berjudul Cara mencegat file sebelum dibuka dan tentukan bingkai mana : /programming//a/18371427/2112489 Fungsi my-add-bufferini perlu dimasukkan di lokasi yang sesuai dari kode di tautan di atas jika pengguna memilih untuk mengimplementasikan fitur itu.

Pengguna mungkin ingin membuat entri dalam kustom mode-line-formatyang menampilkan nama grup tab saat ini di mode-line dengan memasukkan potongan berikut: (:eval (when tabbar-mode (format "%s" (tabbar-current-tabset t)))) Kustomisasi mode-line lebih detail, bagaimanapun, berada di luar cakupan contoh ini.

Fungsi tabbar-add-tabini telah dimodifikasi untuk mengabjadkan tab / buffer.

Fungsi tabbar-line-tabini telah dimodifikasi untuk menyediakan empat (4) wajah berbeda tergantung pada situasinya. Jika tab / buffer dikaitkan dengan bingkai dan IS dipilih, maka gunakan tabbar-selected-associatedwajah. Jika tab / penyangga dikaitkan dengan bingkai dan TIDAK dipilih, maka gunakan tabbar-unselected-associatedwajah. Jika tab / buffer TIDAK terkait dengan bingkai dan IS dipilih, maka gunakan tabbar-selected-unassociatedwajah. Jika tab / buffer TIDAK terkait dengan bingkai dan TIDAK dipilih, maka gunakan tabbar-unselected-unassociatedwajah.

;; 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)

Tangkapan layar berikut menggambarkan dua kemungkinan buffer / tab pengelompokan: (1) di sebelah kiri adalah pengelompokan dari buffer / tab yang dikaitkan dengan bingkai bernama SYSTEM[tab kuning dan putih], dengan huruf kapital "A" ditunjukkan dalam mode-line; dan (2) di sebelah kanan adalah pengelompokan buffer / tab yang TIDAK terkait dengan bingkai bernama SYSTEM[tab biru dan merah], dengan huruf kapital "N" yang ditunjukkan dalam mode-line.

Contoh

daftar hukum
sumber
Tetapi OP tidak ingin "satu tabbar per jendela", ia ingin satu tabbar per bingkai dan setiap tab di tabbar harus mewakili "konfigurasi jendela" (yaitu beberapa jendela) daripada buffer.
Stefan
5

Pertimbangkan untuk memeriksa elscreen , meskipun itu sebenarnya bukan buffer grup.

Apa yang dilakukannya adalah mengelompokkan jendela dan menyediakan akses ke beberapa tata letak (tab) yang dapat Anda pindahkan dengan cepat. Alur kerja saya sering memiliki beberapa kode Ruby dan tes terkait di satu layar, sedangkan catatan todo dan Org saya ada di layar lain, dan mungkin buffer awal untuk penyusunan kueri SQL ada di layar ketiga. Ini memungkinkan saya untuk beralih antara tugas dan proyek dengan mudah, meskipun setiap layar menggunakan kumpulan buffer yang sama.

RP Dillon
sumber
3

Bagaimana dengan plugin saya, centaur-tab? Ini memiliki banyak opsi konfigurasi, itu benar-benar fungsional, didukung oleh tema yang sangat populer seperti Kaolin Themes dan secara keseluruhan adalah paket yang terlihat sangat bagus dan estetika (sesuai dengan umpan balik pengguna). Ini tersedia dalam MELPA dan terlihat seperti ini:

masukkan deskripsi gambar di sini

Emmanuel Bustos
sumber
Ini tampaknya menjadi satu lagi "setiap tab mewakili buffer dan setiap jendela memiliki tabbar sendiri" non-solusi.
Stefan
Saya baru saja menambahkan kustomisasi untuk menampilkan grup tab alih-alih nama tab sehingga dalam fungsi Anda menetapkan aturan (yaitu grup elisp dan lisp dalam satu grup, grup c dan c ++ di grup lain dan seterusnya) dan di tab grup tersebut ditampilkan.
Emmanuel Bustos
Itu masih tidak menjawab pertanyaan, di mana harus ada satu tabbar per frame (bukan per jendela) dan masing-masing tab mewakili konfigurasi jendela.
Stefan
Ok, saya tidak mengerti. Saya akan menyelidiki dan bekerja di sana!
Emmanuel Bustos
0

Ini konfigurasi saya, untuk apa yang layak. Ini fitur:

  • Operasi mouse pada tab ( mouse-2untuk menutup, seperti di browser , mouse-3 untuk membuka di jendela Emacs baru, seperti di i3 )
  • Kontrol keyboard ( M-left& tab sakelar kanan, seperti pada TMux / Layar )
  • Warna (konsisten dengan moe-darkkonfigurasi " Tema Moe / " termasuk)
  • Pengelompokan (saat ini, Emacs *buffers*dan "reguler")
  • Pembaruan otomatis (dengan paket penggunaan )

TabBar

(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))

Lampiran 1 - Tema Moe

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

Lampiran 2 - Beralih 2 buffer terakhir (KB makro)

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