Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
git rm -rf . --quiet

# Restore plugin files from dev
git checkout dev -- plugin/ README.md LICENSE
git checkout dev -- plugin/ doc/ README.md LICENSE

# Only commit if there are changes
if git diff --cached --quiet; then
Expand Down
66 changes: 51 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,39 +1,75 @@
# tabs.vim

A lightweight Vim plugin that replaces the tabline with a clean mode-aware bar: tabs on the left, current mode pill on the right. Also provides terminal toggles, tab/window management, and file-drop support.
A lightweight Vim plugin that replaces the native tabline with a clean, mode-aware bar: numbered tabs on the left, a color-coded mode pill on the right. Also handles split terminals, tab/window management, and file-drop support.

## Requirements

- Vim 8.2+ or Neovim 0.7+
- Optional: [junegunn/fzf.vim](https://github.com/junegunn/fzf.vim) for file-picker integration

## Installation

```vim
Plug 'jesse23/tabs.vim'
```

## Features

**Tabline** — always-visible bar showing open tabs (with modified indicator `*`) and a color-coded mode pill (Normal / Insert / Visual / Replace / Command / Terminal).
## Keybindings

**Tab navigation**
- `<Tab>` / `<S-Tab>` — next / previous tab
- `<leader>1`–`<leader>9` — jump to tab by number
- `<leader>wt` — new tab
- `<leader>x` / `<leader>X` — close window / close all other tabs

**Split terminals**
- `<leader>h` / `<leader>ts` — toggle horizontal split terminal (15 lines)
- `<leader>tv` — toggle vertical split terminal (80 cols)
- `<leader>tt` — open terminal in a new tab
- `<C-]>` — enter terminal mode; `<Esc>` or `<C-]>` — exit terminal mode
**Tab management**
- `<leader>wt` — new empty tab
- `<leader>ft` — open file in new tab via fzf
- `<leader>x` / `<leader>X` — close window / close all other tabs
- `gF` — open file under cursor in new tab

**Window & buffer ops**
**Splits & windows**
- `<leader>ws` / `<leader>wv` — horizontal / vertical split
- `<leader>wm` — maximize (close other windows)

**Buffer ops**
- `<leader>wr` — rename current buffer
- `<leader>fy` — copy file path to clipboard
- `gF` — open file under cursor in new tab

**File drop** — drag a file from Finder onto the terminal; it opens in a new tab (requires bracketed-paste support, e.g. iTerm2).
**Terminals**
- `<leader>h` / `<leader>ts` — toggle horizontal split terminal (15 lines)
- `<leader>tv` — toggle vertical split terminal (80 cols)
- `<leader>tt` — open terminal in new tab
- `<C-]>` — enter terminal mode; `<Esc>` or `<C-]>` — exit

**File drop** — drag a file from Finder onto the terminal to open it in a new tab (requires bracketed-paste, e.g. iTerm2).

## Configuration

### Mode style

Controls what the tabline shows:

```vim
" all — mode-driven selected tab + mode pill (default)
" tabs — mode-driven selected tab, no pill
" mode — mode pill, fixed selected-tab color
let g:tabs_vim_mode_style = 'all'
```

### Colors

Override any color via `g:tabs_vim_colors`. Each value is `[guifg, guibg, ctermfg, ctermbg]`:

```vim
" Partial override — unspecified keys keep Dracula defaults
let g:tabs_vim_colors = {
\ 'normal': ['#282828', '#d79921', 235, 172],
\ 'insert': ['#282828', '#b8bb26', 235, 142],
\ }
```

Mode keys: `normal`, `insert`, `visual`, `replace`, `command`, `terminal`
Chrome keys: `tabline`, `tabline_sel`, `tabline_fill`

**FZF integration** — `<leader>ft` opens a file in a new tab via fzf (requires `junegunn/fzf.vim`).
See `:help tabs.vim` for the full reference.

## License

Expand Down
158 changes: 158 additions & 0 deletions doc/tabs.vim.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
*tabs.vim.txt* Mode-aware tabline with tab/terminal management

==============================================================================
CONTENTS *tabs.vim-contents*

1. Introduction ......................... |tabs.vim-intro|
2. Requirements ......................... |tabs.vim-requirements|
3. Installation ......................... |tabs.vim-installation|
4. Tabline .............................. |tabs.vim-tabline|
5. Keybindings .......................... |tabs.vim-keybindings|
6. Configuration ........................ |tabs.vim-config|
6.1 Mode Style ....................... |tabs.vim-mode-style|
6.2 Colors ........................... |tabs.vim-colors|
7. License .............................. |tabs.vim-license|

==============================================================================
1. Introduction *tabs.vim-intro*

tabs.vim replaces Vim's native tabline with a clean, mode-aware bar: open
tabs on the left, a color-coded mode pill on the right. It also provides
keybindings for tab/window management, split terminals, and file-drop support.

==============================================================================
2. Requirements *tabs.vim-requirements*

- Vim 8.2+ or Neovim 0.7+
- Optional: junegunn/fzf.vim (for |<leader>ft|)

==============================================================================
3. Installation *tabs.vim-installation*

With vim-plug: >
Plug 'jesse23/tabs.vim'
<
With lazy.nvim: >
{ 'jesse23/tabs.vim' }
<
==============================================================================
4. Tabline *tabs.vim-tabline*

The tabline shows:
- Left side: numbered open tabs; active tab highlighted by current mode color;
modified buffers marked with ` *`
- Right side: mode pill showing the current Vim mode (when enabled)

Mode labels~
N Normal
I Insert
V Visual / V·LINE / V·BLOCK
R Replace
C Command
T Terminal

==============================================================================
5. Keybindings *tabs.vim-keybindings*

Tab navigation~
<Tab> Next tab
<S-Tab> Previous tab
<leader>1-9 Jump to tab 1–9

Tab management~
<leader>wt New empty tab
<leader>ft Open file in new tab via fzf (requires fzf.vim)
<leader>x Close window (or toggle terminal; quit prompt if last window)
<leader>X Close all tabs except current
gF Open file under cursor in new tab

Window splits~
<leader>ws Horizontal split
<leader>wv Vertical split
<leader>wm Maximize (close other windows)

Buffer operations~
<leader>wr Rename current buffer
<leader>fy Copy full file path to clipboard

Terminal~
<leader>h Toggle horizontal split terminal (15 lines)
<leader>ts Toggle horizontal split terminal (alias)
<leader>tv Toggle vertical split terminal (80 cols)
<leader>tt Open terminal in new tab
<C-]> Enter terminal mode (normal→terminal)
<Esc> / <C-]> Exit terminal mode

