Coder Social home page Coder Social logo

ema2159 / centaur-tabs Goto Github PK

View Code? Open in Web Editor NEW
723.0 10.0 49.0 3.27 MB

Emacs plugin aiming to become an aesthetic, modern looking tabs plugin

License: GNU General Public License v3.0

Emacs Lisp 99.61% Makefile 0.39%
emacs emacs-lisp emacs-package emacs-plugin elisp

centaur-tabs's Introduction

Centaur tabs

https://melpa.org/packages/centaur-tabs-badge.svg https://stable.melpa.org/packages/centaur-tabs-badge.svg https://img.shields.io/badge/License-GPL%20v3-blue.svg https://github.com/ema2159/centaur-tabs/actions/workflows/test.yml/badge.svg

./images/centaur.png

Contents

What is this?

This projects aims to become an aesthetic, functional and efficient tabs plugin for Emacs with a lot of customization options. Although this is a fork from awesome-tab (that I forked with the permission from the author and it’s also based on tabbar) it’s been heavily modified so now it may be considered a different package. Also this package integrates functionalities from tabbar-ruler.

It currently looks like this (although there’s a ton of possible configurations):

./screenshot.png

Installation

You can download this package from MELPA. This is a basic use-package configuration:

(use-package centaur-tabs
  :demand
  :config
  (centaur-tabs-mode t)
  :bind
  ("C-<prior>" . centaur-tabs-backward)
  ("C-<next>" . centaur-tabs-forward))

Or if you use require:

(require 'centaur-tabs)
(centaur-tabs-mode t)
(global-set-key (kbd "C-<prior>")  'centaur-tabs-backward)
(global-set-key (kbd "C-<next>") 'centaur-tabs-forward)

Customization

This package is heavily customizable, with many options available to the user. Here are some of them:

Headline face

You can make the headline face match the centaur-tabs-default face. This makes the tabbar have an uniform appearance. In your configuration use the following function:

(centaur-tabs-headline-match)

Tab Styles

To change the tab style, modify the centaur-tabs-style variable like this:

(setq centaur-tabs-style "bar")

The options available are:

  • “alternate”

./images/alternate.png

  • “bar”

./images/bar.png

  • “box”

./images/box.png

  • “chamfer”

./images/chamfer.png

  • “rounded”

./images/rounded.png

  • “slant”

./images/slant.png

  • “wave”

./images/wave.png

  • “zigzag”

./images/zigzag.png

Tab height

To change the tab height do

(setq centaur-tabs-height 32)

Tab icons

To display themed icons from all the icons

(setq centaur-tabs-set-icons t)

Plain icons

To make icons plain (same color as tabs’ text):

(setq centaur-tabs-plain-icons t)

Graying out icons

To gray out icons for the unselected tabs:

(setq centaur-tabs-gray-out-icons 'buffer)

Selected tab bar

To display a colored bar at the left of the selected tab

(setq centaur-tabs-set-bar 'left)

./images/bar.png

To display an overline over the selected tab:

(setq centaur-tabs-set-bar 'over)

./images/overline.png

To display an underline over the selected tab:

(setq centaur-tabs-set-bar 'under)
;; Note: If you're not using Spacmeacs, in order for the underline to display
;; correctly you must add the following line:
(setq x-underline-at-descent-line t)

./images/underline.png

The color can be customized via the centaur-tabs-active-bar-face face.

Customize the close button

To disable the close button

(setq centaur-tabs-set-close-button nil)

To change the displayed string for the close button

(setq centaur-tabs-close-button "X")

Also there are two faces to customize the close button string: centaur-tabs-close-unselected and centaur-tabs-close-selected

Customize the modified marker

To display a marker indicating that a buffer has been modified (atom-style)

(setq centaur-tabs-set-modified-marker t)

To change the displayed string for the modified-marker

(setq centaur-tabs-modified-marker "*")

Also there are two faces to customize the close button string: centaur-tabs-modified-marker-unselected and centaur-tabs-modified-marker-selected

./images/marker.png

Change the font family and height

To easily customize the tabs font by changing it’s height and font family use the following function:

(centaur-tabs-change-fonts "arial" 160)

Disable centaur-tabs in selected buffers

To disable the tabs in a buffer just add a hook to the centaur-tabs-local-mode function like this:

(add-hook 'dired-mode-hook 'centaur-tabs-local-mode)

or with use-package:

(use-package centaur-tabs
  ...
  :hook
  (dired-mode . centaur-tabs-local-mode)
  ...)

Buffer groups

To customize the way that the buffers are grouped modify the centaur-tabs-buffer-groups function like this:

(defun centaur-tabs-buffer-groups ()
  "`centaur-tabs-buffer-groups' control buffers' group rules.

Group centaur-tabs with mode if buffer is derived from `eshell-mode' `emacs-lisp-mode' `dired-mode' `org-mode' `magit-mode'.
All buffer name start with * will group to \"Emacs\".
Other buffer group by `centaur-tabs-get-group-name' with project name."
  (list
   (cond
    ((or (string-equal "*" (substring (buffer-name) 0 1))
         (memq major-mode '(magit-process-mode
                            magit-status-mode
                            magit-diff-mode
                            magit-log-mode
                            magit-file-mode
                            magit-blob-mode
                            magit-blame-mode
                            )))
     "Emacs")
    ((derived-mode-p 'prog-mode)
     "Editing")
    ((derived-mode-p 'dired-mode)
     "Dired")
    ((memq major-mode '(helpful-mode
                        help-mode))
     "Help")
    ((memq major-mode '(org-mode
                        org-agenda-clockreport-mode
                        org-src-mode
                        org-agenda-mode
                        org-beamer-mode
                        org-indent-mode
                        org-bullets-mode
                        org-cdlatex-mode
                        org-agenda-log-mode
                        diary-mode))
     "OrgMode")
    (t
     (centaur-tabs-get-group-name (current-buffer))))))

Show buffer groups names instead of buffer names in tabs

If you want your tabs to display buffer groups names instead of buffer names you can put the following in your configuration:

(setq centaur-tabs--buffer-show-groups t)

You can toggle between the two options interactively with the (centaur-tabs-toggle-groups) command.

Enable Vim like tab motions

To enable Vim like tab changing binds

(define-key evil-normal-state-map (kbd "g t") 'centaur-tabs-forward)
(define-key evil-normal-state-map (kbd "g T") 'centaur-tabs-backward)

or with use-package:

(use-package centaur-tabs
  ...
  :bind
  (:map evil-normal-state-map
        ("g t" . centaur-tabs-forward)
        ("g T" . centaur-tabs-backward))
  ...)

Prevent the access to specified buffers

You can prevent the access to some buffers via tab motions changing the following function like this:

(defun centaur-tabs-hide-tab (x)
  "Do no to show buffer X in tabs."
  (let ((name (format "%s" x)))
    (or
     ;; Current window is not dedicated window.
     (window-dedicated-p (selected-window))

     ;; Buffer name not match below blacklist.
     (string-prefix-p "*epc" name)
     (string-prefix-p "*helm" name)
     (string-prefix-p "*Helm" name)
     (string-prefix-p "*Compile-Log*" name)
     (string-prefix-p "*lsp" name)
     (string-prefix-p "*company" name)
     (string-prefix-p "*Flycheck" name)
     (string-prefix-p "*tramp" name)
     (string-prefix-p " *Mini" name)
     (string-prefix-p "*help" name)
     (string-prefix-p "*straight" name)
     (string-prefix-p " *temp" name)
     (string-prefix-p "*Help" name)
     (string-prefix-p "*mybuf" name)

     ;; Is not magit buffer.
     (and (string-prefix-p "magit" name)
          (not (file-name-extension name)))
     )))

The function shown is the default function from the centaur-tabs configuration, adding the (string-prefix-p "*​mybuf" name) part to prevent the access to every buffer with its name ending in “mybuf”. You can either add this function as it is to preserve centaur-tabs default filters and add any Boolean function that you want to filter your buffers (i.e string-prefix-p or string-suffix-p) like in this example with the “mybuf” line, or completely override the function with your custom filters if you completely know what you’re doing.

Tab cycling

The default behaviour from the centaur-tabs-forward/backward functions is to go through all the tabs in the current group and then change the group. If this is something that is to desired to be changed the centaur-tabs-cycle-scope custom must be changed like this:

(setq centaur-tabs-cycle-scope 'tabs)

There are three options:

  • ‘default: (Already described)
  • ‘tabs: Cycle through visible tabs (that is, the tabs in the current group)
  • ‘groups: Navigate through tab groups only

Buffer reordering (thanks to jixiuf)

To enable an automatic buffer reordering function use the following function in your configuration:

(centaur-tabs-enable-buffer-reordering)
;; When the currently selected tab(A) is at the right of the last visited
;; tab(B), move A to the right of B. When the currently selected tab(A) is
;; at the left of the last visited tab(B), move A to the left of B
(setq centaur-tabs-adjust-buffer-order t)

;; Move the currently selected tab to the left of the the last visited tab.
(setq centaur-tabs-adjust-buffer-order 'left)

;; Move the currently selected tab to the right of the the last visited tab.
(setq centaur-tabs-adjust-buffer-order 'right)

This works the following way. If there’s a certain group of tabs like the following:

tab1.eltab2.jstab3.ctab4.py

If you’re in a tab and change to another tab in the group (via Ido, Ivy or Helm) the new tab will move to the right side of the tab you were, so if you’re on tab1.el and you clicked tab4.py the tabs order will be the following:

tab1.eltab4.pytab2.jstab3.c

And then if you were on tab4.py and changed to tab2.js, the tabs order will be the following:

tab1.eltab4.pytab2.jstab3.c

the order doesn’t change, because the tabs are already next to each other.

And now if you were on tab2.js and changed to tab1.el, the tabs order will be the following:

tab4.pytab1.eltab2.jstab3.c

This functionality doesn’t take effect when using centaur-tabs motion functions like centaur-tabs-backward/forward.

Alphabetical buffer reordering (thanks to cburroughs)

To enable an automatic alpabetical buffer reordering, put the following lines in your configuration.

(centaur-tabs-enable-buffer-alphabetical-reordering)
(setq centaur-tabs-adjust-buffer-order t)

This function will trigger each time a non centaur-tabs motion command is executed. NOTE: Given the Emacs behaviour when opening a new file is a little bit funky, when a new tab is opened, it will always be placed at the right of the last visited buffer. This behaviour needs to be investigated in order to see if a possible solution exists.

Fixed tab length

If you desire to make the width of your tabs fixed, you have to modify the centaur-tabs-label-fixed-length custom variable with the maximum length desired (defaults to 0 for dynamic). Example:

(setq centaur-tabs-label-fixed-length 8)

Would render the following tabs:

foo.orga_very_d…bar.org

Selectrum integration (revert to completing-read)

Turn off default ido-mode completions by customising centaur-tabs-enable-ido-completion in order to revert to Emacs’ native completing-read.

Helm integration

You can integrate Helm with centaur-tabs for changing tab-groups. Just add helm-source-centaur-tabs-group in helm-source-list. Then you’ll be able to use (centaur-tabs-build-helm-source) function and bind it to any key you want. (I’m not a Helm user so I’ll not be able to solve problems related to this).

Ivy integration

You can integrate Ivy with centaur-tabs for changing tab-groups. Just use the (centaur-tabs-counsel-switch-group) and bind it to any key you want.

Projectile integration

You can group your tabs by Projectile’s project. Just use the following function in your configuration:

(centaur-tabs-group-by-projectile-project)

This function can be called interactively to enable Projectile grouping. To go back to centaur-tabs’s user defined (or default) buffer grouping function you can interactively call:

(centaur-tabs-group-buffer-groups)

Mouse support (thanks to alvarogonzalezsotillo)

  • Just click in a tab to change the buffer of the current window.
  • Click the mouse wheel to close a buffer.
  • Right click on empty space to show a tab groups popup.
  • Right click on a tab to show a context menu. The options are inspired by the options provided by VSCode. images/tab-context-menu.png
  • Use the mouse wheel to invoke centaur-tabs-backward/forward.
  • Set the centaur-tabs-show-navigation-buttons custom variable to t to display cool navigation buttons. With the CTRL key, the left and right navigation buttons will move the tabs through the tab line. images/navigation-buttons.png

New-tab button (thanks to lucasgruss)

The new-tab button is a button at the right of the tabs that will spawn a new tab based on the current context. For instance in vterm/eshell/ansi-term mode, the new tab will spawn a new buffer corresponding to the current major mode. In eww, you are prompted for a search term and the result is displayed in a new buffer. The default behaviour in other modes is to open a new empty buffer.

  • the variable centaur-tabs-show-new-tab-button controls whether the button is shown.
  • the variable centaur-tabs-new-tab-text controls the appearance of the button.
  • the function centaur-tabs--create-new-tab controls the behaviour of the context-based new tab.

Tab count (thanks to kamilwaheed)

Adds a count of the current tab position in the total number of tabs in the current window. Controlled by the variable centaur-tabs-show-count.

Ace jump (thanks to Simon-Lin)

Enables quick tab switching through an Ace-jump/Avy-like interface. To use it, interactively call the centaur-tabs-ace-jump function. While on Ace-jump mode, you can press ? to display a menu showing the possible actions available. images/ace-jump.png

Key bindings

If you want to enable a series of key bindings with different tab managing functions, put the following in your configuration before the package is loaded (if you use use-package, this should go in the :init section):

(setq centaur-tabs-enable-key-bindings t)

This will enable a series of key bindings for centaur-tabs prefixed by “C-c t”.

TO DO [17/19]

  • [X] Integrate all-the-icons
  • [X] Improve all the icons placing
  • [X] Fix all the icons background
  • [X] Add selected, unselected, selected-modified and unselected-modified faces
  • [X] Make function to inherit tabbar faces
  • [X] Group tabs by projectile’s project (was already implemented but not for projectile)
  • [X] Create PR to different theme packages for this package
  • [X] Add modified marker icon option
  • [X] Add sideline for selected tab (atom style)
  • [X] Add overline for selected tab (atom style). It’s easy to add to the text, but not to the icon, so for any who figures it out a PR is welcome.
  • [ ] Add easy tab style configuration function. (Atom, Sublime, VS Code… like (centaur-tabs-tab-theme "atom"))
  • [X] Make icon insert after the separator
  • [X] Add a customizable close button
  • [X] Explore if after-modifying-buffer function can be improved
  • [X] Fix messages buffer icon an FontAwesome errors
  • [X] Check for Elscreen compatibility
  • [X] Add this package to MELPA
  • [X] Make a configuration to display buffer groups names instead of buffer names in tabs
  • [ ] Add full evil-mode support with tab commands

My personal configuration

My personal configuration for reference:

(use-package centaur-tabs
  :init
  (setq centaur-tabs-enable-key-bindings t)
  :config
  (setq centaur-tabs-style "bar"
        centaur-tabs-height 32
        centaur-tabs-set-icons t
        centaur-tabs-show-new-tab-button t
        centaur-tabs-set-modified-marker t
        centaur-tabs-show-navigation-buttons t
        centaur-tabs-set-bar 'under
        centaur-tabs-show-count nil
        ;; centaur-tabs-label-fixed-length 15
        ;; centaur-tabs-gray-out-icons 'buffer
        ;; centaur-tabs-plain-icons t
        x-underline-at-descent-line t
        centaur-tabs-left-edge-margin nil)
  (centaur-tabs-change-fonts (face-attribute 'default :font) 110)
  (centaur-tabs-headline-match)
  ;; (centaur-tabs-enable-buffer-alphabetical-reordering)
  ;; (setq centaur-tabs-adjust-buffer-order t)
  (centaur-tabs-mode t)
  (setq uniquify-separator "/")
  (setq uniquify-buffer-name-style 'forward)
  (defun centaur-tabs-buffer-groups ()
    "`centaur-tabs-buffer-groups' control buffers' group rules.

Group centaur-tabs with mode if buffer is derived from `eshell-mode' `emacs-lisp-mode' `dired-mode' `org-mode' `magit-mode'.
All buffer name start with * will group to \"Emacs\".
Other buffer group by `centaur-tabs-get-group-name' with project name."
    (list
     (cond
      ;; ((not (eq (file-remote-p (buffer-file-name)) nil))
      ;; "Remote")
      ((or (string-equal "*" (substring (buffer-name) 0 1))
           (memq major-mode '(magit-process-mode
                              magit-status-mode
                              magit-diff-mode
                              magit-log-mode
                              magit-file-mode
                              magit-blob-mode
                              magit-blame-mode
                              )))
       "Emacs")
      ((derived-mode-p 'prog-mode)
       "Editing")
      ((derived-mode-p 'dired-mode)
       "Dired")
      ((memq major-mode '(helpful-mode
                          help-mode))
       "Help")
      ((memq major-mode '(org-mode
                          org-agenda-clockreport-mode
                          org-src-mode
                          org-agenda-mode
                          org-beamer-mode
                          org-indent-mode
                          org-bullets-mode
                          org-cdlatex-mode
                          org-agenda-log-mode
                          diary-mode))
       "OrgMode")
      (t
       (centaur-tabs-get-group-name (current-buffer))))))
  :hook
  (dashboard-mode . centaur-tabs-local-mode)
  (term-mode . centaur-tabs-local-mode)
  (calendar-mode . centaur-tabs-local-mode)
  (org-agenda-mode . centaur-tabs-local-mode)
  :bind
  ("C-<prior>" . centaur-tabs-backward)
  ("C-<next>" . centaur-tabs-forward)
  ("C-S-<prior>" . centaur-tabs-move-current-tab-to-left)
  ("C-S-<next>" . centaur-tabs-move-current-tab-to-right)
  (:map evil-normal-state-map
        ("g t" . centaur-tabs-forward)
        ("g T" . centaur-tabs-backward)))

Useful commands

Centaur tabs has plenty of useful commands for manipulating tabs and tab groups. Some of them are:

  • (centaur-tabs-kill-all-buffers-in-current-group): Kills all buffers in current tab group.
  • (centaur-tabs-kill-match-buffers-in-current-group): Kills all buffers in current tab group with the same extension as the current buffer.
  • (centaur-tabs-keep-match-buffers-in-current-group): Asks for a file extension and kills all the buffers with a different extension.
  • (centaur-tabs-kill-other-buffers-in-current-group): Kills all buffers in current tab group except the current buffer.
  • (centaur-tabs-kill-unmodified-buffers-in-current-group): Kills all buffers in current tab group that are unmodified.
  • (centaur-tabs-select-beg-tab): Selects the first tab of the group.
  • (centaur-tabs-select-end-tab): Selects the last tab of the group.
  • (centaur-tabs-forward-group): Go to the next tab group.
  • (centaur-tabs-backward-group): Go to the previous tab group.

Common issues

Icons not showing

If the icons in your tabs are not showing, it is likely because of one of the two following reasons:

all-the-icons not installed

If all-the-icons is not installed properly, your mode icons won’t show up. To solve this issue, you have to install all-the-icons and follow the instructions indicated in its repository.

Font with required unicode symbols missing

If you get something like the following image in your tabs:

./images/font-missing.png

it is likely that you’re missing a font that has the required unicode symbols. To solve this issue, simply install a font that has this symbols such as Google Noto Sans Symbols2.

Known supported theme plugins

How to contribute

You can contribute by forking the repo and then creating a pull request with the changes you consider will improve the package. There’s a TO DO list with wanted features so you can start from there. I’ll be glad to receive help. Please try to keep the code as clear and documented as possible.

centaur-tabs's People

Contributors

alvarogonzalezsotillo avatar black7375 avatar casouri avatar claritystorm avatar compro-prasad avatar czerw avatar duianto avatar ema2159 avatar et2010 avatar ianyepan avatar ibnishak avatar jasonmiu avatar jcs090218 avatar jianingy avatar jixiuf avatar kamilwaheed avatar levindu avatar linktohack avatar manateelazycat avatar nebhrajani-a avatar nickbp avatar nmccarty avatar protesilaos avatar rainstormstudio avatar rileyrg avatar riscy avatar simon-lin avatar xlshiz avatar xwl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

centaur-tabs's Issues

Comparison with existing packages

Hey there!

I came here to learn a bit about the package after seeing the PR to theme it in Zenburn and it looks pretty cool. One thing that's not clear to me, however, is what are the differences between tabbar, awesome-tabs and centaur-tabs, so you might want to add something on the subject to the README. You mentioned that the package started life as a fork of awesome-tags, but I'm curious to hear what was the motivation for the fork and so on.

separate icon for different states

It would be nice to be able to use different icons for different states, e.g. normal, hovered, pressed, as long as different faces for these icons.

second click on tab changes tabbar background color (Solaire Mode)

Note the bg color:
Screenshot from 2019-08-13 09-47-56

I'm clicking *Messages*. Note that bg is lighter now:
Screenshot from 2019-08-13 09-48-15

I'm clicking *Messages* again. Bg restored to previous state
Screenshot from 2019-08-13 09-48-03

If I unfocus Emacs this doesn't happen unless I do consecutive switching between tabs again.

My Centaur tabs config:
https://github.com/andreyorst/dotfiles/blob/dff3996e17a8c70e0e502bdf6d90cff668447536/.emacs.d/init.el#L532-L561

My DOOM Themes config:
https://github.com/andreyorst/dotfiles/blob/dff3996e17a8c70e0e502bdf6d90cff668447536/.emacs.d/init.el#L157-L163

My Solaire Mode config:
https://github.com/andreyorst/dotfiles/blob/dff3996e17a8c70e0e502bdf6d90cff668447536/.emacs.d/init.el#L176-L215

Without Solaire there's no bug. Happens with all DOOM Themes for me. Seems like (solaire-mode-swap-bg) is causing the problem

Hydras get unwanted extra header

I am using hydra and centaur tabs together. When I activate a hydra, the hydra content gets an unwanted line on the header which messes up the layout (see screenshot 1). When I mouse click the blue line, it vanishes and the layout looks like the way it should be. Deactivating centaur tabs fixes the issue. I would like to turn off centaur tabs for hydra windows, but I don't know how to do that. Any help would be appreciated.

Screenshot 1

Screenshot 2

Always selects first group from centaur-tabs-buffer-groups-function

centaur-tabs-buffer-groups-function should return a list of groups but it doesn't help when the list has more than one group. It just considers the first group from the list. My centaur-tabs-buffer-groups-function is:

(defun compro/centaur-tabs-buffer-groups ()
    (let* ((project-root (projectile-project-p))
           (project-name (projectile-project-name))
           (buf (buffer-name))
           (groups
            (-filter
             (lambda (it) (not (null it)))
             (list
              (when (or (string-prefix-p "*sent mail" buf)
                        (string-prefix-p "*notmuch" buf)
                        (string-equal "*unsent mail*" buf))
                "Mail")
              (when (or (buffer-file-name)
                        (eq major-mode 'dired-mode))
                "Files")
              (when (eq major-mode 'helpful-mode)
                "Helpful")
              (when (or (eq major-mode 'telega-chat-mode)
                        (eq major-mode 'telega-root-mode))
                "Telegram")
              (when (string-prefix-p "*" buf)
                "Internal")
              (when (not (null project-root))
                (concat "Project: " project-name))))))
      (when (null groups)
        (push "Unregistered" groups))
      groups))

This will put a file based buffer in two groups: File and Project: <project-name> group. But the function which uses the above function is only based on the first element of the list. So, centaur-tabs-counsel-switch-group is of little use.

Basically, I sometimes want to see a list of open files while sometimes I want to see a list of open files in the current project. There is some bug which doesn't let this happen.

spaceline flicker with 2 or more windows

Thanks for the awesome package!

I encountered an issue:
on emacs27, and spacemacs on develop branch.
When more than one window is open with tabs on, spaceline starts to flicker with every line change. Can be connected to the similar issue that existed in helm with focus?
emacs-helm/helm#1593

Disabling `centaur-tabs-mode` breaks Emacs

Reproduce steps:

  1. Launch Emacs like this:
    emacs -q --eval "(progn (package-initialize) (require 'centaur-tabs))"
    
  2. M-x centaur-tabs-mode RET
    Tabs should appear
  3. M-x centaur-tabs-mode RET
    Tabs should disappear
  4. Try to exit Emacs withC-x C-c or the close button, or change buffer, or call M-x

Every action prints this error message in my case:

funcall: Symbol’s value as variable is void: pl/reverse-pattern

Without Emacs -q the message is different:

funcall: Symbol’s value as variable is void: gnus-widget-reversible-match

and seems that it depends on the configuration and quite random.

I'm using

GNU Emacs 26.2 (build 1, x86_64-redhat-linux-gnu, GTK+ Version 3.24.8) of 2019-04-30
GNU Emacs 26.3 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.10) of 2019-08-29

centaur-tabs + doom-modeline height faces leads to scrollbar dancing madness

Approximate steps to reproduce:

  • Use centaur-tabs and doom-modeline
  • Customize the modeline height faces
  • Open multiple elisp files
  • Vertically split into two windows
  • Switch to the right window
  • Type something
  • Switch tabs
  • Switch back to the left window
  • Type Type Type
  • The cursor will disappear and the left scrollbar will start oscillating in a little dance

I think this is close to a minimal config:

;; GNU Emacs 26.2 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.8)

(require 'package)
(setq package-enable-at-startup nil)
(setq package-archives
      '(("gnu" . "http://elpa.gnu.org/packages/")
        ("melpa-stable" . "https://stable.melpa.org/packages/")
        ("melpa" . "https://melpa.org/packages/")))

(package-initialize)

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))

(eval-when-compile
  (require 'use-package))
(require 'bind-key)

(use-package centaur-tabs
  :ensure t
  :demand
  :bind
  ([(C-S-iso-lefttab)] . centaur-tabs-backward)
  ([(control tab)] . centaur-tabs-forward)
  :config
  (centaur-tabs-mode t))


(use-package doom-modeline
  :ensure t
  :pin melpa-stable
  :hook (after-init . doom-modeline-mode)
  :config
  (set-face-attribute 'mode-line nil :height 105)
  (set-face-attribute 'mode-line-inactive nil :height 105))

weird text flicker on tabline

when using Magit I some times see regular text appear for a split second on the tabline. Can't find reproducible steps yet though.

consider making non file buffers that show the same projectile-project-root group with the associated project by default

Example in cider clojure repls should group with the project ideally. This can be configured in a custom function in theory but ideally but when grouping buffers by project one would expect such buffers to be grouped by default as they are as much part of the project as the files.

If utilizing this method of grouping one ends up frequently switching between groups without reason.

Disable tabs when only one tab is present

Hi ema2159
I really like centaur-tabs.

Using other apps I've mostly used the option to only show tabs if there is more than one.
I was thinking if you'd consider adding this setting.

Cheers

Change centaur-tabs-default :background color

Hi all,

First thanks to ema2159 for sharing and working with centaur-tabs.

I am new to emacs, trying to customize tab background color but I am failing. Can anyone help me?

The part I am trying to change is the tab background color (black). I want it white.

Screen Shot 2019-10-01 at 9 20 54 PM

Here is my config. bg1 is #ffffff and bg2 is #f0f0f7

;; Centaur-tabs
               (centaur-tabs-default :background ,bg1 :foreground ,black1 :box nil)
               (centaur-tabs-selected :background ,bg1 :foreground ,black1 :box nil)
               (centaur-tabs-unselected :background ,bg2 :foreground ,black2 :box nil)
               (centaur-tabs-selected-modified :background ,bg1 :foreground ,orange1 :box nil)
               (centaur-tabs-unselected-modified :background ,bg2 :foreground ,orange1 :box nil)
               (centaur-tabs-active-bar-face :background ,yellow1 :box nil)
               (centaur-tabs-modified-marker-selected :inherit 'centaur-tabs-selected-modified :foreground ,yellow1 :box nil)
               (centaur-tabs-modified-marker-unselected :inherit 'centaur-tabs-unselected-modified :foreground ,yellow1 :box nil)

I think is it same case on minimap window.

Screen Shot 2019-10-01 at 9 09 51 PM

Thanks

options for sorted tabs

I'll admit that this is an attempt to replicate the -- possibly quirky -- behavior I like from a circa 2003 copy of tabbar.

I know the more typical modern behavior is for tabs to be ordered by whenever you opened them. Would it be possible to have a hook/option to keep the tabs lexographically sorted?

all tabs in one group possible?

Is it possible to display all tabs from different directories/projects in one group? I'm not using projectile, and have a custom function for project.el to find roots, but I mainly use it for eglot.

if I'm working on file on a different project it creates new group for it which I don't like, because this hides all other tabs. Switching groups is just an additional action for me and I would like to avoid it until it's really necessary.

Related: #15

centaur-tabs-close-button nil not working properly

There's some issue when (setq centaur-tabs-close-button nil).

Steps:

  1. emacs -q
  2. Load centaur tabs and dependencies
  3. M-x centar-tabs-mode
    All is fine thus far.
  4. (setq centaur-tabs-close-button nil)
  5. M-x centar-tabs-mode (disable centaur tabs)
  6. M-x centar-tabs-mode (re-enable centaur tabs)
    Tab bar is there but has no tabs.

Set-bar 'over needs multiple init file reloads

Hi @ema2159 thanks for adding the over-bar feature so quickly! It really resembles the firefox theme and it's looking super cool.

However, I noticed that I had to load the config file more than once to get the over-bar working, whereas if I set it to the left it needs only one reload. Perhaps it's the way I'm organizing my init file, or could it be an ordering issue in your latest commit? Here's my snippet:

  (use-package centaur-tabs
    :demand
    :config
    (centaur-tabs-mode)
    (setq centaur-tabs-set-modified-marker t
          centaur-tabs-modified-marker "●"
          centaur-tabs-cycle-scope 'tabs
          centaur-tabs-height 32
          centaur-tabs-set-bar 'over))

ability to tab "out" of "hidden" buffers

I'll admit that this is an attempt to replicate the -- possibly quirky -- behavior I like from a circa 2003 copy of tabbar.

I've defined centaur-tabs-hide-tab to hide several buffers, such as the scratch buffer or messages. This keeps centaur-tabs-forward/backward from goinginto those buffers (yeah!). However, I'd still like to be able to tab out of those buffers. That is centaur-tabs-forward from the scratch buffer would take me to the first buffer that isn't hidden from centaur-tabs. Right now, that command appears to do nothing in a hidden buffer

tabbar-buffer-list-function equivalent

1: Thanks for this package \o/

2:
Is there an equivalent to the variable tabbar-buffer-list-function ?
I would like to exclude some buffers by their name:

example in tabber to exclude internal, magit and TAGS buffers:

(setq tabbar-buffer-list-function
       (lambda ()
           (remove-if
            (lambda(buffer)
              (or (string-match-p "TAGS" (buffer-name buffer))
                  (string-match-p "^magit.*" (buffer-name buffer))
                  (find (aref (buffer-name buffer) 0) " *" )))
            (buffer-list))))

Regards

Button/ability to kill window?

Sometimes when I close a buffer in a multi-window setup I also want to kill that window. If I'm doing it on a keyboard it's easy as C-x k RET C-x 0. But when I'm interacting with mouse by using tabs, there's a way to kill a buffer with the close button, but no way to kill the window with the tabline. Maybe it is good idea to add a button that will kill the window?

Or as another solution the window can be killed if there's no tabs left in the group, so instead of switching the active group, the window will be killed automatically, like in Atom? Though this may involve having separate groups for separate windows.

Generalization of buffer groups

Hello, I'm quite interested in this package since it has appeared on Emacs Reddit.

I've noticed that buffer groups are the most central to this package and that tabs are just a way to present the buffer groups, To name a few, the following packages are well-known alternatives that implement what I call buffer groups:

By adding a strong support for buffer groups like those packages, I think centaur-tabs can potentially constitute an integral part of Emacs workflow. However, it may be beyond the scope of the package... Otherwise, it may be a good idea to support an external buffer group manager through a modular design. That is, you can define buffer groups in somewhere else (or another package) and let centaur-tabs present tabs based on the groups. It may help reduce the code in this package and focus on presentation.

What do you think?

turning on modified marker crashes emacs

basically, with (setq centaur-tabs-set-modified-marker t) in my init.el, typing anything into a buffer (ie, modifying it) crashes emacs entirely. Turning off the modified marker seems to fix it.
Emacs version 25.2, centaur-tabs version 20190711.520

*Minibuf-1* started to appear with other buffers

I'm using this function to create groups:

(defun centaur-tabs-buffer-groups ()
  "Use as few groups as possible."
  (list (cond ((string-equal "*" (substring (buffer-name) 0 1))
               (cond ((string-match-p "eglot" (buffer-name)) "Eglot")
                     ((or (string-match-p "geiser" (buffer-name))
                          (string-match-p "repl \\*" (buffer-name))) "Geiser")
                     (t "Tools")))
              ((string-match-p "magit" (buffer-name)) "Magit")
              (t "Default"))))

Whenever I open M-x or using phi-search this tab appears:
image

But only in single window:
image

I thought that first cond branch should put this buffer into the "Tools" group, but it seems that with latest updates, that brought multiple buffers in multiple groups I need to handle this thing differently?

no tabs when opeing file from treemacs buffer or via command line

steps to reproduce:

emacs -q --eval "(progn
                   (package-initialize)
                   (require 'centaur-tabs)
                   (require 'treemacs)
                   (treemacs)
                   (centaur-tabs-mode t))" test_file

Outcome:
image

Expected:
image

removing (treemacs) call makes tabs appear at launch.

Also can be observed with these steps:

  1. launch Emacs like so:
    emacs -q --eval "(progn
                       (package-initialize)
                       (require 'centaur-tabs)
                       (require 'treemacs)
                       (treemacs)
                       (centaur-tabs-mode t))"
    
    (also observe that tabline is empty for *messages* and *scratch* buffers until first click)
  2. While cursor is inside treemacs window press C-x C-f test_file RET

Outcome: No tabs in new buffer
Expected: Tabs in test_file buffer.

Happens on

GNU Emacs 26.2 (build 1, x86_64-redhat-linux-gnu, GTK+ Version 3.24.8) of 2019-04-30
GNU Emacs 26.3 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.10) of 2019-08-29

extra space after close button

there's a space before file an icon in the tab, but no space after close and modified buttons. I can add it manually though:

(setq centaur-tabs-set-modified-marker t
      centaur-tabs-modified-marker ""
      centaur-tabs-close-button (concat centaur-tabs-close-button " ")

but it adds underline on that space when hovering:

image

I guess this can also be solved with different face settings for hovered state, but I think there should be some space after close button in the first place

Tabs are unwantingly automatically reordered

If I switch focus of buffers (either by C-x b or clicking on the tab bar), the order of the tab bars will unpredictably scramble, especially when the switched-from tab and the switched-to tab aren't next to each other.

To reproduce the problem, open four tabs in the same grouping, say:

| index.html | app.js | sw1.jsx | sw2.jsx |

and I have my current buffer focus on the first tab (index.html). As soon as I click the last tab (sw2.jsx), the order of the tabs becomes:

| app.js | sw1.jsx | index.html | sw2.jsx |

Then I click on the second tab (sw1.jsx) and the order becomes:

| app.js | sw1.jsx | sw2.jsx | index.html |

I'm not sure what's causing this issue, but I'm sure most users would expect the four tabs to stay in their same position, no matter the change of focus.

P.s. I'm suspecting this is the behavior of Emacs ordering the buffers internally since Centaur-Tabs does not keep track of the buffers with its own index list?

Thanks for your time, let me know if you need more details!

Ability to customize mouse bindings

Hi, I'd like to be able to customize the mouse bindings: particularly, I'd like to make mouse-2 (the middle mouse button) kill the currently selected tab but there doesn't seem to be any obvious way to do that as is.

Tabs dissapear in Geiser REPL

When starting Geiser REPL for Racket, tabs are active until the REPL fully started:

image

As the REPL starts there's no tabs anymore:
image

Calling centaur-tabs-local-mode in this window for the first time displays that the mode was enabled, but tabs do not appear. Calling it second time says that mode was disabled and tabs appear as they should. Why can tabs disappear during REPL startup?

Clicking on tab opens in other window

Reproduction steps

  1. Open two files in the same project so that you have two tabs
  2. C-x 3 to split into two halves
  3. Click on the other tab in other(currently inactive) window

What I was expecting

Buffer opens in the other window

Unexpected behaviour

Buffer opens in the same active window.

centaur-tabs-forward-tab behavior

IMHO !!
I think centaur-tabs-forward-tab and centaur-tabs-backward-tab should stay in the same tab-set.
it is disturbing to change the group of tabs without using centaur-tabs-forward-group.

Regards

Change tabs location

Just read the README and I guess there weren't any feature to change tabs location...
I also didn't find any guide/wiki or issues about this matter so I thought it's fine to open one.
Sorry if it's duplicated...
Some possible options can be: Above status-bar, Below status-bar, top, bottom, and etc...
I think the concept is pretty clear and doesn't need any further explanations.

{Sorry for bad English and not having enough info about how to open issues and stuff}
Thanks for your time and effort!

uniquify settings unconditionally overridden

https://github.com/ema2159/centaur-tabs/blame/master/centaur-tabs.el#L1977..L1982

;; Uniquify tab name when open multiple buffers with same filename.
(setq uniquify-separator "/")
(setq uniquify-buffer-name-style 'post-forward-angle-brackets)
(setq uniquify-after-kill-buffer-p t)

These settings seem fine, but I'm not sure why centaur-tabs needs to override them. If a user wants a different uniquify-buffer-name-style, is it intended that they should have to use (eval-after-load 'centaur-tabs-mode?

Centaur-tabs-set-bar position options?

Many modern editors/IDEs like to have the selected tab indicator to be at the bottom or top of the tab (instead of the left). Is there any plan to implement this option?

P.s. Love this package, well done mate!

Closing all buffers removes tabs from *scratch*

Previously if default *scratch* and *messages* buffers were closed (in this order) a new *scratch* buffer appeared with tabs. Now this visual glitch appears, and after that there's no tabs in *scratch* buffer:

image

Can't reproduce with emacs -q. Will try to trim down issue to some configuration

Possible to configure the fonts?

As titled. Since I'm using a proportional San Francisco font in Treemacs, I'd love to have the variable pitch experience in tabs as well. Is there a one-liner (a master default face) that controls the font behaviour of Centaur Tabs?

Cheers in advance!

Disable tabs for *Completion* buffer

Is it just me, or do other people think the Centaur tabs make the *Completion* buffer much less useful? When it's enabled, there's only one line of values, and the rest is the tabs and this boilerplate:

Click on a completion to select it.
In this buffer, type RET to select the completion near point.

Possible completions are:

I think the only fix needed for this is to edit https://github.com/ema2159/centaur-tabs#disable-centaur-tabs-in-selected-buffers so it recommends to users to use this:

(add-hook 'completion-list-mode-hook 'centaur-tabs-local-mode)

[Suggest] icon colors

It's better make the color of the buffer icons on inactive tabs "gray" (same as the buffer names). This can be a customization for users.

[discussion] Buffer-Tab relationship semantics

I had thought about relationship between buffers and tabs, and came to the conclusion, that buffer != tab. Or at least the relationship is not 1 to 1.

In Emacs, everything we interact with is a buffer. Buffer is a data structure that can hold anything, but primarily holds text information. It may seem natural to tie tabs to buffers as 1 to 1 relationship, but after giving it some thought, I've realized, that tabs are not meant to be buffers. Tabs are interface to interact with meaningful set of buffers that can be manged from graphical interface. Current grouping semantics are more a hack over the problem of not displaying tabs for buffers that we not need to see. Therefore I think that relationship between buffers and tabs should not be as tight. Tabs are merely a graphical interface, while buffers are data structure, so I think this can be changed to work like in other GUI editors out there.

I've thought about some set of rules on how we can manage tabs, and here's what I've got:

  1. Buffer can have as many tabs as long as these conditions are true:
    1. Buffer is not marked as ignored
    2. Buffer can have only 1 tab per window.
  2. Buffer can exist without tab, but tab can not exist without buffer. Therefore such buffer killing semantics apply:
    1. Buffer that do not have tabs cannot be killed by tab plugin. ignored buffers must be managed by existing Emacs functions.
    2. Buffer that has more than 1 tab cannot be killed by tab plugin.
    3. Closing tab must kill buffer if there is no other tabs of this buffer exist.
  3. Window can have as many tabs as long as these conditions are true:
    1. Window is not displaying ignored buffer;
    2. Window is not marked as dedicated;
  4. Window can exist without tabs, but tabs can not exist without
    window. Therefore such window killing semantics apply:
    1. Window that has more than 1 tab cannot be killed by tab plugin;
    2. Closing tab must kill window if there is no other tabs left in the window;
    3. Window that has no tabs cannot be killed by tab plugin.
    4. Manually killing window must transfer all of its tabs to another window.
    5. Window that no longer applies to conditions mentioned in 3. automatically transfers its tabs to another window. (E.g. making window dedicated to a buffer, or switching to ignored buffer disables tabs for current window.)

So in implementation could be as a some sort of a tree structure that holds buffer name and its properties. For example, a json structure:

{
    "buffers": [
        {
            "id": "buffer-id",
            "ignored": false,
            "tabs": [
                {
                    "window": {
                        "id": "window-id",
                        "dedicated": false
                    }
                },
                {
                    "window": {
                        "id": "window-id",
                        "dedicated": false
                    }
                }
            ]
        },
        {
            "id": "buffer-id",
            "ignored": true,
            "tabs": []
        },
    ]
}

So the thing is that if some buffer Buffer1 exists and doesn't marked as ignored a tab should be displayed in a #<window A on Buffer1> where the buffer is displayed. Currently centaur-tabs works like this. If we have Buffer1 displayed in secondary window #<window B on Buffer1> a tab should be displayed in both windows now. Again, centaur-tabs works the same. Now if we try to close a tab in #<window B on Buffer1>, a rule number 2.ii evaluates. Since buffer has 2 tabs both in #<window A on Buffer1> and #<window B on Buffer1> it cannot be killed. So the tab is being killed. After that a windowing rule 4.ii must be evaluated. Since #<window B on Buffer1> has no tabs to display it must be deleted, so only one window #<window A on Buffer1> with Buffer1 tab is displayed. The data structure above doesn't include information about window in buffer field itself because the data structure should inspected only after window is tested for dedicated. Yet the information about some window displaying a dedicated buffer that has other tabs somewhere in other windows can be handy.

The other rules can be applied to situations when we display several tabs and make window dedicated in the same way as described in previous paragraph. I believe this will bring more consistent tab interface to Emacs which represents real tabs in GUI editors and other tab based environments. I want to hear your thought on these approaches.

centaur-tabs-select-visible-tab is not working with key sequences more than 2 keystrokes

If bind the command "centaur-tabs-select-visible-tab()" with a key sequence more then 2 keystrokes,
such as
(dotimes (n 10) (global-set-key (kbd (format "C-c %d" n)) 'centaur-tabs-select-visible-tab))
Execute the command with key sequence C-c 1 gives:
centaur-tabs-select-visible-nth-tab: Wrong type argument: stringp, nil

Key sequences with only 2 keystrokes have no problem.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.