File drop~
Drag a file from Finder/Explorer onto the terminal — it opens in a new tab.
Requires bracketed-paste support (e.g. iTerm2).

==============================================================================
6. Configuration *tabs.vim-config*

------------------------------------------------------------------------------
6.1 Mode Style *tabs.vim-mode-style*
*g:tabs_vim_mode_style*

Controls how mode information is presented in the tab bar.

Default: `'all'` >
let g:tabs_vim_mode_style = 'all'
<
Values:

`all` Selected-tab color is mode-driven; mode pill is shown. (default)
`tabs` Selected-tab color is mode-driven; mode pill is hidden.
`mode` Mode pill is shown; selected-tab color is fixed to |TabLineSel|.

Unknown values fall back to `'all'`.

------------------------------------------------------------------------------
6.2 Colors *tabs.vim-colors*
*g:tabs_vim_colors*

Override any tab bar color via a dict. Each value is a four-element list: >
[guifg, guibg, ctermfg, ctermbg]
<
Mode color keys (affect mode pill and, in `all`/`tabs` style, selected tab):
`normal` Normal mode
`insert` Insert mode
`visual` Visual mode
`replace` Replace mode
`command` Command mode
`terminal` Terminal mode

Tab bar chrome keys:
`tabline` Inactive tabs and separators (→ |TabLine|)
`tabline_sel` Standard tab selection; selected-tab in `mode` style (→ |TabLineSel|)
`tabline_fill` Empty tabline fill area (→ |TabLineFill|)

The plugin owns all TabLine* highlight groups — no separate `hi TabLine*`
declarations are needed in your vimrc.

Full override example (Dracula defaults): >
let g:tabs_vim_colors = {
\ 'normal': ['#282a36', '#bd93f9', 235, 141],
\ 'insert': ['#282a36', '#50fa7b', 235, 84 ],
\ 'visual': ['#282a36', '#ffb86c', 235, 215],
\ 'replace': ['#282a36', '#ff5555', 235, 203],
\ 'command': ['#282a36', '#bd93f9', 235, 141],
\ 'terminal': ['#282a36', '#8be9fd', 235, 117],
\ 'tabline': ['#6272a4', 'NONE', 61, 'NONE'],
\ 'tabline_sel': ['#bd93f9', 'NONE', 141, 'NONE'],
\ 'tabline_fill': ['#6272a4', 'NONE', 61, 'NONE'],
\ }
<
Partial override (only change some modes; rest keep Dracula defaults): >
let g:tabs_vim_colors = {
\ 'normal': ['#282828', '#d79921', 235, 172],
\ 'insert': ['#282828', '#b8bb26', 235, 142],
\ }
<
==============================================================================
7. License *tabs.vim-license*

MIT License. See LICENSE in the repository root.

==============================================================================
vim:tw=78:ts=8:ft=help:norl:
13 changes: 13 additions & 0 deletions doc/tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
g:tabs_vim_colors tabs.vim.txt /*g:tabs_vim_colors*
g:tabs_vim_mode_style tabs.vim.txt /*g:tabs_vim_mode_style*
tabs.vim-colors tabs.vim.txt /*tabs.vim-colors*
tabs.vim-config tabs.vim.txt /*tabs.vim-config*
tabs.vim-contents tabs.vim.txt /*tabs.vim-contents*
tabs.vim-installation tabs.vim.txt /*tabs.vim-installation*
tabs.vim-intro tabs.vim.txt /*tabs.vim-intro*
tabs.vim-keybindings tabs.vim.txt /*tabs.vim-keybindings*
tabs.vim-license tabs.vim.txt /*tabs.vim-license*
tabs.vim-mode-style tabs.vim.txt /*tabs.vim-mode-style*
tabs.vim-requirements tabs.vim.txt /*tabs.vim-requirements*
tabs.vim-tabline tabs.vim.txt /*tabs.vim-tabline*
tabs.vim.txt tabs.vim.txt /*tabs.vim.txt*
59 changes: 59 additions & 0 deletions docs/adrs/003.tabs-vim.mode-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# 003. Mode Style Strategy

**SPEC:** tabs.vim
**Status:** Accepted
**Last Updated:** 2026-04-04

---

## Decision

Add a new enum option `g:tabs_vim_mode_style` to control how mode information is presented in the tab bar.

**Allowed values:**
- `all` *(default)*
- `tabs`
- `mode`

`mode` is chosen as the concise mode-indicator-only value name.

### Semantics

| Value | Selected tab color | Top-right mode pill |
|-------|--------------------|----------------------|
| `all` | Mode-driven (`TabsVim_Sel*`) | Visible |
| `tabs` | Mode-driven (`TabsVim_Sel*`) | Hidden |
| `mode` | Fixed from `tabline_sel` | Visible |

## Context

Current behavior couples two signals:
1. selected-tab color changes with mode
2. top-right mode pill is shown

Some users want only one of those signals depending on visual preference:
- Keep mode-aware selected-tab color but remove pill clutter (`tabs`)
- Keep pill but stabilize selected-tab color to the standard tab selection style (`mode`)

The option must preserve existing visuals by default and avoid breaking current users.

## Considered Options

| Option | Pros | Cons |
|--------|------|------|
| **`all` / `tabs` / `mode` enum** *(chosen)* | Explicit, easy to reason about, backward-compatible default | Adds one more config axis |
| Boolean toggle (`show_mode_pill`) only | Very simple | Cannot express "mode-only" behavior |
| Two independent booleans (`show_mode_pill`, `mode_driven_selected_tab`) | Flexible | Invalid combinations and higher complexity |

`full/tab/badge` and `notation` were considered, but `all/tabs/mode` are shorter and map directly to behavior.

## Consequences

- Backward compatibility: `all` remains the default and preserves current behavior.
- The color contract gains one additional interpretation rule:
- In `mode`, selected-tab color is taken from `tabline_sel`.
- Documentation and examples must show all three modes to reduce ambiguity.
- Fallback rules are explicit:
- Unknown `g:tabs_vim_mode_style` values fall back to `all`.
- Missing `g:tabs_vim_colors` keys use built-in defaults.
- Future extensions can add values without breaking existing configs.
27 changes: 24 additions & 3 deletions docs/specs/tabs.vim.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ Tabs plugin plays well with others (fzf, Fern, vim-fugitive). It doesn't reimple
All keybindings are configurable. Users can disable features (e.g., if they don't use tabs) without source code changes.

**4. Integrated Theming**
Dracula color scheme is the built-in default; tab bar includes mode indicator (Normal/Insert/Visual/Replace/Command/Terminal) with context-aware highlighting. Users may override any or all mode colors via `g:tabs_vim_colors`.
Dracula color scheme is the built-in default; the tab bar can show a mode pill (Normal/Insert/Visual/Replace/Command/Terminal) and can style the selected tab by mode, depending on `g:tabs_vim_mode_style`. Users may override any or all mode colors via `g:tabs_vim_colors`.

**5. Vimrc Integration Boundary**
The plugin owns all behavior it directly triggers. Integration with third-party plugins (vim-flog, vim-fugitive, diff buffers) — for example, binding `q` to `:tabclose` in their buffer types — is intentionally left to the user's vimrc. These bindings are tab-aware but depend on optional external plugins; pulling them into tabs.vim would introduce undeclared dependencies and couple the plugin to unrelated workflows.
Expand All @@ -140,13 +140,32 @@ All tab bar colors are configurable via the `g:tabs_vim_colors` global dict. Eac

The plugin owns the full tab bar and applies all highlight groups itself — no separate `hi TabLine*` declarations are needed in the user's vimrc.

In the plugin-managed tab bar, the selected tab is styled by the active mode color via mode-specific selected-tab groups (`TabsVim_SelNormal`, `TabsVim_SelInsert`, etc.). Changing `normal`, `insert`, `visual`, `replace`, `command`, or `terminal` therefore changes selected-tab appearance for that mode.
In `all` and `tabs` mode, the selected tab is styled by the active mode color via mode-specific selected-tab groups (`TabsVim_SelNormal`, `TabsVim_SelInsert`, etc.). In `mode`, selected-tab styling comes from `tabline_sel` instead. Changing `normal`, `insert`, `visual`, `replace`, `command`, or `terminal` therefore changes selected-tab appearance in `all` and `tabs` mode.

`tabline`, `tabline_sel`, and `tabline_fill` map to Vim's standard `TabLine`, `TabLineSel`, and `TabLineFill` groups. `tabline_sel` is retained for compatibility/interoperability with non-plugin or default tabline contexts, but it does not control selected-tab styling inside `TabsVim_Line()`.
`tabline`, `tabline_sel`, and `tabline_fill` map to Vim's standard `TabLine`, `TabLineSel`, and `TabLineFill` groups. `tabline_sel` does not control selected-tab styling in `all` or `tabs` mode; in `mode` mode, `tabline_sel` is the selected-tab style source.

**Mode color keys:** `normal`, `insert`, `visual`, `replace`, `command`, `terminal`
**Tab bar chrome keys:** `tabline`, `tabline_sel`, `tabline_fill`

### Mode Style Contract

Mode style is controlled by `g:tabs_vim_mode_style`.

```vim
" default
let g:tabs_vim_mode_style = 'all'
```

Allowed values:

| Value | Behavior |
|-------|----------|
| `all` | Current behavior: selected-tab color is mode-driven and top-right mode pill is shown |
| `tabs` | Mode-driven selected-tab color remains, but top-right mode pill is hidden |
| `mode` | Top-right mode pill is shown; selected-tab color is fixed to `tabline_sel` |

Unknown values should fall back to `all` for backward compatibility.

**Default (Dracula palette):**

```vim
Expand Down Expand Up @@ -220,6 +239,7 @@ let g:tabs_vim_colors = {
| **Tab Creation** | Create new tab with `<leader>wt`, via file picker with `<leader>ft` | — | ✅ |
| **Tab Closing** | Close current tab or all but current with `<leader>x` / `<leader>X` | — | ✅ |
| **Tab Appearance** | Dracula default theme; user-configurable colors via `g:tabs_vim_colors` | ADR-002 | ✅ |
| **Mode Style Variants** | `g:tabs_vim_mode_style` supports `all` / `tabs` / `mode` display strategies | ADR-003 | ⬜ |
| **Terminal in Tabs** | Toggle split terminals and spawn tab terminals (`<leader>h/ts/tv/tt`) | — | ✅ |
| **File Tree Integration** | Open files in tabs from Fern file browser (`t` key) | — | ⬜ |
| **Git Integration** | Open git-related output (diffs, logs) in tabs | — | ⬜ |
Expand Down Expand Up @@ -248,3 +268,4 @@ None yet.
| 2026-04-03 | Initial SPEC: navigation, creation, theming |
| 2026-04-04 | Extend color config: plugin now owns TabLine/TabLineSel/TabLineFill via `tabline`, `tabline_sel`, `tabline_fill` keys |
| 2026-04-04 | Add Vimrc Integration Boundary pattern; mark completed features; align Features table to template |
| 2026-04-04 | Rename to `g:tabs_vim_mode_style` enum (`all` / `tabs` / `mode`) with `all` as default |
Loading
Loading