├── .github └── workflows │ └── test.yml ├── .gitignore ├── Flavorfile.lock ├── Gemfile ├── README.md ├── autoload ├── crystalline.vim └── crystalline │ └── theme │ ├── ayu.vim │ ├── badwolf.vim │ ├── default.vim │ ├── dracula.vim │ ├── gruvbox.vim │ ├── hybrid.vim │ ├── iceberg.vim │ ├── jellybeans.vim │ ├── molokai.vim │ ├── nord.vim │ ├── onedark.vim │ ├── onehalfdark.vim │ ├── onehalflight.vim │ ├── papercolor.vim │ ├── shadesofpurple.vim │ └── solarized.vim ├── doc └── crystalline.txt ├── examples └── neovim_lua_examples.md ├── legacy └── autoload │ └── crystalline.vim ├── lua └── crystalline.lua ├── nvim └── autoload │ └── crystalline.vim ├── plugin └── crystalline.vim ├── t └── crystalline.vim └── vim9 └── autoload └── crystalline.vim /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: "test status" 2 | on: 3 | - "push" 4 | jobs: 5 | test: 6 | runs-on: "ubuntu-latest" 7 | strategy: 8 | matrix: 9 | include: 10 | - vim_type: "vim" 11 | vim_version: "v8.0.1850" 12 | - vim_type: "vim" 13 | vim_version: "head" 14 | - vim_type: "neovim" 15 | vim_version: "head" 16 | steps: 17 | - name: "checkout" 18 | uses: "actions/checkout@v3" 19 | with: 20 | fetch-depth: 1 21 | - id: "vim" 22 | name: "install ${{ matrix.vim_type }}" 23 | uses: "thinca/action-setup-vim@v1" 24 | with: 25 | vim_version: "${{ matrix.vim_version }}" 26 | vim_type: "${{ matrix.vim_type }}" 27 | download: "available" 28 | - name: "install ruby" 29 | uses: "ruby/setup-ruby@v1" 30 | with: 31 | ruby-version: "3.0" 32 | bundler-cache: true 33 | - name: "run tests" 34 | env: 35 | VSPEC_VIM: "${{ steps.vim.outputs.executable }}" 36 | run: "bundle exec vim-flavor test" 37 | lint: 38 | runs-on: "ubuntu-latest" 39 | steps: 40 | - name: "checkout" 41 | uses: "actions/checkout@v3" 42 | - uses: "actions/setup-python@v4" 43 | with: 44 | python-version: "3.x" 45 | - name: "run vint" 46 | run: | 47 | sudo python3 -m pip install vim-vint 48 | rm -rf t/ 49 | vint --color plugin autoload legacy 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | tags 2 | .vim-flavor 3 | Gemfile.lock 4 | VimFlavor.lock 5 | -------------------------------------------------------------------------------- /Flavorfile.lock: -------------------------------------------------------------------------------- 1 | kana/vim-vspec (v1.9.2) 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'vim-flavor', '4.0.2' 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-crystalline 2 | 3 | [![test status](https://github.com/rbong/vim-crystalline/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/rbong/vim-crystalline/actions/workflows/test.yml) 4 | 5 | Want a nice statusline in Vim? 6 | Other statusline plugins too [slow](https://github.com/rbong/vim-crystalline/wiki/Performance-Comparison) 7 | and [uncustomizable](https://github.com/rbong/vim-crystalline/wiki/Configuration-Comparison)? 8 | `vim-crystalline` is for you. 9 | 10 | `vim-crystalline` lets you build your own statusline and tabline in a vanilla Vim style. 11 | 12 | ## Obligatory Colorful Theme Screenshots 13 | 14 | **default** 15 | 16 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/default.png) 17 | 18 | **ayu (dark)** 19 | 20 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/ayu_dark.png) 21 | 22 | **ayu (light)** 23 | 24 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/ayu_light.png) 25 | 26 | **badwolf** 27 | 28 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/badwolf.png) 29 | 30 | **dracula** 31 | 32 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/dracula.png) 33 | 34 | **gruvbox (dark)** 35 | 36 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/gruvbox_dark.png) 37 | 38 | **gruvbox (light)** 39 | 40 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/gruvbox_light.png) 41 | 42 | **hybrid (dark)** 43 | 44 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/hybrid_dark.png) 45 | 46 | **hybrid (light)** 47 | 48 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/hybrid_light.png) 49 | 50 | **iceberg (dark)** 51 | 52 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/iceberg_dark.png) 53 | 54 | **iceberg (light)** 55 | 56 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/iceberg_light.png) 57 | 58 | **jellybeans** 59 | 60 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/jellybeans.png) 61 | 62 | **molokai** 63 | 64 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/molokai.png) 65 | 66 | **nord** 67 | 68 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/nord.png) 69 | 70 | **onedark** 71 | 72 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/onedark.png) 73 | 74 | **onehalfdark** 75 | 76 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/onehalfdark.png) 77 | 78 | **onehalflight** 79 | 80 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/onehalflight.png) 81 | 82 | **papercolor** 83 | 84 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/papercolor.png) 85 | 86 | **shadesofpurple** 87 | 88 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/shadesofpurple.png) 89 | 90 | **solarized (dark)** 91 | 92 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/solarized_dark.png) 93 | 94 | **solarized (light)** 95 | 96 | ![img](https://github.com/rbong/vim-crystalline/wiki/screenshots/solarized_light.png) 97 | 98 | **Making your own theme** 99 | 100 | See also [`:help crystalline-creating-themes`](https://raw.githubusercontent.com/rbong/vim-crystalline/master/doc/crystalline.txt) 101 | and [Porting Airline Themes](https://github.com/rbong/vim-crystalline/wiki/Porting-Airline-Themes). 102 | 103 | ## Installation 104 | 105 | ### Installation with [vim-plug](https://github.com/junegunn/vim-plug) 106 | 107 | ```vim 108 | call plug#begin() 109 | Plug 'rbong/vim-crystalline' 110 | call plug#end() 111 | ``` 112 | 113 | Run `:PlugInstall` after restarting vim. 114 | 115 | ### Installation with [packer.nvim](https://github.com/wbthomason/packer.nvim) 116 | 117 | ```lua 118 | require("packer").startup(function(use) 119 | use("rbong/vim-crystalline") 120 | end) 121 | ``` 122 | 123 | Run `:PackerInstall` after restarting neovim. 124 | 125 | ## Examples 126 | 127 | These examples use vimscript. 128 | Examples are also available in [neovim-flavored Lua](examples/neovim_lua_examples.md). 129 | 130 | All examples belong in `.vimrc` before `vim-crystalline` is loaded. 131 | 132 | ### Creating a Basic Statusline 133 | 134 | ```vim 135 | function! g:CrystallineStatuslineFn(winnr) 136 | let l:s = '' 137 | 138 | " Add file name and modification status 139 | let l:s .= ' %f%h%w%m%r ' 140 | 141 | " Start the right side of the statusline 142 | let l:s .= '%=' 143 | 144 | " Add file type and position info 145 | let l:s .= '%{&ft} %l/%L %2v ' 146 | 147 | return l:s 148 | endfunction 149 | 150 | " Always show the statusline 151 | set laststatus=2 152 | ``` 153 | 154 | See [`:help 'statusline'`](https://vimhelp.org/options.txt.html#%27statusline%27) for more info. 155 | 156 | ### Creating a Basic Tabline 157 | 158 | ```vim 159 | function! g:CrystallineTablineFn() 160 | return crystalline#DefaultTabline() 161 | endfunction 162 | 163 | " Always show the tabline 164 | set showtabline=2 165 | " Show the tabline in gvim 166 | set guioptions-=e 167 | ``` 168 | 169 | See [`:help 'tabline'`](https://vimhelp.org/options.txt.html#%27statusline%27) for more info. 170 | 171 | ### Hiding Sections 172 | 173 | ```vim 174 | function! g:CrystallineStatuslineFn(winnr) 175 | let l:s = '' 176 | 177 | let l:s .= ' %f%h%w%m%r ' 178 | 179 | let l:s .= '%=' 180 | 181 | " Only add this section in active windows 182 | if a:winnr == winnr() 183 | let l:s .= '%{&ft} ' 184 | endif 185 | " Only add this section in wide enough windows 186 | if winwidth(a:winnr) >= 80 187 | let l:s .= '%l/%L %2v ' 188 | endif 189 | 190 | return l:s 191 | endfunction 192 | 193 | set laststatus=2 194 | ``` 195 | 196 | ### Using Highlight Groups 197 | 198 | ```vim 199 | function! g:CrystallineStatuslineFn(winnr) 200 | let l:s = '' 201 | 202 | if a:winnr == winnr() 203 | " Start highlighting section A 204 | let l:s .= crystalline#HiItem('A') 205 | else 206 | " Start highlighting Fill section for inactive windows 207 | let l:s .= crystalline#HiItem('InactiveFill') 208 | endif 209 | 210 | let l:s .= ' %f%h%w%m%r ' 211 | 212 | return l:s 213 | endfunction 214 | 215 | set laststatus=2 216 | " Default theme 217 | let g:crystalline_theme = 'default' 218 | ``` 219 | 220 | See [`:help crystalline-highlight-groups`](https://raw.githubusercontent.com/rbong/vim-crystalline/master/doc/crystalline.txt) 221 | for the full list of groups. 222 | 223 | See [screenshots](#obligatory-colorful-theme-screenshots) 224 | for the full list of themes. 225 | 226 | ### Using Separators 227 | 228 | ```vim 229 | function! g:CrystallineStatuslineFn(winnr) 230 | let l:s = '' 231 | 232 | let l:s .= crystalline#HiItem('A') 233 | 234 | let l:s .= ' %f%h%w%m%r ' 235 | 236 | " Add separator 0 between section A and the statusline fill section 237 | let l:s .= crystalline#Sep(0, 'A', 'Fill') 238 | 239 | let l:s .= '%=' 240 | 241 | " Add separator 1 between the fill section and section A 242 | let l:s .= crystalline#Sep(1, 'Fill', 'A') 243 | 244 | let l:s .= '%{&ft} %l/%L %2v ' 245 | 246 | return l:s 247 | endfunction 248 | 249 | function! g:CrystallineTablineFn() 250 | " Add separators to the tabline 251 | return crystalline#DefaultTabline({ 'enable_sep': 1 }) 252 | endfunction 253 | 254 | set laststatus=2 255 | set showtabline=2 256 | set guioptions-=e 257 | " By default, these are powerline-style separators 258 | let g:crystalline_separators = [ 259 | \ { 'ch': '>', 'alt_ch': '|', 'dir': '>' }, 260 | \ { 'ch': '<', 'alt_ch': '|', 'dir': '<' }, 261 | \ ] 262 | ``` 263 | 264 | ### Using Mode Colors 265 | 266 | Using mode colors manually: 267 | 268 | ```vim 269 | function! g:CrystallineStatuslineFn(winnr) 270 | let l:s = '' 271 | 272 | " In different modes, this will be 'NormalModeA', 'InsertModeA', etc. 273 | let l:s .= crystalline#ModeHiItem('A') 274 | 275 | let l:s .= ' %f%h%w%m%r ' 276 | 277 | " The mode prefix is added to all separator groups 278 | let l:s .= crystalline#Sep(0, crystalline#ModeGroup('A'), crystalline#ModeGroup('Fill')) 279 | 280 | return l:s 281 | endfunction 282 | 283 | function! g:CrystallineTablineFn() 284 | " auto_prefix_groups automatically uses mode colors 285 | return crystalline#DefaultTabline({ 'auto_prefix_groups': 1 }) 286 | endfunction 287 | 288 | set laststatus=2 289 | set showtabline=2 290 | set guioptions-=e 291 | ``` 292 | 293 | Using mode colors automatically: 294 | 295 | ```vim 296 | function! g:CrystallineStatuslineFn(winnr) 297 | let l:s = '' 298 | 299 | " In different modes, this will be 'NormalModeA', 'InsertModeA', etc. 300 | " In inactive windows, this will be 'InactiveA' 301 | let l:s .= crystalline#HiItem('A') 302 | 303 | let l:s .= ' %f%h%w%m%r ' 304 | 305 | " The prefix will automatically be added to separator groups 306 | let l:s .= crystalline#Sep(0, 'A', 'Fill') 307 | 308 | return l:s 309 | endfunction 310 | 311 | function! g:CrystallineTablineFn() 312 | " auto_prefix_groups will default to true 313 | " 'Inactive*' groups will not be used in the tabline 314 | return crystalline#DefaultTabline() 315 | endfunction 316 | 317 | set laststatus=2 318 | set showtabline=2 319 | set guioptions-=e 320 | " This enables auto mode/inactive colors 321 | " All functions work with this option 322 | let g:crystalline_auto_prefix_groups = 1 323 | ``` 324 | 325 | Add a mode section: 326 | 327 | ```vim 328 | function! g:CrystallineStatuslineFn(winnr) 329 | let l:s = '' 330 | 331 | " Automatically create a mode highlight group, mode label, and separator 332 | " Same arguments as crystalline#Sep() 333 | let l:s .= crystalline#ModeSection(0, 'A', 'B') 334 | 335 | let l:s .= ' %f%h%w%m%r ' 336 | 337 | let l:s .= crystalline#Sep(0, 'B', 'Fill') 338 | 339 | return l:s 340 | endfunction 341 | 342 | set laststatus=2 343 | ``` 344 | 345 | ### Using Color Variants 346 | 347 | Using color variants manually: 348 | 349 | ```vim 350 | function! g:GroupSuffix() 351 | if mode() ==# 'i' && &paste 352 | " Add the suffix '2' to all groups 353 | return '2' 354 | endif 355 | if &modified 356 | " Add the suffix '1' to all groups 357 | return '1' 358 | endif 359 | " Don't add any suffix 360 | return '' 361 | endfunction 362 | 363 | function! g:CrystallineStatuslineFn(winnr) 364 | let l:s = '' 365 | 366 | " Add the variant onto the end of the highlight item 367 | let l:s .= crystalline#HiItem('Fill' . g:GroupSuffix()) 368 | 369 | let l:s .= ' %f%h%w%m%r ' 370 | 371 | return l:s 372 | endfunction 373 | 374 | function! g:CrystallineTablineFn() 375 | " Add the variant onto the end of all tabline groups 376 | return crystalline#DefaultTabline({ 'group_suffix': g:GroupSuffix() }) 377 | endfunction 378 | 379 | set laststatus=2 380 | set showtabline=2 381 | set guioptions-=e 382 | let g:crystalline_auto_prefix_groups = 1 383 | ``` 384 | 385 | Using color variants automatically: 386 | 387 | ```vim 388 | function! g:GroupSuffix() 389 | if mode() ==# 'i' && &paste 390 | return '2' 391 | endif 392 | if &modified 393 | return '1' 394 | endif 395 | return '' 396 | endfunction 397 | 398 | function! g:CrystallineStatuslineFn(winnr) 399 | let l:s = '' 400 | 401 | " Automatically add the suffix onto the end of all groups 402 | " Works with all functions 403 | let g:crystalline_group_suffix = g:GroupSuffix() 404 | 405 | let l:s .= crystalline#HiItem('Fill') 406 | 407 | let l:s .= ' %f%h%w%m%r ' 408 | 409 | return l:s 410 | endfunction 411 | 412 | function! g:CrystallineTablineFn() 413 | let g:crystalline_group_suffix = g:GroupSuffix() 414 | return crystalline#DefaultTabline() 415 | endfunction 416 | 417 | set laststatus=2 418 | set showtabline=2 419 | set guioptions-=e 420 | let g:crystalline_auto_prefix_groups = 1 421 | ``` 422 | 423 | There are 2 variants to use in built-in themes. 424 | 425 | ### Showing More Statusline Information 426 | 427 | ```vim 428 | function! g:CrystallineStatuslineFn(winnr) 429 | let l:s = '' 430 | 431 | let l:s .= ' %f%h%w%m%r ' 432 | 433 | " Add the current branch from vim-fugitive 434 | " Plugins often provide functions for the statusline 435 | let l:s .= '%{fugitive#Head()} ' 436 | 437 | let l:s .= '%=' 438 | 439 | " Show settings in the statusline 440 | let l:s .= '%{&paste ? "PASTE " : " "}' 441 | 442 | return l:s 443 | endfunction 444 | 445 | set laststatus=2 446 | ``` 447 | 448 | ### Showing More Tabline Information 449 | 450 | ```vim 451 | function! g:CrystallineTablineFn() 452 | let l:max_width = &columns 453 | " Start the right side of the tabline 454 | let l:right = '%=' 455 | 456 | " Add a separator 457 | " Reuse the TabType group for the right section 458 | let l:right .= crystalline#Sep(1, 'TabFill', 'TabType') 459 | " Subtract the width of the separator 460 | let l:max_width -= 1 461 | 462 | " Add a label indicating if vim or neovim is being used 463 | let l:vimlabel = has('nvim') ? ' NVIM ' : ' VIM ' 464 | let l:right .= l:vimlabel 465 | " Use strchars() to get the real visible width 466 | let l:max_width -= strchars(l:vimlabel) 467 | 468 | " Reduce the number of max tabs to fit new tabline items 469 | let l:max_tabs = 23 470 | 471 | return crystalline#DefaultTabline({ 'max_tabs': l:max_tabs, 'max_width': l:max_width }) . l:right 472 | endfunction 473 | 474 | set showtabline=2 475 | set guioptions-=e 476 | ``` 477 | 478 | ### Full Example 479 | 480 | ```vim 481 | function! g:GroupSuffix() 482 | if mode() ==# 'i' && &paste 483 | return '2' 484 | endif 485 | if &modified 486 | return '1' 487 | endif 488 | return '' 489 | endfunction 490 | 491 | function! g:CrystallineStatuslineFn(winnr) 492 | let g:crystalline_group_suffix = g:GroupSuffix() 493 | let l:curr = a:winnr == winnr() 494 | let l:s = '' 495 | 496 | if l:curr 497 | let l:s .= crystalline#ModeSection(0, 'A', 'B') 498 | else 499 | let l:s .= crystalline#HiItem('Fill') 500 | endif 501 | let l:s .= ' %f%h%w%m%r ' 502 | if l:curr 503 | let l:s .= crystalline#Sep(0, 'B', 'Fill') . ' %{fugitive#Head()}' 504 | endif 505 | 506 | let l:s .= '%=' 507 | if l:curr 508 | let l:s .= crystalline#Sep(1, 'Fill', 'B') . '%{&paste ? " PASTE " : " "}' 509 | let l:s .= crystalline#Sep(1, 'B', 'A') 510 | endif 511 | if winwidth(a:winnr) > 80 512 | let l:s .= ' %{&ft} %l/%L %2v ' 513 | else 514 | let l:s .= ' ' 515 | endif 516 | 517 | return l:s 518 | endfunction 519 | 520 | function! g:CrystallineTablineFn() 521 | let l:max_width = &columns 522 | let l:right = '%=' 523 | 524 | let l:right .= crystalline#Sep(1, 'TabFill', 'TabType') 525 | let l:max_width -= 1 526 | 527 | let l:vimlabel = has('nvim') ? ' NVIM ' : ' VIM ' 528 | let l:right .= l:vimlabel 529 | let l:max_width -= strchars(l:vimlabel) 530 | 531 | let l:max_tabs = 23 532 | 533 | return crystalline#DefaultTabline({ 534 | \ 'enable_sep': 1, 535 | \ 'max_tabs': l:max_tabs, 536 | \ 'max_width': l:max_width 537 | \ }) . l:right 538 | endfunction 539 | 540 | set showtabline=2 541 | set guioptions-=e 542 | set laststatus=2 543 | let g:crystalline_auto_prefix_groups = 1 544 | ``` 545 | 546 | ## More Info 547 | 548 | See [`:help crystalline`](https://raw.githubusercontent.com/rbong/vim-crystalline/master/doc/crystalline.txt) for more information. 549 | 550 | Don't hesitate to [start a discussion](https://github.com/rbong/vim-crystalline/discussions/new/choose) if you have any questions or suggestions 551 | or [post an issue](https://github.com/rbong/vim-crystalline/issues/new) if you encounter any bugs. 552 | 553 | Feel free to [make a pull request](https://github.com/rbong/vim-crystalline/pulls) if you'd like to to contribute. 554 | It's much appreciated. 555 | -------------------------------------------------------------------------------- /autoload/crystalline.vim: -------------------------------------------------------------------------------- 1 | " Deprecated Functions {{{ 2 | 3 | function! crystalline#mode(...) abort 4 | throw 'crystalline: crystalline#mode() is deprecated, use crystalline#ModeSection()' 5 | endfunction 6 | 7 | function! crystalline#mode_hi(...) abort 8 | throw 'crystalline: crystalline#mode_hi() is deprecated, use crystalline#ModeGroup()' 9 | endfunction 10 | 11 | function! crystalline#mode_label(...) abort 12 | throw 'crystalline: crystalline#mode_label() is deprecated, use crystalline#ModeLabel()' 13 | endfunction 14 | 15 | function! crystalline#mode_sep(...) abort 16 | throw 'crystalline: crystalline#mode_sep() is deprecated, use crystalline#Sep() with crystalline#ModeGroup()' 17 | endfunction 18 | 19 | function! crystalline#right_sep(...) abort 20 | throw 'crystalline: crystalline#RightSep() is deprecated, use crystalline#Sep()' 21 | endfunction 22 | 23 | function! crystalline#left_sep(...) abort 24 | throw 'crystalline: crystalline#LeftSep() is deprecated, use crystalline#Sep()' 25 | endfunction 26 | 27 | function! crystalline#right_mode_sep(...) abort 28 | throw 'crystalline: crystalline#right_mode_sep() is deprecated, use crystalline#Sep() with crystalline#ModeGroup()' 29 | endfunction 30 | 31 | function! crystalline#left_mode_sep(...) abort 32 | throw 'crystalline: crystalline#left_mode_sep() is deprecated, use crystalline#Sep() with crystalline#ModeGroup()' 33 | endfunction 34 | 35 | function! crystalline#bufferline(...) abort 36 | throw 'crystalline: crystalline#bufferline() is deprecated, use crystalline#DefaultTabline()' 37 | endfunction 38 | 39 | function! crystalline#hide_buf_tab(...) abort 40 | throw 'crystalline: crystalline#hide_buf_tab() is deprecated, use crystalline#DefaultHideBuffer()' 41 | endfunction 42 | 43 | function! crystalline#default_tablabel_parts(...) abort 44 | throw 'crystalline: crystalline#default_tablabel_parts() is deprecated, use crystalline#DefaultTab()' 45 | endfunction 46 | 47 | function! crystalline#default_tabwidth(...) abort 48 | throw 'crystalline: crystalline#default_tabwidth() is deprecated, use crystalline#DefaultTab()' 49 | endfunction 50 | 51 | " }}} 52 | 53 | " General Utils {{{ 54 | 55 | function! crystalline#EscapeStatuslineString(str) abort 56 | return substitute(a:str, '%', '%%', 'g') 57 | endfunction 58 | 59 | function! crystalline#LeftPad(s, ...) abort 60 | if empty(a:s) 61 | return '' 62 | endif 63 | let l:amount = a:0 >= 1 ? a:1 : 1 64 | let l:char = a:0 >= 2 ? a:2 : ' ' 65 | return repeat(l:char, l:amount) . a:s 66 | endfunction 67 | 68 | function! crystalline#RightPad(s, ...) abort 69 | if empty(a:s) 70 | return '' 71 | endif 72 | let l:amount = a:0 >= 1 ? a:1 : 1 73 | let l:char = a:0 >= 2 ? a:2 : ' ' 74 | return a:s . repeat(l:char, l:amount) 75 | endfunction 76 | 77 | function! crystalline#Profile(loops) abort 78 | let l:start = reltime() 79 | for _ in range(a:loops) 80 | redraw! 81 | endfor 82 | let l:end = reltime() 83 | let l:time = reltimefloat(reltime(l:start, l:end)) / a:loops 84 | echo printf('redraw time: %f seconds', l:time) 85 | endfunction 86 | 87 | " }}} 88 | 89 | " Statusline Utils {{{ 90 | 91 | function! crystalline#Group(group) abort 92 | if g:crystalline_auto_prefix_groups 93 | if g:crystalline_inactive 94 | return 'Inactive' . a:group . g:crystalline_group_suffix 95 | else 96 | return g:crystalline_mode_hi_groups[mode()] . a:group . g:crystalline_group_suffix 97 | endif 98 | endif 99 | return a:group . g:crystalline_group_suffix 100 | endfunction 101 | 102 | function! crystalline#ModeGroup(group) abort 103 | return g:crystalline_mode_hi_groups[mode()] . a:group . g:crystalline_group_suffix 104 | endfunction 105 | 106 | function! crystalline#ModeSepGroup(group) abort 107 | if g:crystalline_auto_prefix_groups 108 | return a:group 109 | endif 110 | return g:crystalline_mode_hi_groups[mode()] . a:group 111 | endfunction 112 | 113 | function! crystalline#HiItem(group) abort 114 | return '%#Crystalline' . crystalline#Group(a:group) . '#' 115 | endfunction 116 | 117 | function! crystalline#ModeHiItem(group) abort 118 | return '%#Crystalline' . crystalline#ModeGroup(a:group) . '#' 119 | endfunction 120 | 121 | function! crystalline#ModeLabel() abort 122 | return g:crystalline_mode_labels[mode()] 123 | endfunction 124 | 125 | function! crystalline#ModeSection(sep_index, left_group, right_group) abort 126 | let l:dir = get(g:crystalline_separators, a:sep_index, { 'dir': '>' }).dir 127 | 128 | if l:dir ==# '<' 129 | return crystalline#Sep(a:sep_index, a:left_group, crystalline#ModeSepGroup(a:right_group)) 130 | \ . crystalline#ModeLabel() 131 | endif 132 | 133 | return crystalline#ModeHiItem(a:left_group) 134 | \ . crystalline#ModeLabel() 135 | \ . crystalline#Sep(a:sep_index, crystalline#ModeSepGroup(a:left_group), a:right_group) 136 | endfunction 137 | 138 | function! crystalline#GetStatusline(win_id) abort 139 | let l:winnr = win_id2win(a:win_id) 140 | let g:crystalline_inactive = l:winnr != winnr() 141 | return g:CrystallineStatuslineFn(l:winnr) 142 | endfunction 143 | 144 | function! crystalline#UpdateStatusline(win_id) abort 145 | let l:winnr = win_id2win(a:win_id) 146 | call setwinvar(l:winnr, '&statusline', '%!crystalline#GetStatusline(' . a:win_id . ')') 147 | endfunction 148 | 149 | function! crystalline#GetSep(sep_index, left_group, right_group) abort 150 | if a:left_group == v:null || a:right_group == v:null 151 | return '' 152 | endif 153 | 154 | if a:left_group ==# a:right_group 155 | let l:next_item = '' 156 | else 157 | let l:next_item = '%#Crystalline' . a:right_group . '#' 158 | endif 159 | 160 | if !get(g:, 'crystalline_enable_sep', 1) 161 | return l:next_item 162 | endif 163 | 164 | let l:sep = get(g:crystalline_separators, a:sep_index, {}) 165 | 166 | if empty(l:sep) 167 | return l:next_item 168 | endif 169 | 170 | let l:ch = l:sep.ch 171 | 172 | if l:sep.dir ==# '<' 173 | let l:from_group = a:right_group 174 | let l:to_group = a:left_group 175 | else 176 | let l:from_group = a:left_group 177 | let l:to_group = a:right_group 178 | endif 179 | 180 | if a:left_group ==# a:right_group 181 | let l:sep_item = l:sep.alt_ch 182 | else 183 | let l:sep_group = l:from_group . 'To' . l:to_group 184 | 185 | " Create separator highlight group if it doesn't exist 186 | if !has_key(g:crystalline_sep_hi_groups, l:sep_group) 187 | call crystalline#GenerateSepHi(l:from_group, l:to_group) 188 | let g:crystalline_sep_hi_groups[l:sep_group] = [l:from_group, l:to_group] 189 | endif 190 | 191 | if get(g:crystalline_skip_sep_groups, l:sep_group, 0) 192 | " Skip separator highlight group 193 | let l:sep_item = l:sep.alt_ch 194 | elseif get(g:crystalline_alt_sep_groups, l:sep_group, 0) 195 | if l:sep.dir ==# '<' 196 | return l:next_item . l:sep.alt_ch 197 | endif 198 | let l:sep_item = l:sep.alt_ch 199 | else 200 | let l:sep_item = '%#Crystalline' . l:sep_group . '#' . l:ch 201 | endif 202 | endif 203 | 204 | return l:sep_item . l:next_item 205 | endfunction 206 | 207 | " }}} 208 | 209 | " Tabline Utils {{{ 210 | 211 | function! crystalline#GetTabline() abort 212 | let g:crystalline_inactive = 0 213 | return g:CrystallineTablineFn() 214 | endfunction 215 | 216 | function! crystalline#UpdateTabline() abort 217 | set tabline=%!crystalline#GetTabline() 218 | endfunction 219 | 220 | function! crystalline#Tabs(...) abort 221 | if has_key(a:, 1) 222 | let l:opts = copy(a:1) 223 | else 224 | let l:opts = {} 225 | endif 226 | let l:opts.is_buffers = 0 227 | return crystalline#TabsOrBuffers(l:opts) 228 | endfunction 229 | 230 | function! crystalline#Buffers(...) abort 231 | if has_key(a:, 1) 232 | let l:opts = copy(a:1) 233 | else 234 | let l:opts = {} 235 | endif 236 | let l:opts.is_buffers = 1 237 | return crystalline#TabsOrBuffers(l:opts) 238 | endfunction 239 | 240 | function! crystalline#TabTypeLabel(...) abort 241 | if get(a:, 1, 0) 242 | return g:crystalline_buffers_tab_type_label 243 | endif 244 | return g:crystalline_tabs_tab_type_label 245 | endfunction 246 | 247 | function! crystalline#DefaultTablineIsBuffers() abort 248 | return tabpagenr('$') == 1 249 | endfunction 250 | 251 | function! crystalline#DefaultTabline(...) abort 252 | if has_key(a:, 1) 253 | let l:opts = copy(a:1) 254 | else 255 | let l:opts = {} 256 | endif 257 | 258 | let l:is_buffers = crystalline#DefaultTablineIsBuffers() 259 | let l:tab_type = crystalline#TabTypeLabel(l:is_buffers) 260 | let l:opts.is_buffers = l:is_buffers 261 | let l:opts.left_group = 'TabType' 262 | let l:opts.max_width = get(l:opts, 'max_width', &columns) - strchars(l:tab_type) 263 | let l:opts.max_tabs = get(l:opts, 'max_tabs', 25) 264 | 265 | return '%#CrystallineTabType#' 266 | \ . l:tab_type 267 | \ . crystalline#TabsOrBuffers(l:opts) 268 | endfunction 269 | 270 | " }}} 271 | 272 | " Theme Utils {{{ 273 | 274 | " Returns a dictionary with attributes of a highlight group. 275 | " Returns an empty dictionary if the highlight group doesn't exist. 276 | function! crystalline#SynIDattrs(hlgroup) abort 277 | let l:id = synIDtrans(hlID(a:hlgroup)) 278 | if !l:id 279 | return {} 280 | endif 281 | 282 | let l:result = {} 283 | 284 | for l:mode in g:crystalline_syn_modes 285 | let l:result[l:mode] = {} 286 | let l:result[l:mode]['attrs'] = [] 287 | 288 | for l:attr in g:crystalline_syn_attrs 289 | if synIDattr(l:id, l:attr, l:mode) 290 | call add(l:result[l:mode].attrs, l:attr) 291 | endif 292 | endfor 293 | 294 | " term mode has no colors 295 | if l:mode ==# 'term' 296 | continue 297 | endif 298 | 299 | for l:color in g:crystalline_syn_colors 300 | " only gui mode has sp color 301 | if l:color ==# 'sp' && l:mode !=# 'gui' 302 | continue 303 | endif 304 | let l:res_color = synIDattr(l:id, l:color, l:mode) 305 | let l:result[l:mode][l:color] = !empty(l:res_color) ? l:res_color : 'NONE' 306 | endfor 307 | endfor 308 | 309 | return l:result 310 | endfunction 311 | 312 | " Translates crystalline#SynIDattrs() into the format 313 | " crystalline#GenerateHi() understands. 314 | function! crystalline#GetHlAttrs(group) abort 315 | let l:attrs = crystalline#SynIDattrs('Crystalline' . a:group) 316 | if l:attrs == {} 317 | return [] 318 | endif 319 | let l:retval = [[l:attrs.cterm.fg, l:attrs.cterm.bg], [l:attrs.gui.fg, l:attrs.gui.bg]] 320 | 321 | let l:retval_attrs = [] 322 | for l:mode in keys(l:attrs) 323 | if !empty(l:attrs[l:mode].attrs) 324 | call add(l:retval_attrs, l:mode . '=' . join(l:attrs[l:mode].attrs, ',')) 325 | endif 326 | endfor 327 | if !empty(l:retval_attrs) 328 | call add(l:retval, join(l:retval_attrs, ' ')) 329 | endif 330 | 331 | return l:retval 332 | endfunction 333 | 334 | function! crystalline#GenerateHi(group, attrs) abort 335 | let l:has_attrs = 0 336 | 337 | let l:hi = 'hi Crystalline' . a:group 338 | 339 | for [l:i, l:j, l:name] in g:crystalline_theme_attrs 340 | let l:value = a:attrs[l:i][l:j] 341 | if !(l:value is# '') 342 | let l:hi .= ' ' . l:name . '=' . l:value 343 | let l:has_attrs = 1 344 | endif 345 | endfor 346 | 347 | let l:extra = get(a:attrs, 2, '') 348 | if !empty(l:extra) 349 | let l:hi .= ' ' . l:extra 350 | let l:has_attrs = 1 351 | endif 352 | 353 | if !l:has_attrs 354 | let l:hi .= ' NONE' 355 | endif 356 | 357 | let l:hi .= ' cterm=nocombine gui=nocombine' 358 | 359 | return l:hi 360 | endfunction 361 | 362 | function! crystalline#GetEmptyThemeAttrs() abort 363 | return [['', ''], ['', ''], ''] 364 | endfunction 365 | 366 | function! crystalline#SetThemeFallbackAttrs(theme, style, section, variant) abort 367 | let l:group = a:section . a:variant 368 | let l:full_group = a:style . a:section . a:variant 369 | 370 | if !has_key(a:theme, l:full_group) 371 | " set default attrs 372 | let l:attrs = crystalline#GetEmptyThemeAttrs() 373 | let a:theme[l:full_group] = l:attrs 374 | else 375 | let l:attrs = a:theme[l:full_group] 376 | endif 377 | 378 | " pad length 379 | while len(l:attrs) < 2 380 | let l:attrs += [['', '']] 381 | endwhil 382 | if len(l:attrs) < 3 383 | let l:attrs += [''] 384 | endif 385 | 386 | " get fallback attrs 387 | " assume this function is called in fallback order unless otherwise noted 388 | if !empty(a:variant) 389 | let l:fallback_attrs = a:theme[a:style . a:section] 390 | elseif l:group ==# 'A' || l:group ==# 'B' || l:group ==# 'Fill' 391 | if a:style is# '' 392 | let l:fallback_attrs = crystalline#GetEmptyThemeAttrs() 393 | else 394 | let l:fallback_attrs = get(a:theme, l:group, crystalline#GetEmptyThemeAttrs()) 395 | endif 396 | elseif l:group ==# 'Tab' 397 | " ensure inactive mid is set 398 | let [l:fallback_attrs, l:_] = crystalline#SetThemeFallbackAttrs(a:theme, 'Inactive', 'Fill', '') 399 | elseif l:group ==# 'TabSel' 400 | let l:fallback_attrs = a:theme[a:style . 'A'] 401 | elseif l:group ==# 'TabFill' 402 | let l:fallback_attrs = a:theme[a:style . 'Fill'] 403 | elseif l:group ==# 'TabType' 404 | let l:fallback_attrs = a:theme[a:style . 'B'] 405 | else 406 | let l:fallback_attrs = crystalline#GetEmptyThemeAttrs() 407 | endif 408 | 409 | " set default attributes 410 | let l:has_attrs = 0 411 | for [l:i, l:j, l:_] in g:crystalline_theme_attrs 412 | if l:attrs[l:i][l:j] ==# '' 413 | let l:attrs[l:i][l:j] = l:fallback_attrs[l:i][l:j] 414 | else 415 | let l:has_attrs = 1 416 | endif 417 | endfor 418 | 419 | " set default extra attributes 420 | if !l:has_attrs && empty(l:attrs[2]) 421 | let l:attrs[2] = l:fallback_attrs[2] 422 | endif 423 | 424 | return [l:attrs, l:fallback_attrs] 425 | endfunction 426 | 427 | function! crystalline#GenerateTheme(theme) abort 428 | let l:theme = deepcopy(a:theme) 429 | let l:his = [] 430 | 431 | " set fallback attributes 432 | for l:style in g:crystalline_theme_styles 433 | for l:section in g:crystalline_theme_sections 434 | for l:variant in g:crystalline_theme_variants 435 | call crystalline#SetThemeFallbackAttrs(l:theme, l:style, l:section, l:variant) 436 | endfor 437 | endfor 438 | endfor 439 | 440 | " generate highlight groups 441 | for [l:group, l:attr] in items(l:theme) 442 | let l:hi = crystalline#GenerateHi(l:group, l:attr) 443 | if !empty(l:hi) 444 | let l:his += [l:hi] 445 | endif 446 | endfor 447 | 448 | " execute highlight groups 449 | if len(l:his) > 0 450 | exec join(l:his, ' | ') 451 | endif 452 | endfunction 453 | 454 | function! crystalline#GenerateSepHi(from_group, to_group) abort 455 | if get(g:, 'crystalline_no_generate_sep_hi') 456 | return 457 | endif 458 | 459 | if (a:from_group ==# '' || a:to_group ==# '') && !get(g:, 'crystalline_did_warn_deprecated_hi_groups') 460 | echoerr 'crystalline: use of deprecated highlight groups detected, see :help crystalline-highlight-groups' 461 | let g:crystalline_did_warn_deprecated_hi_groups = 1 462 | endif 463 | 464 | let l:sep_group = a:from_group . 'To' . a:to_group 465 | 466 | let l:attr_a = crystalline#GetHlAttrs(a:from_group) 467 | let l:attr_b = crystalline#GetHlAttrs(a:to_group) 468 | 469 | if empty(l:attr_a) || empty(l:attr_b) 470 | return 471 | endif 472 | 473 | let l:attr_type = has('gui_running') ? 1 : 0 474 | if l:attr_a[l:attr_type] == l:attr_b[l:attr_type] 475 | let g:crystalline_skip_sep_groups[l:sep_group] = 1 476 | return 477 | elseif l:attr_a[l:attr_type][1] == l:attr_b[l:attr_type][1] 478 | let g:crystalline_alt_sep_groups[l:sep_group] = 1 479 | return 480 | endif 481 | 482 | let l:sep_attr = [[l:attr_a[0][1], l:attr_b[0][1]], [l:attr_a[1][1], l:attr_b[1][1]]] 483 | if len(l:attr_a) > 2 484 | let l:sep_attr += [l:attr_a[2]] 485 | endif 486 | 487 | exec crystalline#GenerateHi(l:sep_group, l:sep_attr) 488 | endfunction 489 | 490 | function! crystalline#GetAirlineAttrs(theme_name, style, section) abort 491 | let l:pal = g:['airline#themes#' . a:theme_name . '#palette'] 492 | 493 | if !has_key(get(l:pal, a:style, {}), a:section) 494 | return crystalline#GetEmptyThemeAttrs() 495 | endif 496 | 497 | let l:attrs = l:pal[a:style][a:section] 498 | 499 | let l:extra = get(l:attrs, 4, '') 500 | if l:extra !=# '' 501 | let l:extra = 'cterm=' . l:extra . ' gui=' . l:extra 502 | endif 503 | 504 | " rearrange attributes into crystalline order 505 | return [[l:attrs[2], l:attrs[3]], [l:attrs[0], l:attrs[1]], l:extra] 506 | endfunction 507 | 508 | function! crystalline#PortAirlineTheme(theme_name) abort 509 | " get all style attributes 510 | let l:groups = {} 511 | for [l:style, l:airline_style] in g:crystalline_theme_airline_styles 512 | for [l:section, l:airline_section] in g:crystalline_theme_airline_sections 513 | if l:style ==# 'Inactive' && l:section =~# '^Tab' 514 | continue 515 | endif 516 | 517 | let [l:airline_section_style, l:airline_section] = l:airline_section 518 | if empty(l:airline_section_style) 519 | let l:airline_section_style = l:airline_style 520 | endif 521 | 522 | for [l:variant, l:airline_variant] in g:crystalline_theme_airline_variants 523 | let l:group = l:style . l:section . l:variant 524 | let l:groups[l:group] = crystalline#GetAirlineAttrs(a:theme_name, l:airline_section_style . l:airline_variant, l:airline_section) 525 | endfor 526 | endfor 527 | endfor 528 | 529 | " get fallbacks and filter duplicate styles 530 | let l:unique_groups = {} 531 | for l:style in g:crystalline_theme_styles 532 | for l:section in g:crystalline_theme_sections 533 | for l:variant in g:crystalline_theme_variants 534 | let [l:attrs, l:fallback_attrs] = crystalline#SetThemeFallbackAttrs(l:groups, l:style, l:section, l:variant) 535 | let l:str_attrs = string(l:attrs) 536 | if l:str_attrs !=# string(l:fallback_attrs) 537 | let l:unique_groups[l:style . l:section . l:variant] = l:str_attrs 538 | endif 539 | endfor 540 | endfor 541 | endfor 542 | let l:groups = l:unique_groups 543 | 544 | " find max group length for padding 545 | let l:max_group_len = 0 546 | for [l:group, l:rules] in items(l:groups) 547 | if len(l:group) > l:max_group_len 548 | let l:max_group_len = len(l:group) 549 | endif 550 | endfor 551 | 552 | " build output 553 | let l:o = 'call crystalline#GenerateTheme({' 554 | for l:style in g:crystalline_theme_styles 555 | for l:section in g:crystalline_theme_sections 556 | for l:variant in g:crystalline_theme_variants 557 | let l:group = l:style . l:section . l:variant 558 | if has_key(l:groups, l:group) 559 | let l:attrs = l:groups[l:group] 560 | let l:o .= "\n \\ '" . l:group . "': " . repeat(' ', l:max_group_len - len(l:group)) . l:attrs . ',' 561 | endif 562 | endfor 563 | endfor 564 | endfor 565 | let l:o .= "\n \\ })" 566 | 567 | return l:o 568 | endfunction 569 | 570 | " }}} 571 | 572 | " Setting Management {{{ 573 | 574 | function! crystalline#InitStatusline() abort 575 | augroup CrystallineAutoUpdateStatusline 576 | au! 577 | au BufWinEnter,WinEnter,WinLeave * call crystalline#UpdateStatusline(win_getid()) 578 | if exists('##CmdWinEnter') && exists('##CmdlineEnter') && exists('##CmdlineLeave') 579 | au CmdWinEnter,CmdlineEnter,CmdlineLeave : call crystalline#UpdateStatusline(win_getid()) 580 | endif 581 | augroup END 582 | call crystalline#UpdateStatusline(win_getid()) 583 | endfunction 584 | 585 | function! crystalline#ClearStatusline() abort 586 | set statusline= 587 | augroup CrystallineAutoUpdateStatusline 588 | au! 589 | augroup END 590 | endfunction 591 | 592 | function! crystalline#InitTabline() abort 593 | if exists('+tabline') 594 | augroup CrystallineAutoUpdateTabline 595 | au! 596 | if exists('##ModeChanged') 597 | au ModeChanged * call crystalline#UpdateTabline() 598 | endif 599 | au InsertLeave * call crystalline#UpdateTabline() 600 | augroup END 601 | call crystalline#UpdateTabline() 602 | endif 603 | endfunction 604 | 605 | function! crystalline#ClearTabline() abort 606 | if exists('+tabline') 607 | set tabline= 608 | augroup CrystallineAutoUpdateTabline 609 | au! 610 | augroup END 611 | endif 612 | endfunction 613 | 614 | function! crystalline#ApplyCurrentTheme() abort 615 | let g:crystalline_mode = '' 616 | let g:crystalline_sep_hi_groups = {} 617 | let g:crystalline_skip_sep_groups = {} 618 | let g:crystalline_alt_sep_groups = {} 619 | let g:crystalline_sep_cache = {} 620 | 621 | try 622 | call function('crystalline#theme#' . g:crystalline_theme . '#SetTheme')() 623 | catch /^Vim\%((\a\+)\)\=:E118:/ 624 | " theme does not use autoload function 625 | endtry 626 | 627 | silent doautocmd User CrystallineSetTheme 628 | endfunction 629 | 630 | function! crystalline#SetTheme(theme) abort 631 | let g:crystalline_theme = a:theme 632 | call crystalline#ApplyCurrentTheme() 633 | endfunction 634 | 635 | function! crystalline#ClearTheme() abort 636 | return crystalline#SetTheme('default') 637 | endfunction 638 | 639 | " }}} 640 | 641 | " Load Optimized Functions {{{ 642 | 643 | let s:scriptdir = expand(':p:h:h') 644 | 645 | if has('nvim') 646 | exec 'source ' . s:scriptdir . '/nvim/autoload/crystalline.vim' 647 | elseif has('vim9script') 648 | exec 'source ' . s:scriptdir . '/vim9/autoload/crystalline.vim' 649 | else 650 | exec 'source ' . s:scriptdir . '/legacy/autoload/crystalline.vim' 651 | endif 652 | 653 | " }}} 654 | 655 | " vim:set et sw=2 ts=2 fdm=marker: 656 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/ayu.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#ayu#SetTheme() abort 2 | let l:ayucolor = get(g:, 'ayucolor', &background) 3 | 4 | if l:ayucolor ==# 'light' 5 | call crystalline#GenerateTheme({ 6 | \ 'A': [[66, 106], ['#6c7680', '#86b300'], ''], 7 | \ 'B': [[106, 66], ['#86b300', '#6c7680'], ''], 8 | \ 'Fill': [[66, 231], ['#6c7680', '#fafafa'], ''], 9 | \ 'InactiveA': [[106, 231], ['#86b300', '#fafafa'], ''], 10 | \ 'InactiveB': [[106, 231], ['#86b300', '#fafafa'], ''], 11 | \ 'InactiveFill': [[106, 231], ['#86b300', '#fafafa'], ''], 12 | \ 'InsertModeA': [[66, 74], ['#6c7680', '#55b4d4'], ''], 13 | \ 'InsertModeB': [[74, 66], ['#55b4d4', '#6c7680'], ''], 14 | \ 'VisualModeA': [[66, 209], ['#6c7680', '#fa8d3e'], ''], 15 | \ 'VisualModeB': [[209, 66], ['#fa8d3e', '#6c7680'], ''], 16 | \ 'ReplaceModeA': [[66, 196], ['#6c7680', '#f51818'], ''], 17 | \ }) 18 | elseif l:ayucolor ==# 'mirage' 19 | call crystalline#GenerateTheme({ 20 | \ 'A': [[0, 114], ['#212733', '#bbe67e'], ''], 21 | \ 'B': [[114, 0], ['#bbe67e', '#212733'], ''], 22 | \ 'Fill': [[15, 0], ['#e6e1cf', '#212733'], ''], 23 | \ 'InactiveA': [[114, 114], ['#bbe67e', '#212733'], ''], 24 | \ 'InactiveFill': [[114, 0], ['#bbe67e', '#212733'], ''], 25 | \ 'InsertModeA': [[0, 80], ['#212733', '#80d4ff'], ''], 26 | \ 'InsertModeB': [[80, 0], ['#80d4ff', '#212733'], ''], 27 | \ 'VisualModeA': [[0, 173], ['#212733', '#ffae57'], ''], 28 | \ 'VisualModeB': [[173, 0], ['#ffae57', '#212733'], ''], 29 | \ 'ReplaceModeA': [[0, 167], ['#212733', '#f07178'], ''], 30 | \ }) 31 | else 32 | call crystalline#GenerateTheme({ 33 | \ 'A': [[59, 149], ['#3d424d', '#c2d94c'], ''], 34 | \ 'B': [[149, 59], ['#c2d94c', '#304357'], ''], 35 | \ 'Fill': [[145, 16], ['#b3b1ad', '#0a0e14'], ''], 36 | \ 'InactiveA': [[149, 16], ['#c2d94c', '#0a0e14'], ''], 37 | \ 'InactiveB': [[149, 16], ['#c2d94c', '#0a0e14'], ''], 38 | \ 'InactiveFill': [[149, 16], ['#c2d94c', '#0a0e14'], ''], 39 | \ 'InsertModeA': [[59, 74], ['#3d424d', '#39bae6'], ''], 40 | \ 'InsertModeB': [[74, 59], ['#39bae6', '#304357'], ''], 41 | \ 'VisualModeA': [[59, 209], ['#3d424d', '#ff8f40'], ''], 42 | \ 'VisualModeB': [[209, 59], ['#ff8f40', '#304357'], ''], 43 | \ 'ReplaceModeA': [[59, 203], ['#3d424d', '#ff3333'], ''], 44 | \ }) 45 | endif 46 | endfunction 47 | 48 | " vim:set et sw=2 ts=2 fdm=marker: 49 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/badwolf.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#badwolf#SetTheme() abort 2 | call crystalline#GenerateTheme({ 3 | \ 'A': [[232, 154], ['#141413', '#aeee00'], ''], 4 | \ 'B': [[222, 238], ['#f4cf86', '#45413b'], ''], 5 | \ 'B1': [[222, 241], ['#f4cf86', '#666462'], ''], 6 | \ 'Fill': [[121, 235], ['#8cffba', '#242321'], ''], 7 | \ 'Fill1': [[214, 238], ['#ffa724', '#45413b'], ''], 8 | \ 'Tab1': [[214, 238], ['#ffa724', '#45413b'], ''], 9 | \ 'TabType1': [[222, 241], ['#f4cf86', '#666462'], ''], 10 | \ 'InactiveA': [[235, 238], ['#242321', '#45413b'], ''], 11 | \ 'InactiveB': [[235, 238], ['#242321', '#45413b'], ''], 12 | \ 'InactiveFill': [[235, 238], ['#242321', '#45413b'], ''], 13 | \ 'InactiveFill1': [[214, 238], ['#ffa724', '#45413b'], ''], 14 | \ 'NormalModeB1': [[222, 241], ['#f4cf86', '#666462'], ''], 15 | \ 'NormalModeFill1': [[214, 238], ['#ffa724', '#45413b'], ''], 16 | \ 'NormalModeTab1': [[214, 238], ['#ffa724', '#45413b'], ''], 17 | \ 'NormalModeTabType1': [[222, 241], ['#f4cf86', '#666462'], ''], 18 | \ 'CommandModeTab1': [[214, 238], ['#ffa724', '#45413b'], ''], 19 | \ 'InsertModeA': [[232, 39], ['#141413', '#0a9dff'], ''], 20 | \ 'InsertModeA2': [[232, 222], ['#141413', '#f4cf86'], ''], 21 | \ 'InsertModeB': [[222, 27], ['#f4cf86', '#005fff'], ''], 22 | \ 'InsertModeFill': [[39, 235], ['#0a9dff', '#242321'], ''], 23 | \ 'InsertModeFill1': [[214, 238], ['#ffa724', '#45413b'], ''], 24 | \ 'InsertModeTab1': [[214, 238], ['#ffa724', '#45413b'], ''], 25 | \ 'InsertModeTabSel2': [[232, 222], ['#141413', '#f4cf86'], ''], 26 | \ 'VisualModeA': [[232, 214], ['#141413', '#ffa724'], ''], 27 | \ 'VisualModeB': [[16, 221], ['#000000', '#fade3e'], ''], 28 | \ 'VisualModeFill': [[16, 137], ['#000000', '#b88853'], ''], 29 | \ 'VisualModeFill1': [[16, 173], ['#000000', '#c7915b'], ''], 30 | \ 'VisualModeTab1': [[214, 238], ['#ffa724', '#45413b'], ''], 31 | \ 'ReplaceModeA': [[232, 211], ['#141413', '#ff9eb8'], ''], 32 | \ 'ReplaceModeB': [[222, 27], ['#f4cf86', '#005fff'], ''], 33 | \ 'ReplaceModeFill': [[39, 235], ['#0a9dff', '#242321'], ''], 34 | \ 'ReplaceModeFill1': [[214, 238], ['#ffa724', '#45413b'], ''], 35 | \ 'ReplaceModeTab1': [[214, 238], ['#ffa724', '#45413b'], ''], 36 | \ 'TerminalModeA': [[232, 39], ['#141413', '#0a9dff'], ''], 37 | \ 'TerminalModeB': [[222, 27], ['#f4cf86', '#005fff'], ''], 38 | \ 'TerminalModeFill': [[39, 235], ['#0a9dff', '#242321'], ''], 39 | \ 'TerminalModeTab1': [[214, 238], ['#ffa724', '#45413b'], ''], 40 | \ }) 41 | endfunction 42 | 43 | " vim:set et sw=2 ts=2 fdm=marker: 44 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/default.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#default#SetTheme() abort 2 | call crystalline#GenerateTheme({ 3 | \ 'A': [[17, 190], ['#00005f', '#dfff00'], ''], 4 | \ 'B': [[255, 238], ['#ffffff', '#444444'], ''], 5 | \ 'Fill': [[85, 234], ['#9cffd3', '#202020'], ''], 6 | \ 'Fill1': [[255, 53], ['#ffffff', '#5f005f'], ''], 7 | \ 'Tab1': [[97, 236], ['#875faf', '#303030'], ''], 8 | \ 'InactiveA': [[239, 234], ['#4e4e4e', '#1c1c1c'], ''], 9 | \ 'InactiveB': [[239, 235], ['#4e4e4e', '#262626'], ''], 10 | \ 'InactiveFill': [[239, 236], ['#4e4e4e', '#303030'], ''], 11 | \ 'InactiveFill1': [[97, 236], ['#875faf', '#303030'], ''], 12 | \ 'NormalModeFill1': [[255, 53], ['#ffffff', '#5f005f'], ''], 13 | \ 'NormalModeTab1': [[97, 236], ['#875faf', '#303030'], ''], 14 | \ 'CommandModeA': [[17, 40], ['#00005f', '#00d700'], ''], 15 | \ 'CommandModeTab1': [[97, 236], ['#875faf', '#303030'], ''], 16 | \ 'InsertModeA': [[17, 45], ['#00005f', '#00dfff'], ''], 17 | \ 'InsertModeA2': [[17, 172], ['#00005f', '#d78700'], ''], 18 | \ 'InsertModeB': [[255, 27], ['#ffffff', '#005fff'], ''], 19 | \ 'InsertModeFill': [[15, 17], ['#ffffff', '#000080'], ''], 20 | \ 'InsertModeFill1': [[255, 53], ['#ffffff', '#5f005f'], ''], 21 | \ 'InsertModeTab1': [[97, 236], ['#875faf', '#303030'], ''], 22 | \ 'InsertModeTabSel2': [[17, 172], ['#00005f', '#d78700'], ''], 23 | \ 'VisualModeA': [[232, 214], ['#000000', '#ffaf00'], ''], 24 | \ 'VisualModeB': [[232, 202], ['#000000', '#ff5f00'], ''], 25 | \ 'VisualModeFill': [[15, 52], ['#ffffff', '#5f0000'], ''], 26 | \ 'VisualModeFill1': [[255, 53], ['#ffffff', '#5f005f'], ''], 27 | \ 'VisualModeTab1': [[97, 236], ['#875faf', '#303030'], ''], 28 | \ 'ReplaceModeA': [[255, 124], ['#ffffff', '#af0000'], ''], 29 | \ 'ReplaceModeB': [[255, 27], ['#ffffff', '#005fff'], ''], 30 | \ 'ReplaceModeFill': [[15, 17], ['#ffffff', '#000080'], ''], 31 | \ 'ReplaceModeFill1': [[255, 53], ['#ffffff', '#5f005f'], ''], 32 | \ 'ReplaceModeTab1': [[97, 236], ['#875faf', '#303030'], ''], 33 | \ 'TerminalModeA': [[17, 45], ['#00005f', '#00dfff'], ''], 34 | \ 'TerminalModeB': [[255, 27], ['#ffffff', '#005fff'], ''], 35 | \ 'TerminalModeFill': [[15, 17], ['#ffffff', '#000080'], ''], 36 | \ 'TerminalModeTab1': [[97, 236], ['#875faf', '#303030'], ''], 37 | \ }) 38 | endfunction 39 | 40 | " vim:set et sw=2 ts=2 fdm=marker: 41 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/dracula.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#dracula#SetTheme() abort 2 | call crystalline#GenerateTheme({ 3 | \ 'A': [[236, 141], ['#282a36', '#bd93f9'], ''], 4 | \ 'B': [[253, 61], ['#f8f8f2', '#6272a4'], ''], 5 | \ 'Fill': [[253, 239], ['#f8f8f2', '#44475a'], ''], 6 | \ 'Fill1': [[253, 235], ['#f8f8f2', '#21222c'], ''], 7 | \ 'TabFill1': [[253, 235], ['#f8f8f2', '#21222c'], ''], 8 | \ 'InactiveA': [[236, 61], ['#282a36', '#6272a4'], ''], 9 | \ 'InactiveB': [[253, 235], ['#f8f8f2', '#21222c'], ''], 10 | \ 'NormalModeFill1': [[253, 235], ['#f8f8f2', '#21222c'], ''], 11 | \ 'NormalModeTabFill1': [[253, 235], ['#f8f8f2', '#21222c'], ''], 12 | \ 'InsertModeA': [[236, 84], ['#282a36', '#50fa7b'], ''], 13 | \ 'InsertModeFill1': [[253, 235], ['#f8f8f2', '#21222c'], ''], 14 | \ 'InsertModeTabFill1': [[253, 235], ['#f8f8f2', '#21222c'], ''], 15 | \ 'VisualModeA': [[236, 228], ['#282a36', '#f1fa8c'], ''], 16 | \ 'VisualModeFill1': [[253, 235], ['#f8f8f2', '#21222c'], ''], 17 | \ 'VisualModeTabFill1': [[253, 235], ['#f8f8f2', '#21222c'], ''], 18 | \ 'ReplaceModeA': [[236, 215], ['#282a36', '#ffb86c'], ''], 19 | \ 'ReplaceModeFill1': [[253, 235], ['#f8f8f2', '#21222c'], ''], 20 | \ 'ReplaceModeTabFill1': [[253, 235], ['#f8f8f2', '#21222c'], ''], 21 | \ 'TerminalModeA': [[236, 84], ['#282a36', '#50fa7b'], ''], 22 | \ }) 23 | endfunction 24 | 25 | " vim:set et sw=2 ts=2 fdm=marker: 26 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/gruvbox.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#gruvbox#SetTheme() abort 2 | if &background ==# 'dark' 3 | call crystalline#GenerateTheme({ 4 | \ 'A': [[235, 246], ['#282828', '#a89984'], ''], 5 | \ 'B': [[246, 239], ['#a89984', '#504945'], ''], 6 | \ 'Fill': [[246, 237], ['#a89984', '#3c3836'], ''], 7 | \ 'Fill1': [[109, 237], ['#83a598', '#3c3836'], ''], 8 | \ 'Tab1': [[109, 237], ['#83a598', '#3c3836'], ''], 9 | \ 'InactiveA': [[243, 237], ['#7c6f64', '#3c3836'], ''], 10 | \ 'InactiveB': [[243, 237], ['#7c6f64', '#3c3836'], ''], 11 | \ 'InactiveFill': [[243, 237], ['#7c6f64', '#3c3836'], ''], 12 | \ 'InactiveFill1': [[109, 237], ['#83a598', '#3c3836'], ''], 13 | \ 'NormalModeFill1': [[109, 237], ['#83a598', '#3c3836'], ''], 14 | \ 'NormalModeTab1': [[109, 237], ['#83a598', '#3c3836'], ''], 15 | \ 'CommandModeA': [[235, 142], ['#282828', '#b8bb26'], ''], 16 | \ 'CommandModeFill': [[223, 239], ['#ebdbb2', '#504945'], ''], 17 | \ 'CommandModeFill1': [[109, 239], ['#83a598', '#504945'], ''], 18 | \ 'CommandModeTab1': [[109, 237], ['#83a598', '#3c3836'], ''], 19 | \ 'InsertModeA': [[235, 109], ['#282828', '#83a598'], ''], 20 | \ 'InsertModeFill': [[223, 239], ['#ebdbb2', '#504945'], ''], 21 | \ 'InsertModeFill1': [[109, 239], ['#83a598', '#504945'], ''], 22 | \ 'InsertModeTab1': [[109, 237], ['#83a598', '#3c3836'], ''], 23 | \ 'VisualModeA': [[235, 208], ['#282828', '#fe8019'], ''], 24 | \ 'VisualModeFill': [[235, 243], ['#282828', '#7c6f64'], ''], 25 | \ 'VisualModeTab1': [[109, 237], ['#83a598', '#3c3836'], ''], 26 | \ 'ReplaceModeA': [[235, 108], ['#282828', '#8ec07c'], ''], 27 | \ 'ReplaceModeFill': [[223, 239], ['#ebdbb2', '#504945'], ''], 28 | \ 'ReplaceModeFill1': [[109, 239], ['#83a598', '#504945'], ''], 29 | \ 'ReplaceModeTab1': [[109, 237], ['#83a598', '#3c3836'], ''], 30 | \ 'TerminalModeTab1': [[109, 237], ['#83a598', '#3c3836'], ''], 31 | \ }) 32 | else 33 | call crystalline#GenerateTheme({ 34 | \ 'A': [[229, 243], ['#fbf1c7', '#7c6f64'], ''], 35 | \ 'B': [[243, 250], ['#7c6f64', '#d5c4a1'], ''], 36 | \ 'Fill': [[243, 223], ['#7c6f64', '#ebdbb2'], ''], 37 | \ 'Fill1': [[24, 223], ['#076678', '#ebdbb2'], ''], 38 | \ 'Tab1': [[24, 223], ['#076678', '#ebdbb2'], ''], 39 | \ 'InactiveA': [[246, 223], ['#a89984', '#ebdbb2'], ''], 40 | \ 'InactiveB': [[246, 223], ['#a89984', '#ebdbb2'], ''], 41 | \ 'InactiveFill': [[246, 223], ['#a89984', '#ebdbb2'], ''], 42 | \ 'InactiveFill1': [[24, 223], ['#076678', '#ebdbb2'], ''], 43 | \ 'NormalModeFill1': [[24, 223], ['#076678', '#ebdbb2'], ''], 44 | \ 'NormalModeTab1': [[24, 223], ['#076678', '#ebdbb2'], ''], 45 | \ 'CommandModeA': [[229, 100], ['#fbf1c7', '#79740e'], ''], 46 | \ 'CommandModeFill': [[237, 250], ['#3c3836', '#d5c4a1'], ''], 47 | \ 'CommandModeFill1': [[24, 250], ['#076678', '#d5c4a1'], ''], 48 | \ 'CommandModeTab1': [[24, 223], ['#076678', '#ebdbb2'], ''], 49 | \ 'InsertModeA': [[229, 24], ['#fbf1c7', '#076678'], ''], 50 | \ 'InsertModeFill': [[237, 250], ['#3c3836', '#d5c4a1'], ''], 51 | \ 'InsertModeFill1': [[24, 250], ['#076678', '#d5c4a1'], ''], 52 | \ 'InsertModeTab1': [[24, 223], ['#076678', '#ebdbb2'], ''], 53 | \ 'VisualModeA': [[229, 130], ['#fbf1c7', '#af3a03'], ''], 54 | \ 'VisualModeFill': [[229, 246], ['#fbf1c7', '#a89984'], ''], 55 | \ 'VisualModeTab1': [[24, 223], ['#076678', '#ebdbb2'], ''], 56 | \ 'ReplaceModeA': [[229, 65], ['#fbf1c7', '#427b58'], ''], 57 | \ 'ReplaceModeFill': [[237, 250], ['#3c3836', '#d5c4a1'], ''], 58 | \ 'ReplaceModeFill1': [[24, 250], ['#076678', '#d5c4a1'], ''], 59 | \ 'ReplaceModeTab1': [[24, 223], ['#076678', '#ebdbb2'], ''], 60 | \ 'TerminalModeTab1': [[24, 223], ['#076678', '#ebdbb2'], ''], 61 | \ }) 62 | endif 63 | endfunction 64 | 65 | " vim:set et sw=2 ts=2 fdm=marker: 66 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/hybrid.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#hybrid#SetTheme() abort 2 | if &background ==# 'dark' 3 | call crystalline#GenerateTheme({ 4 | \ 'A': [[193, 65], ['#d7ffaf', '#5f875f'], ''], 5 | \ 'B': [[250, 235], ['#c5c8c6', '#282a2e'], ''], 6 | \ 'Fill': [[250, 237], ['#c5c8c6', '#373b41'], ''], 7 | \ 'InactiveA': [[243, 236], ['#707880', '#303030'], ''], 8 | \ 'InactiveB': [[243, 236], ['#707880', '#303030'], ''], 9 | \ 'InactiveFill': [[243, 236], ['#707880', '#303030'], ''], 10 | \ 'InsertModeA': [[250, 110], ['#c5c8c6', '#81a2be'], ''], 11 | \ 'VisualModeA': [[250, 167], ['#c5c8c6', '#cc6666'], ''], 12 | \ 'ReplaceModeA': [[189, 60], ['#d7d7ff', '#5f5f87'], ''], 13 | \ }) 14 | else 15 | call crystalline#GenerateTheme({ 16 | \ 'A': [[22, 194], ['#005f00', '#d7ffd7'], ''], 17 | \ 'B': [[16, 252], ['#000000', '#d0d0d0'], ''], 18 | \ 'Fill': [[16, 250], ['#000000', '#bcbcbc'], ''], 19 | \ 'InactiveA': [[59, 247], ['#5f5f5f', '#9e9e9e'], ''], 20 | \ 'InactiveB': [[59, 247], ['#5f5f5f', '#9e9e9e'], ''], 21 | \ 'InactiveFill': [[59, 247], ['#5f5f5f', '#9e9e9e'], ''], 22 | \ 'InsertModeA': [[16, 110], ['#000000', '#81a2be'], ''], 23 | \ 'VisualModeA': [[16, 224], ['#000000', '#ffd7d7'], ''], 24 | \ 'ReplaceModeA': [[53, 189], ['#5f005f', '#d7d7ff'], ''], 25 | \ }) 26 | endif 27 | endfunction 28 | 29 | " vim:set et sw=2 ts=2 fdm=marker: 30 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/iceberg.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#iceberg#SetTheme() abort 2 | if &background ==# 'dark' 3 | call crystalline#GenerateTheme({ 4 | \ 'A': [[234, 245], ['#17171b', '#818596'], ''], 5 | \ 'B': [[242, 236], ['#6b7089', '#2e313f'], ''], 6 | \ 'Fill': [[238, 233], ['#3e445e', '#0f1117'], ''], 7 | \ 'InactiveA': [[238, 233], ['#3e445e', '#0f1117'], ''], 8 | \ 'InactiveB': [[238, 233], ['#3e445e', '#0f1117'], ''], 9 | \ 'InsertModeA': [[234, 110], ['#161821', '#84a0c6'], ''], 10 | \ 'VisualModeA': [[234, 150], ['#161821', '#b4be82'], ''], 11 | \ 'ReplaceModeA': [[234, 216], ['#161821', '#e2a478'], ''], 12 | \ 'TerminalModeA': [[234, 110], ['#161821', '#84a0c6'], ''], 13 | \ }) 14 | else 15 | call crystalline#GenerateTheme({ 16 | \ 'A': [[252, 243], ['#e8e9ec', '#757ca3'], ''], 17 | \ 'B': [[252, 247], ['#e8e9ec', '#9fa6c0'], ''], 18 | \ 'Fill': [[244, 251], ['#8b98b6', '#cad0de'], ''], 19 | \ 'InactiveA': [[244, 251], ['#8b98b6', '#cad0de'], ''], 20 | \ 'InactiveB': [[244, 251], ['#8b98b6', '#cad0de'], ''], 21 | \ 'InsertModeA': [[254, 25], ['#e8e9ec', '#2d539e'], ''], 22 | \ 'VisualModeA': [[254, 64], ['#e8e9ec', '#668e3d'], ''], 23 | \ 'ReplaceModeA': [[254, 130], ['#e8e9ec', '#c57339'], ''], 24 | \ 'TerminalModeA': [[254, 25], ['#e8e9ec', '#2d539e'], ''], 25 | \ }) 26 | endif 27 | endfunction 28 | 29 | " vim:set et sw=2 ts=2 fdm=marker: 30 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/jellybeans.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#jellybeans#SetTheme() abort 2 | call crystalline#GenerateTheme({ 3 | \ 'A': [[189, 25], ['#d8dee9', '#0d61ac'], ''], 4 | \ 'B': [[231, 235], ['#ffffff', '#262626'], ''], 5 | \ 'Fill': [[59, 233], ['#4f5b66', '#151515'], ''], 6 | \ 'Fill1': [[215, 233], ['#ffb964', '#151515'], ''], 7 | \ 'Tab1': [[215, 233], ['#ffb964', '#151515'], ''], 8 | \ 'InactiveA': [[243, 235], ['#666666', '#262626'], ''], 9 | \ 'InactiveB': [[59, 233], ['#4f5b66', '#151515'], ''], 10 | \ 'InactiveFill1': [[215, 233], ['#ffb964', '#151515'], ''], 11 | \ 'NormalModeFill1': [[215, 233], ['#ffb964', '#151515'], ''], 12 | \ 'NormalModeTab1': [[215, 233], ['#ffb964', '#151515'], ''], 13 | \ 'CommandModeTab1': [[215, 233], ['#ffb964', '#151515'], ''], 14 | \ 'InsertModeA': [[231, 22], ['#ffffff', '#437019'], ''], 15 | \ 'InsertModeFill': [[231, 233], ['#ffffff', '#151515'], ''], 16 | \ 'InsertModeFill1': [[215, 233], ['#ffb964', '#151515'], ''], 17 | \ 'InsertModeTab1': [[215, 233], ['#ffb964', '#151515'], ''], 18 | \ 'VisualModeA': [[231, 88], ['#ffffff', '#870000'], ''], 19 | \ 'VisualModeFill': [[231, 233], ['#ffffff', '#151515'], ''], 20 | \ 'VisualModeFill1': [[215, 233], ['#ffb964', '#151515'], ''], 21 | \ 'VisualModeTab1': [[215, 233], ['#ffb964', '#151515'], ''], 22 | \ 'ReplaceModeA': [[88, 233], ['#870000', '#151515'], ''], 23 | \ 'ReplaceModeFill': [[231, 233], ['#ffffff', '#151515'], ''], 24 | \ 'ReplaceModeFill1': [[215, 233], ['#ffb964', '#151515'], ''], 25 | \ 'ReplaceModeTab1': [[215, 233], ['#ffb964', '#151515'], ''], 26 | \ 'TerminalModeTab1': [[215, 233], ['#ffb964', '#151515'], ''], 27 | \ }) 28 | endfunction 29 | 30 | " vim:set et sw=2 ts=2 fdm=marker: 31 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/molokai.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#molokai#SetTheme() abort 2 | call crystalline#GenerateTheme({ 3 | \ 'A': [[232, 144], ['#080808', '#e6db74'], ''], 4 | \ 'B': [[253, 16], ['#f8f8f0', '#232526'], ''], 5 | \ 'Fill': [[253, 67], ['#f8f8f0', '#465457'], ''], 6 | \ 'Fill1': [[232, 144], ['#080808', '#e6db74'], ''], 7 | \ 'Tab1': [[253, 67], ['#f8f8f0', '#465457'], ''], 8 | \ 'InactiveA': [[233, 67], ['#1b1d1e', '#465457'], ''], 9 | \ 'InactiveB': [[233, 67], ['#1b1d1e', '#465457'], ''], 10 | \ 'InactiveFill': [[233, 67], ['#1b1d1e', '#465457'], ''], 11 | \ 'InactiveFill1': [[253, 67], ['#f8f8f0', '#465457'], ''], 12 | \ 'NormalModeFill1': [[232, 144], ['#080808', '#e6db74'], ''], 13 | \ 'NormalModeTab1': [[253, 67], ['#f8f8f0', '#465457'], ''], 14 | \ 'CommandModeTab1': [[253, 67], ['#f8f8f0', '#465457'], ''], 15 | \ 'InsertModeA': [[232, 81], ['#080808', '#66d9ef'], ''], 16 | \ 'InsertModeFill1': [[232, 81], ['#080808', '#66d9ef'], ''], 17 | \ 'InsertModeTab1': [[253, 67], ['#f8f8f0', '#465457'], ''], 18 | \ 'VisualModeA': [[232, 118], ['#080808', '#a6e22e'], ''], 19 | \ 'VisualModeFill1': [[232, 118], ['#080808', '#a6e22e'], ''], 20 | \ 'VisualModeTab1': [[253, 67], ['#f8f8f0', '#465457'], ''], 21 | \ 'ReplaceModeA': [[232, 161], ['#080808', '#f92672'], ''], 22 | \ 'ReplaceModeFill1': [[232, 161], ['#080808', '#f92672'], ''], 23 | \ 'ReplaceModeTab1': [[253, 67], ['#f8f8f0', '#465457'], ''], 24 | \ 'TerminalModeTab1': [[253, 67], ['#f8f8f0', '#465457'], ''], 25 | \ }) 26 | endfunction 27 | 28 | " vim:set et sw=2 ts=2 fdm=marker: 29 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/nord.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#nord#SetTheme() abort 2 | call crystalline#GenerateTheme({ 3 | \ 'A': [[0, 6], ['#3b4252', '#88C0D0'], ''], 4 | \ 'B': [[0, 4], ['#3b4252', '#81A1C1'], ''], 5 | \ 'Fill': [[7, 8], ['#e5e9f0', '#4C566A'], ''], 6 | \ 'InactiveA': [[7, 8], ['#e5e9f0', '#4C566A'], ''], 7 | \ 'InactiveB': [[7, 8], ['#e5e9f0', '#4C566A'], ''], 8 | \ 'InactiveFill': [[7, 0], ['#e5e9f0', '#3B4252'], ''], 9 | \ 'InsertModeA': [[0, 15], ['#3b4252', '#A3BE8C'], ''], 10 | \ 'VisualModeA': [[0, 14], ['#3b4252', '#8FBCBB'], ''], 11 | \ 'ReplaceModeA': [[0, 2], ['#3b4252', '#A3BE8C'], ''], 12 | \ }) 13 | endfunction 14 | 15 | " vim:set et sw=2 ts=2 fdm=marker: 16 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/onedark.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#onedark#SetTheme() abort 2 | call crystalline#GenerateTheme({ 3 | \ 'A': [[235, 114], ['#282c34', '#98c379'], ''], 4 | \ 'B': [[145, 236], ['#abb2bf', '#3e4452'], ''], 5 | \ 'Fill': [[114, 236], ['#98c379', '#282c34'], ''], 6 | \ 'Fill1': [[145, 236], ['#abb2bf', '#282c34'], ''], 7 | \ 'Tab1': [[145, 236], ['#abb2bf', '#3e4452'], ''], 8 | \ 'InactiveA': [[235, 145], ['#282c34', '#abb2bf'], ''], 9 | \ 'InactiveFill': [[145, 236], ['#abb2bf', '#3e4452'], ''], 10 | \ 'InactiveFill1': [[145, 236], ['#abb2bf', '#3e4452'], ''], 11 | \ 'NormalModeFill1': [[145, 236], ['#abb2bf', '#282c34'], ''], 12 | \ 'NormalModeTab1': [[145, 236], ['#abb2bf', '#3e4452'], ''], 13 | \ 'CommandModeTab1': [[145, 236], ['#abb2bf', '#3e4452'], ''], 14 | \ 'InsertModeA': [[235, 39], ['#282c34', '#61afef'], ''], 15 | \ 'InsertModeFill': [[39, 236], ['#61afef', '#282c34'], ''], 16 | \ 'InsertModeFill1': [[145, 236], ['#abb2bf', '#282c34'], ''], 17 | \ 'InsertModeTab1': [[145, 236], ['#abb2bf', '#3e4452'], ''], 18 | \ 'VisualModeA': [[235, 170], ['#282c34', '#c678dd'], ''], 19 | \ 'VisualModeFill': [[170, 236], ['#c678dd', '#282c34'], ''], 20 | \ 'VisualModeFill1': [[145, 236], ['#abb2bf', '#282c34'], ''], 21 | \ 'VisualModeTab1': [[145, 236], ['#abb2bf', '#3e4452'], ''], 22 | \ 'ReplaceModeA': [[235, 204], ['#282c34', '#e06c75'], ''], 23 | \ 'ReplaceModeFill': [[204, 236], ['#e06c75', '#282c34'], ''], 24 | \ 'ReplaceModeFill1': [[145, 236], ['#abb2bf', '#282c34'], ''], 25 | \ 'ReplaceModeTab1': [[145, 236], ['#abb2bf', '#3e4452'], ''], 26 | \ 'TerminalModeA': [[235, 39], ['#282c34', '#61afef'], ''], 27 | \ 'TerminalModeFill': [[39, 236], ['#61afef', '#282c34'], ''], 28 | \ 'TerminalModeTab1': [[145, 236], ['#abb2bf', '#3e4452'], ''], 29 | \ }) 30 | endfunction 31 | 32 | " vim:set et sw=2 ts=2 fdm=marker: 33 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/onehalfdark.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#onehalfdark#SetTheme() abort 2 | call crystalline#GenerateTheme({ 3 | \ 'A': [[236, 114], ['#282c34', '#98c379'], ''], 4 | \ 'B': [[255, 243], ['#dcdfe4', '#5d677a'], ''], 5 | \ 'Fill': [[114, 238], ['#98c379', '#313640'], ''], 6 | \ 'Fill1': [[180, 238], ['#e5c07b', '#313640'], ''], 7 | \ 'Tab1': [[180, 238], ['#e5c07b', '#313640'], ''], 8 | \ 'TabFill1': [[180, 238], ['#e5c07b', '#313640'], ''], 9 | \ 'InactiveA': [[255, 238], ['#dcdfe4', '#313640'], ''], 10 | \ 'InactiveB': [[255, 238], ['#dcdfe4', '#313640'], ''], 11 | \ 'InactiveFill': [[255, 238], ['#dcdfe4', '#313640'], ''], 12 | \ 'InactiveFill1': [[180, 238], ['#e5c07b', '#313640'], ''], 13 | \ 'NormalModeFill1': [[180, 238], ['#e5c07b', '#313640'], ''], 14 | \ 'NormalModeTab1': [[180, 238], ['#e5c07b', '#313640'], ''], 15 | \ 'NormalModeTabFill1': [[180, 238], ['#e5c07b', '#313640'], ''], 16 | \ 'CommandModeTab1': [[180, 238], ['#e5c07b', '#313640'], ''], 17 | \ 'InsertModeA': [[238, 75], ['#313640', '#61afef'], ''], 18 | \ 'InsertModeA1': [[236, 114], ['#282c34', '#98c379'], ''], 19 | \ 'InsertModeFill': [[75, 238], ['#61afef', '#313640'], ''], 20 | \ 'InsertModeFill1': [[180, 238], ['#e5c07b', '#313640'], ''], 21 | \ 'InsertModeTab1': [[180, 238], ['#e5c07b', '#313640'], ''], 22 | \ 'InsertModeTabSel1': [[236, 114], ['#282c34', '#98c379'], ''], 23 | \ 'InsertModeTabFill1': [[180, 238], ['#e5c07b', '#313640'], ''], 24 | \ 'VisualModeA': [[236, 180], ['#282c34', '#e5c07b'], ''], 25 | \ 'VisualModeA1': [[236, 114], ['#282c34', '#98c379'], ''], 26 | \ 'VisualModeFill': [[180, 238], ['#e5c07b', '#313640'], ''], 27 | \ 'VisualModeTab1': [[180, 238], ['#e5c07b', '#313640'], ''], 28 | \ 'VisualModeTabSel1': [[236, 114], ['#282c34', '#98c379'], ''], 29 | \ 'ReplaceModeA': [[238, 168], ['#313640', '#e06c75'], ''], 30 | \ 'ReplaceModeA1': [[236, 114], ['#282c34', '#98c379'], ''], 31 | \ 'ReplaceModeFill': [[168, 238], ['#e06c75', '#313640'], ''], 32 | \ 'ReplaceModeFill1': [[180, 238], ['#e5c07b', '#313640'], ''], 33 | \ 'ReplaceModeTab1': [[180, 238], ['#e5c07b', '#313640'], ''], 34 | \ 'ReplaceModeTabSel1': [[236, 114], ['#282c34', '#98c379'], ''], 35 | \ 'ReplaceModeTabFill1': [[180, 238], ['#e5c07b', '#313640'], ''], 36 | \ 'TerminalModeTab1': [[180, 238], ['#e5c07b', '#313640'], ''], 37 | \ }) 38 | endfunction 39 | 40 | " vim:set et sw=2 ts=2 fdm=marker: 41 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/onehalflight.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#onehalflight#SetTheme() abort 2 | call crystalline#GenerateTheme({ 3 | \ 'A': [[231, 71], ['#fafafa', '#50a14f'], ''], 4 | \ 'B': [[245, 255], ['#969696', '#f0f0f0'], ''], 5 | \ 'Mid': [[71, 231], ['#50a14f', '#fafafa'], ''], 6 | \ 'Mid1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 7 | \ 'Tab1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 8 | \ 'TabMid1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 9 | \ 'InactiveA': [[245, 255], ['#969696', '#f0f0f0'], ''], 10 | \ 'InactiveMid': [[245, 255], ['#969696', '#f0f0f0'], ''], 11 | \ 'InactiveMid1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 12 | \ 'NormalModeMid1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 13 | \ 'NormalModeTab1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 14 | \ 'NormalModeTabMid1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 15 | \ 'CommandModeTab1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 16 | \ 'InsertModeA': [[231, 31], ['#fafafa', '#0184bc'], ''], 17 | \ 'InsertModeA1': [[231, 71], ['#fafafa', '#50a14f'], ''], 18 | \ 'InsertModeMid': [[31, 231], ['#0184bc', '#fafafa'], ''], 19 | \ 'InsertModeMid1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 20 | \ 'InsertModeTab1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 21 | \ 'InsertModeTabSel1': [[231, 71], ['#fafafa', '#50a14f'], ''], 22 | \ 'InsertModeTabMid1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 23 | \ 'VisualModeA': [[231, 136], ['#fafafa', '#c18401'], ''], 24 | \ 'VisualModeA1': [[231, 71], ['#fafafa', '#50a14f'], ''], 25 | \ 'VisualModeMid': [[136, 231], ['#c18401', '#fafafa'], ''], 26 | \ 'VisualModeMid1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 27 | \ 'VisualModeTab1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 28 | \ 'VisualModeTabSel1': [[231, 71], ['#fafafa', '#50a14f'], ''], 29 | \ 'VisualModeTabMid1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 30 | \ 'ReplaceModeA': [[231, 167], ['#fafafa', '#e45649'], ''], 31 | \ 'ReplaceModeA1': [[231, 71], ['#fafafa', '#50a14f'], ''], 32 | \ 'ReplaceModeMid': [[167, 231], ['#e45649', '#fafafa'], ''], 33 | \ 'ReplaceModeMid1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 34 | \ 'ReplaceModeTab1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 35 | \ 'ReplaceModeTabSel1': [[231, 71], ['#fafafa', '#50a14f'], ''], 36 | \ 'ReplaceModeTabMid1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 37 | \ 'TerminalModeTab1': [[136, 255], ['#c18401', '#f0f0f0'], ''], 38 | \ }) 39 | endfunction 40 | 41 | " vim:set et sw=2 ts=2 fdm=marker: 42 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/papercolor.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#papercolor#SetTheme() abort 2 | call crystalline#GenerateTheme({ 3 | \ 'A': [[240, 254], ['#585858', '#e4e4e4'], ''], 4 | \ 'B': [[254, 31], ['#e4e4e4', '#0087af'], ''], 5 | \ 'Fill': [[255, 24], ['#eeeeee', '#005f87'], ''], 6 | \ 'Tab1': [[240, 254], ['#585858', '#e4e4e4'], ''], 7 | \ 'InactiveB': [[240, 254], ['#585858', '#e4e4e4'], ''], 8 | \ 'InactiveFill': [[254, 31], ['#e4e4e4', '#0087af'], ''], 9 | \ 'InactiveFill1': [[240, 254], ['#585858', '#e4e4e4'], ''], 10 | \ 'NormalModeTab1': [[240, 254], ['#585858', '#e4e4e4'], ''], 11 | \ 'CommandModeTab1': [[240, 254], ['#585858', '#e4e4e4'], ''], 12 | \ 'InsertModeTab1': [[240, 254], ['#585858', '#e4e4e4'], ''], 13 | \ 'VisualModeA': [[24, 254], ['#005f87', '#e4e4e4'], ''], 14 | \ 'VisualModeFill': [[254, 24], ['#e4e4e4', '#005f87'], ''], 15 | \ 'VisualModeTab1': [[240, 254], ['#585858', '#e4e4e4'], ''], 16 | \ 'ReplaceModeA': [[161, 254], ['#d7005f', '#e4e4e4'], ''], 17 | \ 'ReplaceModeTab1': [[240, 254], ['#585858', '#e4e4e4'], ''], 18 | \ 'TerminalModeTab1': [[240, 254], ['#585858', '#e4e4e4'], ''], 19 | \ }) 20 | endfunction 21 | 22 | " vim:set et sw=2 ts=2 fdm=marker: 23 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/shadesofpurple.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#shadesofpurple#SetTheme() abort 2 | call crystalline#GenerateTheme({ 3 | \ 'A': [[140, 234], ['#a599e9', '#1e1e3f'], ''], 4 | \ 'B': [[234, 140], ['#1e1e3f', '#a599e9'], ''], 5 | \ 'Fill': [[140, 236], ['#a599e9', '#2d2b55'], ''], 6 | \ 'InactiveB': [[140, 234], ['#a599e9', '#1e1e3f'], ''], 7 | \ 'InactiveFill': [[140, 234], ['#a599e9', '#1e1e3f'], ''], 8 | \ 'InsertModeA': [[159, 234], ['#9effff', '#1e1e3f'], ''], 9 | \ 'InsertModeFill': [[159, 234], ['#9effff', '#1e1e3f'], ''], 10 | \ 'VisualModeA': [[234, 177], ['#1e1e3f', '#c991ff'], ''], 11 | \ 'VisualModeB': [[234, 213], ['#1e1e3f', '#fb94ff'], ''], 12 | \ 'VisualModeFill': [[140, 234], ['#a599e9', '#1e1e3f'], ''], 13 | \ 'ReplaceModeA': [[234, 204], ['#1e1e3f', '#ff628c'], ''], 14 | \ 'ReplaceModeB': [[234, 211], ['#1e1e3f', '#ff91ae'], ''], 15 | \ 'ReplaceModeFill': [[140, 234], ['#a599e9', '#1e1e3f'], ''], 16 | \ }) 17 | endfunction 18 | 19 | " vim:set et sw=2 ts=2 fdm=marker: 20 | 21 | -------------------------------------------------------------------------------- /autoload/crystalline/theme/solarized.vim: -------------------------------------------------------------------------------- 1 | function! crystalline#theme#solarized#SetTheme() abort 2 | if &background ==# 'dark' 3 | call crystalline#GenerateTheme({ 4 | \ 'A': [[230, 245], ['#fdf6e3', '#93a1a1'], 'cterm=bold gui=bold'], 5 | \ 'B': [[187, 240], ['#eee8d5', '#657b83'], ''], 6 | \ 'Fill': [[239, 235], ['#586e75', '#073642'], ''], 7 | \ 'Fill1': [[245, 235], ['#93a1a1', '#073642'], ''], 8 | \ 'Tab1': [[187, 240], ['#eee8d5', '#657b83'], ''], 9 | \ 'InactiveA': [[235, 240], ['#073642', '#657b83'], ''], 10 | \ 'InactiveB': [[235, 240], ['#073642', '#657b83'], ''], 11 | \ 'InactiveFill': [[235, 240], ['#073642', '#657b83'], ''], 12 | \ 'InactiveFill1': [[187, 240], ['#eee8d5', '#657b83'], ''], 13 | \ 'NormalModeFill1': [[245, 235], ['#93a1a1', '#073642'], ''], 14 | \ 'NormalModeTab1': [[187, 240], ['#eee8d5', '#657b83'], ''], 15 | \ 'CommandModeTab1': [[187, 240], ['#eee8d5', '#657b83'], ''], 16 | \ 'InsertModeA': [[230, 136], ['#fdf6e3', '#b58900'], 'cterm=bold gui=bold'], 17 | \ 'InsertModeFill1': [[245, 235], ['#93a1a1', '#073642'], ''], 18 | \ 'InsertModeTab1': [[187, 240], ['#eee8d5', '#657b83'], ''], 19 | \ 'VisualModeA': [[230, 125], ['#fdf6e3', '#d33682'], 'cterm=bold gui=bold'], 20 | \ 'VisualModeFill1': [[245, 235], ['#93a1a1', '#073642'], ''], 21 | \ 'VisualModeTab1': [[187, 240], ['#eee8d5', '#657b83'], ''], 22 | \ 'ReplaceModeA': [[230, 124], ['#fdf6e3', '#dc322f'], ''], 23 | \ 'ReplaceModeFill1': [[245, 235], ['#93a1a1', '#073642'], ''], 24 | \ 'ReplaceModeTab1': [[187, 240], ['#eee8d5', '#657b83'], ''], 25 | \ 'TerminalModeTab1': [[187, 240], ['#eee8d5', '#657b83'], ''], 26 | \ }) 27 | else 28 | call crystalline#GenerateTheme({ 29 | \ 'A': [[187, 240], ['#eee8d5', '#657b83'], 'cterm=bold gui=bold'], 30 | \ 'B': [[187, 245], ['#eee8d5', '#93a1a1'], ''], 31 | \ 'Fill': [[245, 187], ['#93a1a1', '#eee8d5'], ''], 32 | \ 'Fill1': [[239, 187], ['#586e75', '#eee8d5'], ''], 33 | \ 'Tab1': [[235, 244], ['#073642', '#839496'], ''], 34 | \ 'InactiveA': [[187, 244], ['#eee8d5', '#839496'], ''], 35 | \ 'InactiveB': [[187, 244], ['#eee8d5', '#839496'], ''], 36 | \ 'InactiveFill': [[187, 244], ['#eee8d5', '#839496'], ''], 37 | \ 'InactiveFill1': [[235, 244], ['#073642', '#839496'], ''], 38 | \ 'NormalModeFill1': [[239, 187], ['#586e75', '#eee8d5'], ''], 39 | \ 'NormalModeTab1': [[235, 244], ['#073642', '#839496'], ''], 40 | \ 'CommandModeTab1': [[235, 244], ['#073642', '#839496'], ''], 41 | \ 'InsertModeA': [[187, 136], ['#eee8d5', '#b58900'], 'cterm=bold gui=bold'], 42 | \ 'InsertModeFill1': [[239, 187], ['#586e75', '#eee8d5'], ''], 43 | \ 'InsertModeTab1': [[235, 244], ['#073642', '#839496'], ''], 44 | \ 'VisualModeA': [[187, 125], ['#eee8d5', '#d33682'], 'cterm=bold gui=bold'], 45 | \ 'VisualModeFill1': [[239, 187], ['#586e75', '#eee8d5'], ''], 46 | \ 'VisualModeTab1': [[235, 244], ['#073642', '#839496'], ''], 47 | \ 'ReplaceModeA': [[187, 124], ['#eee8d5', '#dc322f'], ''], 48 | \ 'ReplaceModeFill1': [[239, 187], ['#586e75', '#eee8d5'], ''], 49 | \ 'ReplaceModeTab1': [[235, 244], ['#073642', '#839496'], ''], 50 | \ 'TerminalModeTab1': [[235, 244], ['#073642', '#839496'], ''], 51 | \ }) 52 | endif 53 | endfunction 54 | 55 | " vim:set et sw=2 ts=2 fdm=marker: 56 | -------------------------------------------------------------------------------- /doc/crystalline.txt: -------------------------------------------------------------------------------- 1 | *crystalline.Txt* Functions to help you make your own statusline/tabline 2 | 3 | Author: Roger Bongers 4 | License: Same as Vim (see |license|) 5 | 6 | INTRODUCTION *crystalline* 7 | 8 | vim-crystalline provides functions for creating custom statuslines and 9 | tablines using Vim's native |'statusline'| syntax. 10 | 11 | SETTINGS *crystalline-settings* 12 | 13 | Configure the following global variables before loading vim-crystalline. 14 | Define global function settings with |:function|, not |function()|. 15 | 16 | g:CrystallineStatuslineFn *g:CrystallineStatuslineFn* 17 | 18 | Sets the statusline. 19 | Accepts one argument, the |winnr()| for the statusline. 20 | 21 | g:CrystallineTablineFn *g:CrystallineTablineFn* 22 | 23 | Sets the tabline. 24 | 25 | g:CrystallineTabFn *g:CrystallineTabFn* 26 | 27 | Custom tabs/buffers for |crystalline#TabsOrBuffers()|. 28 | 29 | Arguments: 30 | `tabnr` 31 | The tab number. 32 | `bufnr` 33 | The buffer number. 34 | `max_width` 35 | The max allowed width of the tab. 36 | `is_sel` 37 | Whether the tab is selected. 38 | 39 | Return a list containing the tab content and the visible width of the tab. 40 | 41 | Defaults to |crystalline#DefaultTab()|. 42 | 43 | g:CrystallineHideBufferFn *g:CrystallineHideBufferFn* 44 | 45 | Hide buffers with |crystalline#TabsOrBuffers()|. 46 | 47 | Arguments: 48 | `bufnr` 49 | The buffer number. 50 | 51 | Returns a boolean (whether the buffer is hidden). 52 | 53 | Defaults to |crystalline#DefaultHideBuffer()|. 54 | 55 | g:crystalline_auto_prefix_groups *g:crystalline_auto_prefix_groups* 56 | 57 | Whether to automatically prefix all |crystalline-highlight-groups| with the 58 | current mode or "Inactive" when using |crystalline-functions|. 59 | 60 | g:crystalline_group_suffix *g:crystalline_group_suffix* 61 | 62 | A string to add to the end of to all |crystalline-highlight-groups| when using 63 | |crystalline-functions|. 64 | 65 | g:crystalline_theme *g:crystalline_theme* 66 | 67 | Automatically sets the theme. 68 | 69 | g:crystalline_mode_labels *g:crystalline_mode_labels* 70 | 71 | A dictionary containing labels to use for each |mode()|. 72 | 73 | Default: 74 | >vim 75 | let g:crystalline_mode_labels = { 76 | \ 'n': ' NORMAL ', 77 | \ 'c': ' COMMAND ', 78 | \ 'r': ' NORMAL ', 79 | \ '!': ' NORMAL ', 80 | \ 'i': ' INSERT ', 81 | \ 't': ' TERMINAL ', 82 | \ 'v': ' VISUAL ', 83 | \ 'V': ' VISUAL ', 84 | \ '': ' VISUAL ', 85 | \ 's': ' VISUAL ', 86 | \ 'S': ' VISUAL ', 87 | \ '': ' VISUAL ', 88 | \ 'R': ' REPLACE ', 89 | \ '': '', 90 | \ } 91 | < 92 | 93 | g:crystalline_separators *g:crystalline_separators* 94 | 95 | Separators to use with |crystalline#Sep()|. 96 | 97 | This is a list of objects containing: 98 | `ch` 99 | The separator character. 100 | `alt_ch` 101 | The separator character to use between sections with the same background. 102 | `dir` 103 | The direction the separator faces (either ">" or "<"). 104 | 105 | Default: 106 | >vim 107 | " These use powerline-style separators 108 | " If you're unable to see them, please use a powerline-compatible font 109 | let g:crystalline_separators = [ 110 | \ { 'ch': '', 'alt_ch': '', 'dir': '>' }, 111 | \ { 'ch': '', 'alt_ch': '', 'dir': '<' }, 112 | \ ] 113 | < 114 | 115 | FUNCTIONS *crystalline-functions* 116 | 117 | Documentation uses vimscript, but all functions can be called from Lua with: 118 | >lua 119 | local crystalline = require("crystalline") 120 | crystalline.fn() 121 | < 122 | 123 | *crystalline.HiItem()* 124 | crystalline#HiItem(group) *crystalline#HiItem()* 125 | 126 | Create a statusline highlight group item. 127 | Example: 128 | >vim 129 | " Returns '%#CrystallineA#' 130 | let l:group = crystalline#HiItem('A') 131 | < 132 | 133 | See also |crystalline-highlight-groups|. 134 | 135 | *crystalline.ModeGroup()* 136 | crystalline#ModeGroup(group) *crystalline#ModeGroup()* 137 | 138 | Prepend the current mode to the group. 139 | Example: 140 | >vim 141 | " Returns 'NormalModeA' 142 | let l:group = crystalline#ModeGroup('A') 143 | < 144 | 145 | You do not need to use this function if |g:crystalline_auto_prefix_groups| is 146 | defined. 147 | 148 | See also |crystalline-highlight-groups|. 149 | 150 | *crystalline.ModeHiItem()* 151 | crystalline#ModeHiItem(group) *crystalline#ModeHiItem()* 152 | 153 | Create a statusline highlight group item with the current mode and the group. 154 | Example: 155 | >vim 156 | " Returns '%#CrystallineNormalModeA#' 157 | let l:group = crystalline#ModeHiItem('A') 158 | < 159 | 160 | See also |crystalline-highlight-groups|. 161 | 162 | *crystalline.ModeLabel()* 163 | crystalline#ModeLabel() *crystalline#ModeLabel()* 164 | 165 | Get the current mode label. See also |g:crystalline_mode_labels|. 166 | 167 | *crystalline.ModeSection()* 168 | *crystalline#ModeSection()* 169 | crystalline#ModeSection(sep_index, left_group, right_group) 170 | 171 | Create a statusline section containing the current mode and a separator. 172 | 173 | Arguments: 174 | `sep_index` 175 | The index of a separator in |g:crystalline_separators| to use. 176 | `left_group` 177 | The left highlight group without the "Crystalline" prefix. 178 | When the separator is right facing, this is the mode group. 179 | `right_group` 180 | The right highlight group without the "Crystalline" prefix. 181 | When the separator is left facing, this is the mode group. 182 | 183 | Equivalent to: 184 | >vim 185 | " Right facing separator 186 | let l:section = crystalline#ModeHiItem(a:left_group) 187 | \ . crystalline#ModeLabel() 188 | \ . crystalline#Sep(a:sep_index, crystalline#ModeSepGroup(a:left_group), a:right_group) 189 | " Left facing separator 190 | let l:section = crystalline#ModeHiItem(a:mode_group) 191 | \ . crystalline#ModeLabel() 192 | \ . crystalline#Sep(a:sep_index, a:left_group, crystalline#ModeSepGroup(a:right_group)) 193 | < 194 | 195 | See also |crystalline-highlight-groups|. 196 | 197 | *crystalline.Sep()* 198 | crystalline#Sep(sep_index, left_group, right_group) *crystalline#Sep()* 199 | 200 | Create a separator between sections. 201 | 202 | Arguments: 203 | `sep_index` 204 | The index of the separaotr in |g:crystalline_separators|. 205 | `left_group` 206 | The highlight group to the left. 207 | `right_group` 208 | The highlight group to the right. 209 | 210 | Highlight groups must omit the "Crystalline" prefix. 211 | 212 | See also |crystalline-highlight-groups|. 213 | 214 | *crystalline.DefaultTab()* 215 | *crystalline#DefaultTab()* 216 | crystalline#DefaultTab(tabnr, bufnr, max_width, is_sel) 217 | 218 | The default tab/buffer. 219 | 220 | See also |g:CrystallineTabFn|. 221 | 222 | *crystalline.TabsOrBuffers()* 223 | crystalline#TabsOrBuffers(...) *crystalline#TabsOrBuffers()* 224 | 225 | Create a section with tabs or buffers. 226 | 227 | Arguments: 228 | `opts` 229 | 230 | `opts.is_buffers` 231 | Display buffers instead of tabs. 232 | Defaults to false. 233 | 234 | `opts.enable_sep` 235 | Enable separators. 236 | Defaults to false. 237 | 238 | `opts.sep_index` 239 | The index of a separator in |g:crystalline_separators| to use. 240 | Defaults to 0. 241 | 242 | `opts.enable_mouse` 243 | Enable mouse controls. Not compatible with buffers. 244 | Defaults to true. 245 | 246 | `opts.auto_prefix_groups 247 | Whether to prefix the current mode to highlight groups. 248 | Defaults to |g:crystalline_auto_prefix_group|. 249 | 250 | `opts.min_width` 251 | The minium visible width of the tabs/buffers. 252 | Takes precedence over `opts.max_width`. 253 | Defaults to 24. 254 | 255 | `opts.max_width` 256 | The maximum visible width of the tabs/buffers. 257 | This option should reflect available space. 258 | Defaults to the width of the screen. 259 | 260 | `opts.min_tab_width` 261 | The minimum width of individual tabs/buffers. 262 | Defaults to the space required for an empty buffer. 263 | 264 | `opts.min_tab_sel_width` 265 | The minimum width of the currently selected tab/buffer. 266 | Defaults to `opts.min_tab_width`. 267 | 268 | `opts.max_tabs` 269 | The maximum number of tabs. 270 | 271 | This should prevent the max possible statusline items from being exceeded. 272 | Statuslines and tablines can have at max 80 items in Vim. 273 | 274 | In the worst case, there are 3 items per tab: the mouse control item and 2 275 | items for the separator. 276 | There may also be an item used for the right group and an item used to 277 | terminate mouse controls. 278 | 279 | You should decrease this number if |g:CrystallineTabFn| adds items to 280 | tabs. 281 | 282 | Defaults to (80 - 2) / 3 = 26, which is enough to fit the max items. 283 | Increase this amount with caution. 284 | 285 | `opts.group_suffix` 286 | A string to append to all group names. 287 | Defaults to |g:crystalline_group_suffix|. 288 | 289 | `opts.left_group` 290 | The group to the left of the tabs/buffers. 291 | A separator will be generated between the tabs/buffers and this section. 292 | 293 | To disable, set to an empty string. 294 | 295 | Defaults to "TabFill" if `sep_index` is left facing. 296 | 297 | `opts.right_group` 298 | The group to the right of the tabs/buffers. 299 | A separator will be generated between the tabs/buffers and this section. 300 | 301 | To disable, set to an empty string. 302 | 303 | Defaults to "TabFill" if `sep_index` is right facing. 304 | 305 | See also |g:CrystallineTabFn|, |g:CrystallineHideBufferFn|. 306 | See |crystalline-highlight-groups| for more info on groups. 307 | 308 | *crystalline.Tabs()* 309 | crystalline#Tabs(...) *crystalline#Tabs()* 310 | 311 | Create a section with tabs. 312 | 313 | See also |crystalline#TabsOrBuffers()|. 314 | 315 | *crystalline.Buffers()* 316 | crystalline#Buffers(...) *crystalline#Buffers()* 317 | 318 | Create a section with buffers. 319 | 320 | See also |crystalline#TabsOrBuffers()|. 321 | 322 | *crystalline.DefaultTabline()* 323 | crystalline#DefaultTabline(...) *crystalline#DefaultTabline()* 324 | 325 | Create a tabline with tabs or buffers. 326 | Buffers are shown if only one tab is present. Otherwise, tabs are shown. 327 | 328 | See also |crystalline#DefaultTablineIsBuffers()|, 329 | |crystalline#TabTypeLabel()|, |crystalline#TabsOrBuffers()|. 330 | 331 | *crystalline.DefaultTablineIsBuffers()* 332 | *crystalline#DefaultTablineIsBuffers()* 333 | crystalline#DefaultTablineIsBuffers() 334 | 335 | Returns true when |crystalline#DefaultTabline()| shows buffers. 336 | 337 | *crystalline.TabTypeLabel()* 338 | crystalline#TabTypeLabel(...) *crystalline#TabTypeLabel()* 339 | 340 | Returns a string indicating if buffers or tabs are being shown. 341 | 342 | Arguments: 343 | `is_buffers` 344 | Whether buffers are currently shown. 345 | 346 | HIGHLIGHT GROUPS *crystalline-highlight-groups* 347 | *crystalline-themes* 348 | 349 | vim-crystalline themes typically provide these highlight groups. 350 | 351 | Some themes which come with Crystalline automatically adjust to the 352 | 'background' with light/dark modes. 353 | 354 | You do not have to use any of these groups, for example if you do not which to 355 | display the current mode, use the default groups. 356 | 357 | Example of how highlight groups might be used in your statusline/tabline: 358 | > 359 | +--------------------------------------------------------+ 360 | | TabType | Tab | TabSel | Tab | TabFill | 361 | |--------------------------------------------------------| 362 | | | 363 | | | 364 | | | 365 | | | 366 | | | 367 | | | 368 | | | 369 | | | 370 | | | 371 | | | 372 | | | 373 | | | 374 | |--------------------------------------------------------| 375 | | A | B | Fill | B | A | 376 | +--------------------------------------------------------+ 377 | < 378 | 379 | CrystallineA *CrystallineA* 380 | CrystallineB *CrystallineB* 381 | 382 | The default leftmost/rightmost and second leftmost/second rightmost statusline 383 | sections. 384 | 385 | Themes may provide more sections such as `CrystallineC`, `CrystallineD`, etc. 386 | 387 | CrystallineFill *CrystallineFill* 388 | 389 | The middle statusline section. 390 | 391 | CrystallineTab *CrystallineTab* 392 | 393 | Unselected tabs in the tabline. 394 | 395 | CrystallineTabSel *CrystallineTabSel* 396 | 397 | Default selected tabs in the tabline. 398 | 399 | CrystallineTabFill *CrystallineTabFill* 400 | 401 | The middle of the tabline. 402 | 403 | CrystallineTabType *CrystallineTabType* 404 | 405 | The color of the tab type label on the tabline which reads "BUFFERS"/"TABS". 406 | 407 | *crystalline-highlight-group-variants* 408 | CrystallineA1, CrystallineA2, CrystallineB1, CrystallineB2, etc. 409 | 410 | Variants of the statusline and tabline groups. 411 | Can be used to indicate different settings and states. 412 | 413 | Themes may provide more variants such as 3, 4, 5, etc. or custom variants. 414 | 415 | *crystalline-inactive-highlight-groups* 416 | CrystallineInactiveA, CrystallineInactiveA1, CrystallineInactiveB, etc. 417 | 418 | Statusline and tabline groups in inactive windows. 419 | 420 | *crystalline-normal-mode-groups* 421 | CrystallineNormalModeA, CrystallineNormalModeA1, CrystallineNormalModeB, etc. 422 | 423 | Statusline and tabline groups in normal mode. 424 | 425 | *crystalline-command-mode-groups* 426 | CrystallineCommandModeA, CrystallineCommandModeA1, etc. 427 | 428 | Statusline and tabline groups in command mode. 429 | 430 | *crystalline-insert-mode-groups* 431 | CrystallineInsertModeA, CrystallineInsertModeA1, CrystallineInsertModeB, etc. 432 | 433 | Statusline and tabline groups in insert mode. 434 | 435 | *crystalline-visual-mode-groups* 436 | CrystallineVisualModeA, CrystallineVisualModeA1, CrystallineVisualModeB, etc. 437 | 438 | Statusline and tabline groups in visual mode. 439 | 440 | *crystalline-replace-mode-groups* 441 | CrystallineReplaceModeA, CrystallineReplaceModeA1, etc. 442 | 443 | Statusline and tabline groups in replace mode. 444 | 445 | *crystalline-terminal-mode-groups* 446 | CrystallineTerminalModeA, CrystallineTerminalModeA1, etc. 447 | 448 | Statusline and tabline groups in terminal mode. 449 | 450 | CREATING THEMES *crystalline-creating-themes* 451 | *crystalline.GenerateTheme()* 452 | *crystalline#GenerateTheme()* 453 | 454 | Define a new theme by defining an |autoload| function which calls 455 | `crystalline#GenerateTheme()`. Example: 456 | >vim 457 | " ~/.vim/autoload/theme/my_theme.vim 458 | function! crystalline#theme#my_theme#SetTheme() abort 459 | call crystalline#GenerateTheme({ 460 | \ 'A': [[17, 190], ['#00005f', '#dfff00'], 'cterm=bold gui=bold'], 461 | \ 'B': [[255, 238], ['#ffffff', '#444444'], ''], 462 | \ 'Fill': [[85, 234], ['#9cffd3', '#202020'], ''], 463 | \ }) 464 | endfunction 465 | < 466 | 467 | Each group is a list containing the following: 468 | `[[, ], [, ], ]` 469 | 470 | Undefined groups/attributes will have the following defaults: 471 | 472 | `*Tab` `CrystallineInactiveFill` or `CrystallineFill`. 473 | `*TabSel` `*A` 474 | `*TabFill` `*Fill`. 475 | `*TabType` `*B`. 476 | 477 | Where `*` is `Inactive`, `NormalMode`, `CommandMode`, etc. 478 | 479 | Variants default to non-default variants. 480 | Only variants 1-2 are supported by default. 481 | 482 | At a minimum, define all attributes for `A`, `B`, and `Fill`. 483 | 484 | For a full example of creating a custom theme, see the solarized theme: 485 | 486 | 487 | See also |crystalline-highlight-groups|. 488 | 489 | EXAMPLE *crystalline-example* 490 | 491 | More examples: 492 | 493 | Fully featured example: 494 | 495 | >vim 496 | function! g:GroupSuffix() 497 | if mode() ==# 'i' && &paste 498 | return '2' 499 | endif 500 | if &modified 501 | return '1' 502 | endif 503 | return '' 504 | endfunction 505 | 506 | function! g:CrystallineStatuslineFn(winnr) 507 | let g:crystalline_group_suffix = g:GroupSuffix() 508 | let l:curr = a:winnr == winnr() 509 | let l:s = '' 510 | 511 | if l:curr 512 | let l:s .= crystalline#ModeSection(0, 'A', 'B') 513 | else 514 | let l:s .= crystalline#HiItem('InactiveFill') 515 | endif 516 | let l:s .= ' %f%h%w%m%r ' 517 | if l:curr 518 | let l:s .= crystalline#Sep(0, 'B', 'Fill') . ' %{fugitive#Head()}' 519 | endif 520 | 521 | let l:s .= '%=' 522 | if l:curr 523 | let l:s .= crystalline#Sep(1, 'Fill', 'B') . '%{&paste ? " PASTE " : " "}' 524 | let l:s .= crystalline#Sep(1, 'B', 'A') 525 | endif 526 | if winwidth(a:winnr) > 80 527 | let l:s .= ' %{&ft} %l/%L %2v ' 528 | else 529 | let l:s .= ' ' 530 | endif 531 | 532 | return l:s 533 | endfunction 534 | 535 | function! g:CrystallineTablineFn() 536 | let g:crystalline_group_suffix = g:GroupSuffix() 537 | let l:max_width = &columns 538 | 539 | let l:right = '%=' 540 | 541 | let l:right .= crystalline#Sep(1, 'TabFill', 'TabType') 542 | let l:max_width -= 1 543 | 544 | let l:vimlabel = has('nvim') ? ' NVIM ' : ' VIM ' 545 | let l:right .= l:vimlabel 546 | let l:max_width -= strchars(l:vimlabel) 547 | 548 | let l:max_tabs = 23 549 | 550 | return crystalline#DefaultTabline({ 551 | \ 'enable_sep': 1, 552 | \ 'max_tabs': l:max_tabs, 553 | \ 'max_width': l:max_width 554 | \ }) . l:right 555 | endfunction 556 | 557 | set showtabline=2 558 | set guioptions-=e 559 | set laststatus=2 560 | let g:crystalline_auto_prefix_groups = 1 561 | < 562 | 563 | vim:tw=78:ts=8:ft=help 564 | -------------------------------------------------------------------------------- /examples/neovim_lua_examples.md: -------------------------------------------------------------------------------- 1 | # Neovim Lua Examples 2 | 3 | These examples use neovim-flavored Lua. 4 | Examples are also available in [vimscript](../README.md#examples). 5 | 6 | All examples belong in `init.lua` before `vim-crystalline` is loaded. 7 | 8 | ## Creating a Basic Statusline 9 | 10 | ```lua 11 | function vim.g.CrystallineStatuslineFn(winnr) 12 | local s = "" 13 | 14 | -- Add file name and modification status 15 | s = s .. " %f%h%w%m%r " 16 | 17 | -- Start the right side of the statusline 18 | s = s .. "%=" 19 | 20 | -- Add file type and position info 21 | s = s .. "%{&ft} %l/%L %2v " 22 | 23 | return s 24 | end 25 | 26 | -- Always show the statusline 27 | vim.o.laststatus = 2 28 | ``` 29 | 30 | See [`:help 'statusline'`](https://vimhelp.org/options.txt.html#%27statusline%27) for more info. 31 | 32 | ## Creating a Basic Tabline 33 | 34 | ```lua 35 | function vim.g.CrystallineTablineFn() 36 | local cl = require("crystalline") 37 | return cl.DefaultTabline() 38 | end 39 | 40 | -- Always show the tabline 41 | vim.o.showtabline = 2 42 | ``` 43 | 44 | See [`:help 'tabline'`](https://vimhelp.org/options.txt.html#%27statusline%27) for more info. 45 | 46 | ## Hiding Sections 47 | 48 | ```lua 49 | function vim.g.CrystallineStatuslineFn(winnr) 50 | local s = "" 51 | 52 | s = s .. " %f%h%w%m%r " 53 | 54 | s = s .. "%=" 55 | 56 | -- Only add this section in active windows 57 | if winnr == vim.fn.winnr() then 58 | s = s .. "%{&ft} " 59 | end 60 | -- Only add this section in wide enough windows 61 | if vim.fn.winwidth(winnr) >= 80 then 62 | s = s .. "%l/%L %2v " 63 | end 64 | 65 | return s 66 | end 67 | 68 | vim.o.laststatus = 2 69 | ``` 70 | 71 | ## Using Highlight Groups 72 | 73 | ```lua 74 | function vim.g.CrystallineStatuslineFn(winnr) 75 | local cl = require("crystalline") 76 | local s = "" 77 | 78 | if winnr == vim.fn.winnr() then 79 | -- Start highlighting section A 80 | s = s .. cl.HiItem("A") 81 | else 82 | -- Start highlighting Fill section for inactive windows 83 | s = s .. cl.HiItem('InactiveFill') 84 | end 85 | 86 | s = s .. " %f%h%w%m%r " 87 | 88 | return s 89 | end 90 | 91 | vim.o.laststatus = 2 92 | -- Default theme 93 | vim.g.crystalline_theme = "default" 94 | ``` 95 | 96 | See [`:help crystalline-highlight-groups`](https://raw.githubusercontent.com/rbong/vim-crystalline/master/doc/crystalline.txt) 97 | for the full list of groups. 98 | 99 | See [screenshots](../README.md#obligatory-colorful-theme-screenshots) 100 | for the full list of themes. 101 | 102 | ## Using Separators 103 | 104 | ```lua 105 | function vim.g.CrystallineStatuslineFn(winnr) 106 | local cl = require("crystalline") 107 | local s = "" 108 | 109 | s = s .. cl.HiItem("A") 110 | 111 | s = s .. " %f%h%w%m%r " 112 | 113 | -- Add separator 0 between section A and the statusline fill section 114 | s = s .. cl.Sep(0, "A", "Fill") 115 | 116 | s = s .. "%=" 117 | 118 | -- Add separator 1 between the fill section and section A 119 | s = s .. cl.Sep(1, "Fill", "A") 120 | 121 | s = s .. "%{&ft} %l/%L %2v " 122 | 123 | return s 124 | end 125 | 126 | function vim.g.CrystallineTablineFn() 127 | local cl = require("crystalline") 128 | -- Add separators to the tabline 129 | return cl.DefaultTabline({ enable_sep = true }) 130 | end 131 | 132 | vim.o.laststatus = 2 133 | vim.o.showtabline = 2 134 | -- By default, these are powerline-style separators 135 | vim.g.crystalline_separators = { 136 | { ch = ">", alt_ch = "|", dir = ">" }, 137 | { ch = "<", alt_ch = "|", dir = "<" } 138 | } 139 | ``` 140 | 141 | ## Using Mode Colors 142 | 143 | Using mode colors manually: 144 | 145 | ```lua 146 | function vim.g.CrystallineStatuslineFn(winnr) 147 | local cl = require("crystalline") 148 | local s = "" 149 | 150 | -- In different modes, this will be 'NormalModeA', 'InsertModeA', etc. 151 | s = s .. cl.ModeHiItem("A") 152 | 153 | s = s .. " %f%h%w%m%r " 154 | 155 | -- The mode prefix is added to all separator groups 156 | s = s .. cl.Sep(0, cl.ModeGroup("A"), cl.ModeGroup("Fill")) 157 | 158 | return s 159 | end 160 | 161 | function vim.g.CrystallineTablineFn() 162 | local cl = require("crystalline") 163 | -- auto_prefix_groups automatically uses mode colors 164 | return cl.DefaultTabline({ auto_prefix_groups = true }) 165 | end 166 | 167 | vim.o.laststatus = 2 168 | vim.o.showtabline = 2 169 | ``` 170 | 171 | Using mode colors automatically: 172 | 173 | ```lua 174 | function vim.g.CrystallineStatuslineFn(winnr) 175 | local cl = require("crystalline") 176 | local s = "" 177 | 178 | -- In different modes, this will be 'NormalModeA', 'InsertModeA', etc. 179 | -- In inactive windows, this will be 'InactiveA' 180 | s = s .. cl.HiItem("A") 181 | 182 | s = s .. " %f%h%w%m%r " 183 | 184 | -- The prefix will automatically be added to separator groups 185 | s = s .. cl.Sep(0, "A", "Fill") 186 | 187 | return s 188 | end 189 | 190 | function vim.g.CrystallineTablineFn() 191 | local cl = require("crystalline") 192 | -- auto_prefix_groups will default to true 193 | -- 'Inactive*' groups will not be used in the tabline 194 | return cl.DefaultTabline() 195 | end 196 | 197 | vim.o.laststatus = 2 198 | vim.o.showtabline = 2 199 | -- This enables auto mode/inactive colors 200 | -- All functions work with this option 201 | vim.g.crystalline_auto_prefix_groups = true 202 | ``` 203 | 204 | Add a mode section: 205 | 206 | ```lua 207 | function vim.g.CrystallineStatuslineFn(winnr) 208 | local cl = require("crystalline") 209 | local s = "" 210 | 211 | -- Automatically create a mode highlight group, mode label, and separator 212 | -- Same arguments as crystalline.sep() 213 | s = s .. cl.ModeSection(0, "A", "B") 214 | 215 | s = s .. " %f%h%w%m%r " 216 | 217 | s = s .. cl.Sep(0, "B", "Fill") 218 | 219 | return s 220 | end 221 | 222 | vim.o.laststatus = 2 223 | ``` 224 | 225 | ## Using Color Variants 226 | 227 | Using color variants manually: 228 | 229 | ```lua 230 | local function GroupSuffix() 231 | if vim.fn.mode() == 'i' and vim.o.paste then 232 | -- Add the suffix "2" to all groups 233 | return "2" 234 | end 235 | if vim.o.modified then 236 | -- Add the suffix "1" to all groups 237 | return "1" 238 | end 239 | -- Don"t add any suffix 240 | return "" 241 | end 242 | 243 | function vim.g.CrystallineStatuslineFn(winnr) 244 | local cl = require("crystalline") 245 | local s = "" 246 | 247 | -- Add the variant onto the end of the highlight item 248 | s = s .. cl.HiItem("Fill" .. GroupSuffix()) 249 | 250 | s = s .. " %f%h%w%m%r " 251 | 252 | return s 253 | end 254 | 255 | function vim.g.CrystallineTablineFn() 256 | local cl = require("crystalline") 257 | -- Add the variant onto the end of all tabline groups 258 | return cl.DefaultTabline({ group_suffix = GroupSuffix() }) 259 | end 260 | 261 | vim.o.laststatus = 2 262 | vim.o.showtabline = 2 263 | vim.g.crystalline_auto_prefix_groups = true 264 | ``` 265 | 266 | Using color variants automatically: 267 | 268 | ```lua 269 | local function GroupSuffix() 270 | if vim.fn.mode() == 'i' and vim.o.paste then 271 | return "2" 272 | end 273 | if vim.o.modified then 274 | return "1" 275 | end 276 | return "" 277 | end 278 | 279 | function vim.g.CrystallineStatuslineFn(winnr) 280 | local cl = require("crystalline") 281 | local s = "" 282 | 283 | -- Automatically add the suffix onto the end of all groups 284 | -- Works with all functions 285 | vim.g.crystalline_group_suffix = GroupSuffix() 286 | 287 | s = s .. cl.HiItem("Fill") 288 | 289 | s = s .. " %f%h%w%m%r " 290 | 291 | return s 292 | end 293 | 294 | function vim.g.CrystallineTablineFn() 295 | local cl = require("crystalline") 296 | vim.g.crystalline_group_suffix = GroupSuffix() 297 | return cl.DefaultTabline() 298 | end 299 | 300 | vim.o.laststatus = 2 301 | vim.o.showtabline = 2 302 | vim.g.crystalline_auto_prefix_groups = true 303 | ``` 304 | 305 | There are 2 variants to use in built-in themes. 306 | 307 | ## Showing More Statusline Information 308 | 309 | ```lua 310 | function vim.g.CrystallineStatuslineFn(winnr) 311 | local s = "" 312 | 313 | s = s .. " %f%h%w%m%r " 314 | 315 | -- Add the current branch from vim-fugitive 316 | -- Plugins often provide functions for the statusline 317 | s = s .. "%{fugitive#Head()} " 318 | 319 | s = s .. "%=" 320 | 321 | -- Show settings in the statusline 322 | s = s .. "%{&paste ? 'PASTE ' : ' '}" 323 | 324 | return s 325 | end 326 | 327 | vim.o.laststatus = 2 328 | ``` 329 | 330 | ## Showing More Tabline Information 331 | 332 | ```lua 333 | function vim.g.CrystallineTablineFn() 334 | local cl = require("crystalline") 335 | local max_width = vim.o.columns 336 | 337 | -- Start the right side of the tabline 338 | local right = "%=" 339 | 340 | -- Add a separator 341 | -- Reuse the TabType group for the right section 342 | right = right .. cl.Sep(1, "TabFill", "TabType") 343 | -- Subtract the width of the separator 344 | max_width = max_width - 1 345 | 346 | -- Add a label indicating if vim or neovim is being used 347 | local vimlabel = " NVIM " 348 | right = right .. vimlabel 349 | -- Use strchars() to get the real visible width 350 | max_width = max_width - vim.fn.strchars(vimlabel) 351 | 352 | -- Reduce the number of max tabs to fit new tabline items 353 | local max_tabs = 23 354 | 355 | return cl.DefaultTabline({ max_tabs = max_tabs, max_width = max_width }) .. right 356 | end 357 | 358 | vim.o.showtabline = 2 359 | ``` 360 | 361 | ## Full Example 362 | 363 | ```lua 364 | local function GroupSuffix() 365 | if vim.fn.mode() == 'i' and vim.o.paste then 366 | return "2" 367 | end 368 | if vim.o.modified then 369 | return "1" 370 | end 371 | return "" 372 | end 373 | 374 | function vim.g.CrystallineStatuslineFn(winnr) 375 | local cl = require("crystalline") 376 | vim.g.crystalline_group_suffix = GroupSuffix() 377 | local curr = winnr == vim.fn.winnr() 378 | local s = "" 379 | 380 | if curr then 381 | s = s .. cl.ModeSection(0, "A", "B") 382 | else 383 | s = s .. cl.HiItem("Fill") 384 | end 385 | s = s .. " %f%h%w%m%r " 386 | if curr then 387 | s = s .. cl.Sep(0, "B", "Fill") .. " %{fugitive#Head()}" 388 | end 389 | 390 | s = s .. "%=" 391 | if curr then 392 | s = s .. cl.Sep(1, "Fill", "B") .. "%{&paste ? ' PASTE ' : ' '}" 393 | s = s .. cl.Sep(1, "B", "A") 394 | end 395 | if vim.fn.winwidth(winnr) > 80 then 396 | s = s .. " %{&ft} %l/%L %2v " 397 | else 398 | s = s .. " " 399 | end 400 | 401 | return s 402 | end 403 | 404 | function vim.g.CrystallineTablineFn() 405 | local cl = require("crystalline") 406 | local max_width = vim.o.columns 407 | local right = "%=" 408 | 409 | right = right .. cl.Sep(1, "TabFill", "TabType") 410 | max_width = max_width - 1 411 | 412 | local vimlabel = " NVIM " 413 | right = right .. vimlabel 414 | max_width = max_width - vim.fn.strchars(vimlabel) 415 | 416 | max_tabs = 23 417 | 418 | return cl.DefaultTabline({ 419 | enable_sep = true, 420 | max_tabs = max_tabs, 421 | max_width = max_width 422 | }) .. right 423 | end 424 | 425 | vim.o.showtabline = 2 426 | vim.o.laststatus = 2 427 | vim.g.crystalline_auto_prefix_groups = 1 428 | ``` 429 | -------------------------------------------------------------------------------- /legacy/autoload/crystalline.vim: -------------------------------------------------------------------------------- 1 | if has('vim9script') || has('nvim') 2 | finish 3 | endif 4 | 5 | " Statusline Utils {{{ 6 | 7 | function! crystalline#PlainSep(sep_index, left_group, right_group) abort 8 | let l:key = a:sep_index . a:left_group . a:right_group 9 | if !has_key(g:crystalline_sep_cache, l:key) 10 | let g:crystalline_sep_cache[l:key] = crystalline#GetSep(a:sep_index, a:left_group, a:right_group) 11 | endif 12 | return g:crystalline_sep_cache[l:key] 13 | endfunction 14 | 15 | function! crystalline#Sep(sep_index, left_group, right_group) abort 16 | if g:crystalline_auto_prefix_groups 17 | if g:crystalline_inactive 18 | let l:left_group = 'Inactive' . a:left_group . g:crystalline_group_suffix 19 | let l:right_group = 'Inactive' . a:right_group . g:crystalline_group_suffix 20 | else 21 | let l:m = g:crystalline_mode_hi_groups[mode()] 22 | let l:left_group = l:m . a:left_group . g:crystalline_group_suffix 23 | let l:right_group = l:m . a:right_group . g:crystalline_group_suffix 24 | endif 25 | else 26 | let l:left_group = a:left_group . g:crystalline_group_suffix 27 | let l:right_group = a:right_group . g:crystalline_group_suffix 28 | endif 29 | let l:key = a:sep_index . l:left_group . l:right_group 30 | if !has_key(g:crystalline_sep_cache, l:key) 31 | let g:crystalline_sep_cache[l:key] = crystalline#GetSep(a:sep_index, l:left_group, l:right_group) 32 | endif 33 | return g:crystalline_sep_cache[l:key] 34 | endfunction 35 | 36 | " }}} 37 | 38 | " Tabline Utils {{{ 39 | 40 | function! crystalline#DefaultTab(tab, buf, max_width, is_sel) abort 41 | " Return early 42 | if a:max_width <= 0 43 | return ['', 0] 44 | endif 45 | 46 | " Get left/right components 47 | let l:left = g:crystalline_tab_left 48 | let l:right = getbufvar(a:buf, '&mod') ? g:crystalline_tab_mod : g:crystalline_tab_nomod 49 | let l:lr_width = strchars(l:left) + strchars(l:right) 50 | let l:max_name_width = a:max_width - l:lr_width 51 | 52 | " Get name 53 | let l:name = bufname(a:buf) 54 | if l:name ==# '' 55 | let l:name = g:crystalline_tab_empty 56 | let l:name_width = strchars(l:name) 57 | else 58 | let l:name = pathshorten(l:name) 59 | let l:name_width = strchars(l:name) 60 | if l:name_width > l:max_name_width 61 | let l:split_name = split(l:name, '/') 62 | if len(l:split_name) > g:crystalline_tab_min_path_parts 63 | let l:name = join(l:split_name[-g:crystalline_tab_min_path_parts:], '/') 64 | let l:name_width = strchars(l:name) 65 | endif 66 | endif 67 | endif 68 | 69 | " Shorten tab 70 | if l:max_name_width <= 0 71 | let l:tab = strcharpart(l:name, l:name_width - a:max_width) 72 | let l:tabwidth = min([l:name_width, a:max_width]) 73 | else 74 | let l:tab = l:left . strcharpart(l:name, l:name_width - l:max_name_width) . l:right 75 | let l:tabwidth = l:lr_width + min([l:name_width, l:max_name_width]) 76 | endif 77 | 78 | return [crystalline#EscapeStatuslineString(l:tab), l:tabwidth] 79 | endfunction 80 | 81 | function! crystalline#DefaultHideBuffer(buf) abort 82 | return (!buflisted(a:buf) && bufnr('%') != a:buf) || getbufvar(a:buf, '&ft') ==# 'qf' 83 | endfunction 84 | 85 | function! crystalline#TabsOrBuffers(...) abort 86 | " Get args 87 | let l:opts = get(a:, 1, {}) 88 | 89 | " Get options 90 | let l:is_buffers = get(l:opts, 'is_buffers', 0) 91 | let l:enable_mouse = !l:is_buffers && get(l:opts, 'enable_mouse', 1) 92 | let l:enable_sep = get(l:opts, 'enable_sep', 0) 93 | let l:sep_index = get(l:opts, 'sep_index', 0) 94 | let l:sep = get(g:crystalline_separators, l:sep_index, { 'ch': '' }) 95 | let l:dir = get(l:opts, 'dir', l:sep.dir) 96 | let l:min_width = get(l:opts, 'min_width', 24) 97 | let l:max_width = get(l:opts, 'max_width', max([&columns, l:min_width])) 98 | let l:min_tab_width = get(l:opts, 'min_tab_width', 99 | \ strchars(g:crystalline_tab_left . g:crystalline_tab_empty) 100 | \ + max([strchars(g:crystalline_tab_mod), strchars(g:crystalline_tab_nomod)])) 101 | let l:min_tab_sel_width = get(l:opts, 'min_tab_width', l:min_tab_width) 102 | let l:max_tabs = max([1, get(l:opts, 'max_tabs', 26)]) 103 | 104 | " Get group options 105 | let l:auto_prefix_groups = get(l:opts, 'auto_prefix_groups', g:crystalline_auto_prefix_groups) 106 | let l:group_suffix = get(l:opts, 'group_suffix', g:crystalline_group_suffix) 107 | if l:auto_prefix_groups 108 | let l:m = g:crystalline_mode_hi_groups[mode()] 109 | let l:tab_group = get(l:opts, 'tab_group', l:m . 'Tab' . l:group_suffix) 110 | let l:tab_sel_group = get(l:opts, 'tab_sel_group', l:m . 'TabSel' . l:group_suffix) 111 | let l:tab_fill_group = get(l:opts, 'tab_fill_group', l:m . 'TabFill' . l:group_suffix) 112 | else 113 | let l:tab_group = get(l:opts, 'tab_group', 'Tab' . l:group_suffix) 114 | let l:tab_sel_group = get(l:opts, 'tab_sel_group', 'TabSel' . l:group_suffix) 115 | let l:tab_fill_group = get(l:opts, 'tab_fill_group', 'TabFill' . l:group_suffix) 116 | endif 117 | let l:left_group = get(l:opts, 'left_group', l:dir ==# '<' ? l:tab_fill_group : '') 118 | let l:right_group = get(l:opts, 'right_group', l:dir ==# '<' ? '' : l:tab_fill_group) 119 | 120 | " Init variables 121 | let l:o = '' 122 | let l:tab_count = 0 123 | let l:width = 0 124 | let l:sep_width = l:enable_sep ? strchars(l:sep.ch) : 0 125 | let l:first_group = l:tab_group 126 | let l:last_group = l:tab_group 127 | 128 | " Make sure there's room for leftmost/rightmost separator 129 | let l:enable_left_sep = l:enable_sep && l:left_group !=# '' 130 | let l:enable_right_sep = l:enable_sep && l:right_group !=# '' 131 | let l:lr_sep_width = 0 132 | if l:enable_left_sep 133 | " Count left sep 134 | let l:width += l:sep_width 135 | let l:lr_sep_width = l:sep_width 136 | endif 137 | if l:enable_right_sep 138 | " Count right sep 139 | let l:width += l:sep_width 140 | let l:lr_sep_width = l:sep_width 141 | endif 142 | 143 | " Get tab data 144 | let l:tabselidx = -1 145 | let l:ntabs = 0 146 | let l:tabbufs = [] 147 | if l:is_buffers 148 | let l:bufsel = bufnr('%') 149 | if exists('*getbufinfo') 150 | for l:buf in getbufinfo() 151 | let l:buf_bufnr = l:buf.bufnr 152 | if !g:CrystallineHideBufferFn(l:buf_bufnr) 153 | if l:bufsel == l:buf_bufnr 154 | let l:tabselidx = l:ntabs 155 | endif 156 | call add(l:tabbufs, l:buf_bufnr) 157 | let l:ntabs += 1 158 | endif 159 | endfor 160 | else 161 | for l:bufnr in range(1, bufnr('$')) 162 | if bufexists(l:bufnr) && !g:CrystallineHideBufferFn(l:bufnr) 163 | if l:bufsel == l:bufnr 164 | let l:tabselidx = l:ntabs 165 | endif 166 | call add(l:tabbufs, l:bufnr) 167 | let l:ntabs += 1 168 | endif 169 | endfor 170 | endif 171 | else 172 | let l:tabselidx = tabpagenr() - 1 173 | let l:ntabs = tabpagenr('$') 174 | for l:tabidx in range(1, l:ntabs) 175 | call add(l:tabbufs, tabpagebuflist(l:tabidx)[tabpagewinnr(l:tabidx) - 1]) 176 | endfor 177 | endif 178 | 179 | " Calculate remaining width for tabs 180 | let l:remaining_width = l:max_width - l:lr_sep_width 181 | " Calculate max tab width 182 | let l:max_tab_width = max([l:remaining_width / min([l:ntabs, l:max_tabs]), l:min_tab_width + l:sep_width]) - l:sep_width 183 | " Calculate max selected tab width 184 | let l:max_tab_sel_width = max([l:max_tab_width, l:min_tab_sel_width]) 185 | " Handle different width for selected tabs 186 | if l:tabselidx >= 0 && l:max_tab_sel_width != l:max_tab_width 187 | " Recalculate remaining width for non-selected tabs 188 | let l:remaining_width = l:max_width - l:max_tab_sel_width - l:lr_sep_width 189 | " Recalculate max tab width 190 | let l:max_tab_width = max([l:remaining_width / min([l:ntabs - 1, l:max_tabs]), l:min_tab_width + l:sep_width]) - l:sep_width 191 | endif 192 | 193 | " Add selected tab first to ensure it's always added 194 | if l:tabselidx >= 0 195 | let [l:tab, l:tabwidth] = g:CrystallineTabFn(l:tabselidx + 1, l:tabbufs[l:tabselidx], l:max_tab_sel_width, v:true) 196 | if l:enable_mouse 197 | let l:tab = '%' . (l:tabselidx + 1) . 'T' . l:tab 198 | endif 199 | let l:o .= l:tab 200 | let l:tab_count += 1 201 | let l:width += l:tabwidth 202 | let l:first_group = l:tab_sel_group 203 | let l:last_group = l:tab_sel_group 204 | endif 205 | 206 | " Add at least one tab to left of selected if present and there's space 207 | let l:add_left_tabs = l:tabselidx >= 1 && l:width < l:max_width && l:tab_count < l:max_tabs 208 | if l:add_left_tabs 209 | let [l:tab, l:tabwidth] = g:CrystallineTabFn(l:tabselidx, l:tabbufs[l:tabselidx - 1], l:max_tab_width, v:false) 210 | if l:enable_sep 211 | let l:tab .= crystalline#PlainSep(l:sep_index, l:tab_group, l:first_group) 212 | let l:tabwidth += l:sep_width 213 | elseif l:first_group ==# l:tab_sel_group 214 | let l:tab .= '%#Crystalline' . l:tab_sel_group . '#' 215 | endif 216 | if l:enable_mouse 217 | let l:tab = '%' . l:tabselidx . 'T' . l:tab . '' 218 | endif 219 | let l:add_left_tabs = l:width + l:tabwidth <= l:max_width 220 | if l:add_left_tabs 221 | let l:o = l:tab . l:o 222 | let l:tab_count += 1 223 | let l:width += l:tabwidth 224 | let l:first_group = l:tab_group 225 | endif 226 | endif 227 | 228 | " Add at least one tab to right of selected if present and there's space 229 | let l:add_right_tabs = l:width < l:max_width && l:tabselidx + 1 < l:ntabs && l:tab_count < l:max_tabs 230 | if l:add_right_tabs 231 | let [l:tab, l:tabwidth] = g:CrystallineTabFn(l:tabselidx + 2, l:tabbufs[l:tabselidx + 1], l:max_tab_width, v:false) 232 | if l:enable_mouse 233 | let l:tab = '%' . (l:tabselidx + 2) . 'T' . l:tab 234 | endif 235 | if l:enable_sep 236 | let l:sep = crystalline#PlainSep(l:sep_index, l:last_group, l:tab_group) 237 | let l:tab = l:sep . l:tab 238 | let l:tabwidth += l:sep_width 239 | elseif l:last_group ==# l:tab_sel_group 240 | let l:tab = '%#Crystalline' . l:tab_group . '#' . l:tab 241 | endif 242 | let l:add_right_tabs = l:width + l:tabwidth <= l:max_width 243 | if l:add_right_tabs 244 | let l:o .= l:tab 245 | let l:tab_count += 1 246 | let l:width += l:tabwidth 247 | let l:last_group = l:tab_group 248 | endif 249 | endif 250 | 251 | " Get tab separator 252 | if l:enable_sep 253 | let l:tab_sep = crystalline#PlainSep(l:sep_index, l:tab_group, l:tab_group) 254 | endif 255 | 256 | " Add tabs to left of selected 257 | let l:tabidx = l:add_left_tabs ? l:tabselidx - 2 : -1 258 | while l:tabidx >= 0 && l:width < l:max_width && l:tab_count < l:max_tabs 259 | let [l:tab, l:tabwidth] = g:CrystallineTabFn(l:tabidx + 1, l:tabbufs[l:tabidx], l:max_tab_width, v:false) 260 | if l:enable_sep 261 | let l:tab .= l:tab_sep 262 | let l:tabwidth += l:sep_width 263 | endif 264 | if l:enable_mouse 265 | let l:tab = '%' . (l:tabidx + 1) . 'T' . l:tab 266 | endif 267 | if l:width + l:tabwidth > l:max_width 268 | break 269 | endif 270 | let l:o = l:tab . l:o 271 | let l:tab_count += 1 272 | let l:width += l:tabwidth 273 | let l:tabidx -= 1 274 | endwhile 275 | 276 | " Add other tabs to right of selected 277 | let l:tabidx = l:add_right_tabs ? l:tabselidx + 2 : l:ntabs 278 | while l:tabidx < l:ntabs && l:width < l:max_width && l:tab_count < l:max_tabs 279 | let [l:tab, l:tabwidth] = g:CrystallineTabFn(l:tabidx + 1, l:tabbufs[l:tabidx], l:max_tab_width, v:false) 280 | if l:enable_mouse 281 | let l:tab = '%' . (l:tabidx + 1) . 'T' . l:tab 282 | endif 283 | if l:enable_sep 284 | let l:tab = l:tab_sep . l:tab 285 | let l:tabwidth += l:sep_width 286 | endif 287 | if l:width + l:tabwidth > l:max_width 288 | break 289 | endif 290 | let l:o .= l:tab 291 | let l:tab_count += 1 292 | let l:width += l:tabwidth 293 | let l:tabidx += 1 294 | endwhile 295 | 296 | if l:enable_left_sep 297 | " Draw left separator 298 | let l:o = crystalline#PlainSep(l:sep_index, l:left_group, l:first_group) . l:o 299 | else 300 | " Draw first group 301 | let l:o = '%#Crystalline' . l:first_group . '#' . l:o 302 | endif 303 | 304 | if l:enable_right_sep 305 | " Draw right separator 306 | let l:o .= crystalline#PlainSep(l:sep_index, l:last_group, l:right_group) 307 | elseif l:right_group !=# '' 308 | " Draw right group 309 | let l:o .= '%#Crystalline' . l:right_group . '#' 310 | endif 311 | 312 | " End final tab 313 | if l:enable_mouse 314 | let l:o .= '%T' 315 | endif 316 | 317 | return l:o 318 | endfunction 319 | 320 | " }}} 321 | 322 | " vim:set et sw=2 ts=2 fdm=marker: 323 | -------------------------------------------------------------------------------- /lua/crystalline.lua: -------------------------------------------------------------------------------- 1 | local module = {} 2 | 3 | -- Internal Helpers {{{ 4 | 5 | -- Reduce object lookup time 6 | local vim_g = vim.g 7 | local vim_o = vim.o 8 | local vim_fn = vim.fn 9 | local buflisted = vim_fn.buflisted 10 | local bufloaded = vim_fn.bufloaded 11 | local bufname = vim_fn.bufname 12 | local bufnr = vim_fn.bufnr 13 | local getbufinfo = vim_fn.getbufinfo 14 | local getbufvar = vim_fn.getbufvar 15 | local mode = vim_fn.mode 16 | local pathshorten = vim_fn.pathshorten 17 | local slice = vim.list_slice 18 | local split = vim_fn.split 19 | local strcharpart = vim_fn.strcharpart 20 | local strchars = vim_fn.strchars 21 | local tabpagebuflist = vim_fn.tabpagebuflist 22 | local tabpagenr = vim_fn.tabpagenr 23 | local tabpagewinnr = vim_fn.tabpagewinnr 24 | 25 | local function bool(value) 26 | return (value == true or value == 1) and true or false 27 | end 28 | 29 | local function get_default(dict, key, default) 30 | local value = dict[key] 31 | if value == nil then 32 | return default 33 | end 34 | return value 35 | end 36 | 37 | -- }}} 38 | 39 | -- Vim Alias Exports {{{ 40 | 41 | local crystalline_fns = { 42 | "EscapeStatuslineString", 43 | "LeftPad", 44 | "RightPad", 45 | "Profile", 46 | "Group", 47 | "ModeGroup", 48 | "ModeSepGroup", 49 | "HiItem", 50 | "ModeHiItem", 51 | "ModeLabel", 52 | "ModeSection", 53 | "UpdateStatusline", 54 | "GetSep", 55 | "UpdateTabline", 56 | "Tabs", 57 | "Buffers", 58 | "TabTypeLabel", 59 | "DefaultTablineIsBuffers", 60 | "DefaultTabline", 61 | "SynIDattrs", 62 | "GetHlAttrs", 63 | "GenerateHi", 64 | "GetEmptyThemeAttrs", 65 | "SetThemeFallbackAttrs", 66 | "GenerateTheme", 67 | "GenerateSepHi", 68 | "GetAirlineAttrs", 69 | "GetAirlineStyleAttrs", 70 | "PortAirlineTheme", 71 | "InitStatusline", 72 | "ClearStatusline", 73 | "InitTabline", 74 | "ClearTabline", 75 | "ApplyCurrentTheme", 76 | "SetTheme", 77 | "ClearTheme" 78 | } 79 | 80 | for _, fn in pairs(crystalline_fns) do 81 | module[fn] = vim_fn["crystalline#" .. fn] 82 | end 83 | 84 | -- }}} 85 | 86 | -- Statusline Utils {{{ 87 | 88 | function module.PlainSep(sep_index, left_group, right_group) 89 | local cache = vim_g.crystalline_sep_cache 90 | local key = sep_index .. left_group .. right_group 91 | if cache[key] == nil then 92 | cache[key] = module.GetSep(sep_index, left_group, right_group) 93 | end 94 | return cache[key] 95 | end 96 | 97 | function module.Sep(sep_index, _left_group, _right_group) 98 | local cache = vim_g.crystalline_sep_cache 99 | local left_group 100 | local right_group 101 | if bool(vim_g.crystalline_auto_prefix_groups) then 102 | if bool(vim_g.crystalline_inactive) then 103 | left_group = 'Inactive' .. _left_group .. vim_g.crystalline_group_suffix 104 | right_group = 'Inactive' .. _right_group .. vim_g.crystalline_group_suffix 105 | else 106 | local m = vim_g.crystalline_mode_hi_groups[mode()] 107 | left_group = m .. _left_group .. vim_g.crystalline_group_suffix 108 | right_group = m .. _right_group .. vim_g.crystalline_group_suffix 109 | end 110 | else 111 | left_group = _left_group .. vim_g.crystalline_group_suffix 112 | right_group = _right_group .. vim_g.crystalline_group_suffix 113 | end 114 | local key = sep_index .. left_group .. right_group 115 | if cache[key] == nil then 116 | cache[key] = module.GetSep(sep_index, left_group, right_group) 117 | end 118 | return cache[key] 119 | end 120 | 121 | -- }}} 122 | 123 | -- Tabline Utils {{{ 124 | 125 | function module.DefaultTab(tab, buf, max_width, is_sel) 126 | -- Return early 127 | if max_width <= 0 then 128 | return { '', 0 } 129 | end 130 | 131 | -- Get left/right components 132 | local left = vim_g.crystalline_tab_left 133 | local right = bool(getbufvar(buf, '&mod')) and vim_g.crystalline_tab_mod or vim_g.crystalline_tab_nomod 134 | local lr_width = strchars(left) + strchars(right) 135 | local max_name_width = max_width - lr_width 136 | 137 | -- Get name 138 | local name = bufname(buf) 139 | local name_width 140 | if name == '' then 141 | name = vim_g.crystalline_tab_empty 142 | name_width = strchars(name) 143 | else 144 | name = pathshorten(name) 145 | name_width = strchars(name) 146 | if name_width > max_name_width then 147 | local split_name = split(name, '/') 148 | local split_name_len = #split_name 149 | if split_name_len > vim_g.crystalline_tab_min_path_parts then 150 | name = table.concat(slice(split_name, 1 + split_name_len - vim_g.crystalline_tab_min_path_parts), '/') 151 | name_width = strchars(name) 152 | end 153 | end 154 | end 155 | 156 | -- Shorten tab 157 | local tab 158 | local tabwidth 159 | if max_name_width <= 0 then 160 | tab = strcharpart(name, name_width - max_width) 161 | tabwidth = math.min(name_width, max_width) 162 | else 163 | tab = left .. strcharpart(name, name_width - max_name_width) .. right 164 | tabwidth = lr_width + math.min(name_width, max_name_width) 165 | end 166 | 167 | return { module.EscapeStatuslineString(tab), tabwidth } 168 | end 169 | 170 | module.debug = {} 171 | 172 | function module.DefaultHideBuffer(buf) 173 | return ((not bool(buflisted(buf))) and bufnr('%') ~= buf) or getbufvar(buf, '&ft') == 'qf' 174 | end 175 | 176 | local default_tabs_or_buffers_opts = vim.empty_dict() 177 | function module.TabsOrBuffers(opts) 178 | -- Get args 179 | opts = opts or default_tabs_or_buffers_opts 180 | 181 | -- Get options 182 | local is_buffers = bool(get_default(opts, "is_buffers", 0)) 183 | local enable_mouse = not is_buffers and bool(get_default(opts, "enable_mouse", 1)) 184 | local enable_sep = bool(get_default(opts, "enable_sep", 0)) 185 | local sep_index = get_default(opts, "sep_index", 0) 186 | local sep = get_default(vim_g.crystalline_separators, sep_index + 1, { ch = "" }) 187 | local dir = get_default(opts, "dir", sep.dir) 188 | local min_width = get_default(opts, "min_width", 24) 189 | local max_width = get_default(opts, "max_width", math.max(vim_o.columns, min_width)) 190 | local min_tab_width = get_default( 191 | opts, 192 | "min_tab_width", 193 | strchars(vim_g.crystalline_tab_left .. vim_g.crystalline_tab_empty) 194 | + math.max(strchars(vim_g.crystalline_tab_mod), strchars(vim_g.crystalline_tab_nomod)) 195 | ) 196 | local min_tab_sel_width = get_default(opts, "min_tab_width", min_tab_width) 197 | local max_tabs = math.max(1, get_default(opts, "max_tabs", 26)) 198 | 199 | -- Get group options 200 | local auto_prefix_groups = bool(get_default(opts, "auto_prefix_groups", vim_g.crystalline_auto_prefix_groups)) 201 | local group_suffix = get_default(opts, "group_suffix", vim_g.crystalline_group_suffix) 202 | local tab_group 203 | local tab_sel_group 204 | local tab_fill_group 205 | if auto_prefix_groups then 206 | local m = vim_g.crystalline_mode_hi_groups[mode()] 207 | tab_group = get_default(opts, "tab_group", m .. "Tab" .. group_suffix) 208 | tab_sel_group = get_default(opts, "tab_sel_group", m .. "TabSel" .. group_suffix) 209 | tab_fill_group = get_default(opts, "tab_fill_group", m .. "TabFill" .. group_suffix) 210 | else 211 | tab_group = get_default(opts, "tab_group", "Tab" .. group_suffix) 212 | tab_sel_group = get_default(opts, "tab_sel_group", "TabSel" .. group_suffix) 213 | tab_fill_group = get_default(opts, "tab_fill_group", "TabFill" .. group_suffix) 214 | end 215 | local left_group = get_default(opts, "left_group", dir == "<" and tab_fill_group or "") 216 | local right_group = get_default(opts, "right_group", dir == "<" and "" or tab_fill_group) 217 | 218 | -- Init variables 219 | local o = "" 220 | local tab_count = 0 221 | local width = 0 222 | local sep_width = enable_sep and strchars(sep.ch) or 0 223 | local first_group = tab_group 224 | local last_group = tab_group 225 | 226 | -- Make sure there's room for leftmost/rightmost separator 227 | local enable_left_sep = enable_sep and left_group ~= "" 228 | local enable_right_sep = enable_sep and right_group ~= "" 229 | local lr_sep_width = 0 230 | if enable_left_sep then 231 | -- Count left sep 232 | width = width + sep_width 233 | lr_sep_width = sep_width 234 | end 235 | if enable_right_sep then 236 | -- Count right sep 237 | width = width + sep_width 238 | lr_sep_width = sep_width 239 | end 240 | 241 | -- Get tab data 242 | local bufsel 243 | local tabselidx = -1 244 | local ntabs = 0 245 | local tabbufs = {} 246 | 247 | if bool(is_buffers) then 248 | bufsel = bufnr() 249 | for _, buf in pairs(getbufinfo()) do 250 | local buf_bufnr = buf.bufnr 251 | local HideBuffer = vim_g['CrystallineHideBufferFn'] or vim_fn['g:CrystallineHideBufferFn'] 252 | if bool(bufloaded(buf_bufnr)) and not bool(HideBuffer(buf_bufnr)) then 253 | ntabs = ntabs + 1 254 | tabbufs[ntabs] = buf_bufnr 255 | if bufsel == buf_bufnr then 256 | tabselidx = ntabs 257 | end 258 | end 259 | end 260 | else 261 | tabselidx = tabpagenr() 262 | ntabs = tabpagenr("$") 263 | for tabidx = 1, ntabs do 264 | tabbufs[tabidx] = tabpagebuflist(tabidx)[tabpagewinnr(tabidx)] 265 | end 266 | end 267 | 268 | -- Calculate remaining width for tabs 269 | local remaining_width = max_width - lr_sep_width 270 | -- Calculate max tab width 271 | local max_tab_width = math.max(math.floor(remaining_width / math.min(ntabs, max_tabs)), min_tab_width + sep_width) - sep_width 272 | -- Calculate max selected tab width 273 | local max_tab_sel_width = math.max(max_tab_width, min_tab_sel_width) 274 | -- Handle different width for selected tabs 275 | if tabselidx > 0 and max_tab_sel_width ~= max_tab_width then 276 | -- Recalculate remaining width for non-selected tabs 277 | remaining_width = max_width - max_tab_sel_width - lr_sep_width 278 | -- Recalculate max tab width 279 | max_tab_width = math.max(math.floor(remaining_width / math.min(ntabs - 1, max_tabs)), min_tab_width + sep_width) - sep_width 280 | end 281 | 282 | -- Add selected tab first to ensure it's always added 283 | local Tab = vim_g['CrystallineTabFn'] or vim_fn['g:CrystallineTabFn'] 284 | if tabselidx > 0 then 285 | local tabinfo = Tab(tabselidx, tabbufs[tabselidx], max_tab_sel_width, true) 286 | local tab, tabwidth = tabinfo[1], tabinfo[2] 287 | if enable_mouse then 288 | tab = "%" .. tabselidx .. "T" .. tab 289 | end 290 | o = o .. tab 291 | tab_count = tab_count + 1 292 | width = width + tabwidth 293 | first_group = tab_sel_group 294 | last_group = tab_sel_group 295 | end 296 | 297 | -- Add at least one tab to left of selected if present and there's space 298 | local add_left_tabs = tabselidx > 1 and width < max_width and tab_count < max_tabs 299 | if add_left_tabs then 300 | local tabinfo = Tab(tabselidx - 1, tabbufs[tabselidx - 1], max_tab_width, false) 301 | local tab, tabwidth = tabinfo[1], tabinfo[2] 302 | if enable_sep then 303 | tab = tab .. module.PlainSep(sep_index, tab_group, first_group) 304 | tabwidth = tabwidth + sep_width 305 | elseif first_group == tab_sel_group then 306 | tab = tab .. "%#Crystalline" .. tab_sel_group .. "#" 307 | end 308 | if enable_mouse then 309 | tab = "%" .. (tabselidx - 1) .. "T" .. tab .. "" 310 | end 311 | add_left_tabs = width + tabwidth <= max_width 312 | if add_left_tabs then 313 | o = tab .. o 314 | tab_count = tab_count + 1 315 | width = width + tabwidth 316 | first_group = tab_group 317 | end 318 | end 319 | 320 | -- Add at least one tab to right of selected if present and there's space 321 | local add_right_tabs = tabselidx > 0 and tabselidx < ntabs and width < max_width and tab_count < max_tabs 322 | if add_right_tabs then 323 | local tabinfo = Tab(tabselidx + 1, tabbufs[tabselidx + 1], max_tab_width, false) 324 | local tab, tabwidth = tabinfo[1], tabinfo[2] 325 | if enable_mouse then 326 | tab = "%" .. (tabselidx + 1) .. "T" .. tab 327 | end 328 | if enable_sep then 329 | tab = module.PlainSep(sep_index, last_group, tab_group) .. tab 330 | tabwidth = tabwidth + sep_width 331 | elseif last_group == tab_sel_group then 332 | tab = "%#Crystalline" .. tab_group .. "#" .. tab 333 | end 334 | add_right_tabs = width + tabwidth <= max_width 335 | if add_right_tabs then 336 | o = o .. tab 337 | tab_count = tab_count + 1 338 | width = width + tabwidth 339 | last_group = tab_group 340 | end 341 | end 342 | 343 | -- Get tab separator 344 | local tab_sep 345 | if enable_sep then 346 | tab_sep = module.PlainSep(sep_index, tab_group, tab_group) 347 | end 348 | 349 | -- Add tabs to left of selected 350 | local tabidx = add_left_tabs and (tabselidx - 2) or -1 351 | while tabidx > 0 and width < max_width and tab_count < max_tabs do 352 | local tabinfo = Tab(tabidx, tabbufs[tabidx], max_tab_width, false) 353 | local tab, tabwidth = tabinfo[1], tabinfo[2] 354 | if enable_sep then 355 | tab = tab .. tab_sep 356 | tabwidth = tabwidth + sep_width 357 | end 358 | if enable_mouse then 359 | tab = "%" .. tabidx .. "T" .. tab 360 | end 361 | if width + tabwidth > max_width then 362 | break 363 | end 364 | o = tab .. o 365 | tab_count = tab_count + 1 366 | width = width + tabwidth 367 | tabidx = tabidx - 1 368 | end 369 | 370 | -- Add other tabs to right of selected 371 | tabidx = add_right_tabs and tabselidx + 2 or ntabs + 1 372 | while tabidx <= ntabs and width < max_width and tab_count < max_tabs do 373 | local tabinfo = Tab(tabidx, tabbufs[tabidx], max_tab_width, false) 374 | local tab, tabwidth = tabinfo[1], tabinfo[2] 375 | if enable_mouse then 376 | tab = "%" .. tabidx .. "T" .. tab 377 | end 378 | if enable_sep then 379 | tab = tab_sep .. tab 380 | tabwidth = tabwidth + sep_width 381 | end 382 | if width + tabwidth > max_width then 383 | break 384 | end 385 | o = o .. tab 386 | tab_count = tab_count + 1 387 | width = width + tabwidth 388 | tabidx = tabidx + 1 389 | end 390 | 391 | if enable_left_sep then 392 | -- Draw left separator 393 | o = module.PlainSep(sep_index, left_group, first_group) .. o 394 | else 395 | -- Draw first group 396 | o = "%#Crystalline" .. first_group .. "#" .. o 397 | end 398 | 399 | if enable_right_sep then 400 | -- Draw right separator 401 | o = o .. module.PlainSep(sep_index, last_group, right_group) 402 | elseif right_group ~= "" then 403 | -- Draw right group 404 | o = o .. "%#Crystalline" .. right_group .. "#" 405 | end 406 | 407 | -- End final tab 408 | if enable_mouse then 409 | o = o .. "%T" 410 | end 411 | 412 | return o 413 | end 414 | 415 | -- }}} 416 | 417 | return module 418 | 419 | -- vim:set et sw=2 ts=2 fdm=marker: 420 | -------------------------------------------------------------------------------- /nvim/autoload/crystalline.vim: -------------------------------------------------------------------------------- 1 | " See also lua/crystalline.lua 2 | 3 | if !has('nvim') 4 | finish 5 | endif 6 | 7 | let s:crystalline = v:lua.require('crystalline') 8 | 9 | " Statusline Utils {{{ 10 | 11 | function! crystalline#PlainSep(sep_index, left_group, right_group) abort 12 | return s:crystalline.PlainSep(a:sep_index, a:left_group, a:right_group) 13 | endfunction 14 | 15 | function! crystalline#Sep(sep_index, left_group, right_group) abort 16 | return s:crystalline.Sep(a:sep_index, a:left_group, a:right_group) 17 | endfunction 18 | 19 | " }}} 20 | 21 | " Tabline Utils {{{ 22 | 23 | function! crystalline#DefaultTab(tab, buf, max_width, is_sel) abort 24 | return s:crystalline.DefaultTab(a:tab, a:buf, a:max_width, a:is_sel) 25 | endfunction 26 | 27 | function! crystalline#DefaultHideBuffer(buf) abort 28 | return s:crystalline.DefaultHideBuffer(a:buf) 29 | endfunction 30 | 31 | function! crystalline#TabsOrBuffers(...) abort 32 | return s:crystalline.TabsOrBuffers(get(a:, 1, {})) 33 | endfunction 34 | 35 | " }}} 36 | -------------------------------------------------------------------------------- /plugin/crystalline.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | 3 | " Deprecations {{{ 4 | 5 | if exists('g:crystalline_statusline_fn') 6 | echoerr 'g:crystalline_statusline_fn is deprecated, use function! g:CrystallineStatuslineFn' 7 | endif 8 | 9 | if exists('g:crystalline_tabline_fn') 10 | echoerr 'g:crystalline_tabline_fn is deprecated, use function! g:CrystallineTablineFn' 11 | endif 12 | 13 | if exists('g:crystalline_hide_buf_tab') 14 | echoerr 'g:crystalline_hide_buf_tab is deprecated, use function! g:CrystallineHideBufferFn' 15 | endif 16 | 17 | if exists('g:crystalline_tab_separator') 18 | echoerr 'g:crystalline_tab_separator is deprecated, see :help crystalline#BuffersOrTabs()' 19 | endif 20 | 21 | " }}} 22 | 23 | " Helper Variables {{{ 24 | 25 | if !exists('g:crystalline_mode_labels') 26 | let g:crystalline_mode_labels = { 27 | \ 'n': ' NORMAL ', 28 | \ 'c': ' COMMAND ', 29 | \ 'r': ' NORMAL ', 30 | \ '!': ' NORMAL ', 31 | \ 'i': ' INSERT ', 32 | \ 't': ' TERMINAL ', 33 | \ 'v': ' VISUAL ', 34 | \ 'V': ' VISUAL ', 35 | \ '': ' VISUAL ', 36 | \ 's': ' VISUAL ', 37 | \ 'S': ' VISUAL ', 38 | \ '': ' VISUAL ', 39 | \ 'R': ' REPLACE ', 40 | \ '': '', 41 | \ } 42 | elseif !has_key(g:crystalline_mode_labels, 'c') 43 | echoerr 'crystalline: outdated g:crystalline_mode_labels detected, define all of the groups in :help g:crystalline_mode_labels' 44 | endif 45 | 46 | if !exists('g:crystalline_mode_hi_groups') 47 | let g:crystalline_mode_hi_groups = { 48 | \ 'n': 'NormalMode', 49 | \ 'c': 'CommandMode', 50 | \ 'r': 'NormalMode', 51 | \ '!': 'NormalMode', 52 | \ 'i': 'InsertMode', 53 | \ 't': 'TerminalMode', 54 | \ 'v': 'VisualMode', 55 | \ 'V': 'VisualMode', 56 | \ '': 'VisualMode', 57 | \ 's': 'VisualMode', 58 | \ 'S': 'VisualMode', 59 | \ '': 'VisualMode', 60 | \ 'R': 'ReplaceMode', 61 | \ '': '', 62 | \ } 63 | elseif !has_key(g:crystalline_mode_hi_groups, 'c') 64 | echoerr 'crystalline: outdated g:crystalline_mode_labels detected, define all of the groups in :help g:crystalline_mode_labels' 65 | endif 66 | 67 | if !exists('g:crystalline_auto_prefix_groups') 68 | let g:crystalline_auto_prefix_groups = v:false 69 | endif 70 | 71 | if !exists('g:crystalline_group_suffix') 72 | let g:crystalline_group_suffix = '' 73 | endif 74 | 75 | if !exists('g:crystalline_separators') 76 | let g:crystalline_separators = [ 77 | \ { 'ch': '', 'alt_ch': '', 'dir': '>' }, 78 | \ { 'ch': '', 'alt_ch': '', 'dir': '<' }, 79 | \ ] 80 | endif 81 | 82 | if type(get(g:crystalline_separators, 0, {})) != v:t_dict 83 | echoerr "crystalline: detected deprecated use of strings in g:crystalline_separators, use { 'ch': '', 'dir': '>' }" 84 | endif 85 | 86 | if !exists('g:crystalline_tab_sep_index') 87 | let g:crystalline_tab_sep_index = 0 88 | endif 89 | 90 | if !exists('g:crystalline_tab_empty') 91 | let g:crystalline_tab_empty = '[No Name]' 92 | endif 93 | 94 | if !exists('g:crystalline_tab_mod') 95 | let g:crystalline_tab_mod = '[+]' 96 | endif 97 | 98 | if !exists('g:crystalline_tab_left') 99 | let g:crystalline_tab_left = ' ' 100 | endif 101 | 102 | if !exists('g:crystalline_tab_nomod') 103 | let g:crystalline_tab_nomod = ' ' 104 | endif 105 | 106 | if !exists('g:crystalline_tabs_tab_type_label') 107 | let g:crystalline_tabs_tab_type_label = ' TABS ' 108 | endif 109 | 110 | if !exists('g:crystalline_buffers_tab_type_label') 111 | let g:crystalline_buffers_tab_type_label = ' BUFFERS ' 112 | endif 113 | 114 | if !exists('g:crystalline_tab_min_path_parts') 115 | let g:crystalline_tab_min_path_parts = 3 116 | endif 117 | 118 | if !exists('g:CrystallineTabFn') && !exists('*g:CrystallineTabFn') 119 | if has('nvim') 120 | lua vim.g.CrystallineTabFn = require('crystalline').DefaultTab 121 | else 122 | function! g:CrystallineTabFn(tab, buf, max_width, is_sel) abort 123 | return crystalline#DefaultTab(a:tab, a:buf, a:max_width, a:is_sel) 124 | endfunction 125 | endif 126 | endif 127 | 128 | if !exists('g:CrystallineHideBufferFn') && !exists('*g:CrystallineHideBufferFn') 129 | if has('nvim') 130 | lua vim.g.CrystallineHideBufferFn = require('crystalline').DefaultHideBuffer 131 | else 132 | function! g:CrystallineHideBufferFn(buf) abort 133 | return crystalline#DefaultHideBuffer(a:buf) 134 | endfunction 135 | endif 136 | endif 137 | 138 | let g:crystalline_sep_hi_groups = {} 139 | let g:crystalline_skip_sep_groups = {} 140 | let g:crystalline_alt_sep_groups = {} 141 | let g:crystalline_sep_cache = {} 142 | 143 | let g:crystalline_syn_modes = ['term', 'cterm', 'gui'] 144 | 145 | let g:crystalline_syn_attrs = [ 146 | \ 'font', 147 | \ 'bold', 148 | \ 'italic', 149 | \ 'reverse', 150 | \ 'standout', 151 | \ 'underline', 152 | \ 'undercurl', 153 | \ 'strikethrough' 154 | \ ] 155 | 156 | let g:crystalline_syn_colors = ['fg', 'bg', 'sp'] 157 | 158 | if !exists('g:crystalline_theme') 159 | let g:crystalline_theme = 'default' 160 | endif 161 | 162 | if !exists('g:crystalline_theme_airline_styles') 163 | let g:crystalline_theme_airline_styles = [ 164 | \ ['', 'normal'], 165 | \ ['Inactive', 'inactive'], 166 | \ ['NormalMode', 'normal'], 167 | \ ['CommandMode', 'commandline'], 168 | \ ['InsertMode', 'insert'], 169 | \ ['VisualMode', 'visual'], 170 | \ ['ReplaceMode', 'replace'], 171 | \ ['TerminalMode', 'terminal'], 172 | \ ] 173 | endif 174 | 175 | if !exists('g:crystalline_theme_styles') 176 | let g:crystalline_theme_styles = [ 177 | \ '', 178 | \ 'Inactive', 179 | \ 'NormalMode', 180 | \ 'CommandMode', 181 | \ 'InsertMode', 182 | \ 'VisualMode', 183 | \ 'ReplaceMode', 184 | \ 'TerminalMode', 185 | \ ] 186 | endif 187 | 188 | if !exists('g:crystalline_theme_airline_sections') 189 | let g:crystalline_theme_airline_sections = [ 190 | \ ['A', ['', 'airline_a']], 191 | \ ['B', ['', 'airline_b']], 192 | \ ['Fill', ['', 'airline_c']], 193 | \ ['Tab', ['inactive', 'airline_c']], 194 | \ ['TabSel', ['', 'airline_a']], 195 | \ ['TabFill', ['', 'airline_x']], 196 | \ ['TabType', ['', 'airline_b']], 197 | \ ] 198 | endif 199 | 200 | if !exists('g:crystalline_theme_sections') 201 | let g:crystalline_theme_sections = [ 202 | \ 'A', 203 | \ 'B', 204 | \ 'Fill', 205 | \ 'Tab', 206 | \ 'TabSel', 207 | \ 'TabFill', 208 | \ 'TabType', 209 | \ ] 210 | endif 211 | 212 | if !exists('g:crystalline_theme_airline_variants') 213 | let g:crystalline_theme_airline_variants = [ 214 | \ ['', ''], 215 | \ ['1', '_modified'], 216 | \ ['2', '_paste'] 217 | \ ] 218 | endif 219 | 220 | if !exists('g:crystalline_theme_variants') 221 | let g:crystalline_theme_variants = ['', '1', '2'] 222 | endif 223 | 224 | let g:crystalline_theme_attrs = [ 225 | \ [0, 0, 'ctermfg'], 226 | \ [0, 1, 'ctermbg'], 227 | \ [1, 0, 'guifg'], 228 | \ [1, 1, 'guibg'], 229 | \ ] 230 | 231 | let g:crystalline_inactive = 0 232 | 233 | " }}} 234 | 235 | " Load User Settings {{{ 236 | 237 | if exists('g:CrystallineTablineFn') || exists('*g:CrystallineTablineFn') 238 | call crystalline#InitTabline() 239 | endif 240 | 241 | if exists('g:CrystallineStatuslineFn') || exists('*g:CrystallineStatuslineFn') 242 | call crystalline#InitStatusline() 243 | endif 244 | 245 | call crystalline#ApplyCurrentTheme() 246 | 247 | " }}} 248 | 249 | " Setup Autogroups {{{ 250 | 251 | augroup CrystallineTheme 252 | au! 253 | au ColorScheme * call crystalline#ApplyCurrentTheme() 254 | au OptionSet background call crystalline#ApplyCurrentTheme() 255 | augroup END 256 | 257 | " }}} 258 | 259 | " vim:set et sw=2 ts=2 fdm=marker: 260 | -------------------------------------------------------------------------------- /t/crystalline.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | 3 | runtime plugin/crystalline.vim 4 | 5 | describe 'crystalline' 6 | after 7 | " Unload files 8 | %bd 9 | " Clear statusline/tabline 10 | call crystalline#ClearStatusline() 11 | call crystalline#ClearTabline() 12 | " Clear options 13 | delfunction! g:CrystallineStatuslineFn 14 | unlet! g:CrystallineStatuslineFn 15 | delfunction! g:CrystallineTablineFn 16 | unlet! g:CrystallineTablineFn 17 | delfunction! g:CrystallineTabFn 18 | unlet! g:CrystallineTabFn 19 | delfunction! g:CrystallineHideBufferFn 20 | unlet! g:CrystallineHideBufferFn 21 | unlet! g:crystalline_separators 22 | unlet! g:crystalline_auto_prefix_groups 23 | unlet! g:crystalline_group_suffix 24 | " Reset settings 25 | runtime plugin/crystalline.vim 26 | end 27 | 28 | it 'does not overwrite settings by default' 29 | Expect &statusline ==# '' 30 | Expect &tabline ==# '' 31 | end 32 | 33 | it 'sets the statusline' 34 | function! g:CrystallineStatuslineFn(winnr) 35 | return '__STATUSLINE__:' . a:winnr 36 | endfunction 37 | source plugin/crystalline.vim 38 | Expect &statusline ==# '%!crystalline#GetStatusline(1000)' 39 | Expect crystalline#GetStatusline(1000) ==# '__STATUSLINE__:1' 40 | end 41 | 42 | it 'sets the tabline' 43 | function! g:CrystallineTablineFn() 44 | return '__TABLINE__' 45 | endfunction 46 | source plugin/crystalline.vim 47 | Expect &tabline ==# '%!crystalline#GetTabline()' 48 | Expect crystalline#GetTabline() ==# '__TABLINE__' 49 | end 50 | 51 | it 'draws default separators' 52 | Expect crystalline#Sep(0, 'A', 'B') ==# '%#CrystallineAToB#%#CrystallineB#' 53 | Expect crystalline#Sep(0, 'A', 'A') ==# '' 54 | Expect crystalline#Sep(1, 'A', 'B') ==# '%#CrystallineBToA#%#CrystallineB#' 55 | Expect crystalline#Sep(1, 'A', 'A') ==# '' 56 | end 57 | 58 | it 'draws custom separators' 59 | let g:crystalline_separators = [ 60 | \ { 'ch': '>', 'alt_ch': ')', 'dir': '>' }, 61 | \ { 'ch': '<', 'alt_ch': '(', 'dir': '<' } 62 | \ ] 63 | Expect crystalline#Sep(0, 'A', 'B') ==# '%#CrystallineAToB#>%#CrystallineB#' 64 | Expect crystalline#Sep(0, 'A', 'A') ==# ')' 65 | Expect crystalline#Sep(1, 'A', 'B') ==# '%#CrystallineBToA#<%#CrystallineB#' 66 | Expect crystalline#Sep(1, 'A', 'A') ==# '(' 67 | end 68 | 69 | it 'adds the current mode to groups' 70 | Expect crystalline#ModeGroup('A') ==# 'CommandModeA' 71 | end 72 | 73 | it 'draws tabs' 74 | e /tmp/1 75 | tabe /tmp/2 76 | tabe /tmp/3 77 | 78 | normal 2gt 79 | Expect crystalline#DefaultTabline() ==# '%#CrystallineTabType# TABS ' 80 | \ . '%#CrystallineTab#%1T /t/1 ' 81 | \ . '%#CrystallineTabSel#%2T /t/2 ' 82 | \ . '%#CrystallineTab#%3T /t/3 ' 83 | \ . '%#CrystallineTabFill#%T' 84 | end 85 | 86 | it 'draws buffers' 87 | e /tmp/1 88 | try 89 | bd! # 90 | catch /.*/ 91 | endtry 92 | e /tmp/2 93 | e /tmp/3 94 | 95 | buffer /tmp/2 96 | Expect crystalline#DefaultTabline() ==# '%#CrystallineTabType# BUFFERS ' 97 | \ . '%#CrystallineTab# /t/1 ' 98 | \ . '%#CrystallineTabSel# /t/2 ' 99 | \ . '%#CrystallineTab# /t/3 ' 100 | \ . '%#CrystallineTabFill#' 101 | end 102 | 103 | it 'draws tabs with separators' 104 | e /tmp/1 105 | for l:i in range(2, 5) 106 | exec 'tabe /tmp/' . l:i 107 | endfor 108 | 109 | normal 1gt 110 | Expect crystalline#DefaultTabline({ 'enable_sep': 1 }) ==# '%#CrystallineTabType# TABS %#CrystallineTabTypeToTabSel#' 111 | \ . '%#CrystallineTabSel#%1T /t/1 %#CrystallineTabSelToTab#' 112 | \ . '%#CrystallineTab#%2T /t/2 ' 113 | \ . '%3T /t/3 ' 114 | \ . '%4T /t/4 ' 115 | \ . '%5T /t/5 %#CrystallineTabToTabFill#' 116 | \ . '%#CrystallineTabFill#%T' 117 | normal 2gt 118 | Expect crystalline#DefaultTabline({ 'enable_sep': 1 }) ==# '%#CrystallineTabType# TABS %#CrystallineTabTypeToTab#' 119 | \ . '%#CrystallineTab#%1T /t/1 %#CrystallineTabToTabSel#' 120 | \ . '%#CrystallineTabSel#%2T /t/2 %#CrystallineTabSelToTab#' 121 | \ . '%#CrystallineTab#%3T /t/3 ' 122 | \ . '%4T /t/4 ' 123 | \ . '%5T /t/5 %#CrystallineTabToTabFill#' 124 | \ . '%#CrystallineTabFill#%T' 125 | normal 4gt 126 | Expect crystalline#DefaultTabline({ 'enable_sep': 1 }) ==# '%#CrystallineTabType# TABS %#CrystallineTabTypeToTab#' 127 | \ . '%#CrystallineTab#%1T /t/1 ' 128 | \ . '%2T /t/2 ' 129 | \ . '%3T /t/3 %#CrystallineTabToTabSel#' 130 | \ . '%#CrystallineTabSel#%4T /t/4 %#CrystallineTabSelToTab#' 131 | \ . '%#CrystallineTab#%5T /t/5 %#CrystallineTabToTabFill#' 132 | \ . '%#CrystallineTabFill#%T' 133 | normal 5gt 134 | Expect crystalline#DefaultTabline({ 'enable_sep': 1 }) ==# '%#CrystallineTabType# TABS %#CrystallineTabTypeToTab#' 135 | \ . '%#CrystallineTab#%1T /t/1 ' 136 | \ . '%2T /t/2 ' 137 | \ . '%3T /t/3 ' 138 | \ . '%4T /t/4 %#CrystallineTabToTabSel#' 139 | \ . '%#CrystallineTabSel#%5T /t/5 %#CrystallineTabSelToTabFill#' 140 | \ . '%#CrystallineTabFill#%T' 141 | end 142 | 143 | it 'allows custom tabs' 144 | unlet! g:CrystallineTabFn 145 | function! g:CrystallineTabFn(tabnr, bufnr, max_width, is_sel) abort 146 | return [' tab ', 5] 147 | endfunction 148 | 149 | e /tmp/1 150 | tabe /tmp/2 151 | tabe /tmp/3 152 | Expect crystalline#Tabs({ 'enable_mouse': 0 }) ==# '%#CrystallineTab# tab tab %#CrystallineTabSel# tab %#CrystallineTabFill#' 153 | end 154 | 155 | it 'does not exceed max width' 156 | e /tmp/1 157 | for l:i in range(2, 5) 158 | exec 'tabe /tmp/' . l:i 159 | endfor 160 | normal 3gt 161 | 162 | let l:five_tabs = '%#CrystallineTabType# TABS %#CrystallineTabTypeToTab#' 163 | \ . '%#CrystallineTab#%1T /t/1 ' 164 | \ . '%2T /t/2 %#CrystallineTabToTabSel#' 165 | \ . '%#CrystallineTabSel#%3T /t/3 %#CrystallineTabSelToTab#' 166 | \ . '%#CrystallineTab#%4T /t/4 ' 167 | \ . '%5T /t/5 %#CrystallineTabToTabFill#' 168 | \ . '%#CrystallineTabFill#%T' 169 | let l:four_tabs = '%#CrystallineTabType# TABS %#CrystallineTabTypeToTab#' 170 | \ . '%#CrystallineTab#%1T /t/1 ' 171 | \ . '%2T /t/2 %#CrystallineTabToTabSel#' 172 | \ . '%#CrystallineTabSel#%3T /t/3 %#CrystallineTabSelToTab#' 173 | \ . '%#CrystallineTab#%4T /t/4 %#CrystallineTabToTabFill#' 174 | \ . '%#CrystallineTabFill#%T' 175 | let l:three_tabs = '%#CrystallineTabType# TABS %#CrystallineTabTypeToTab#' 176 | \ . '%#CrystallineTab#%2T /t/2 %#CrystallineTabToTabSel#' 177 | \ . '%#CrystallineTabSel#%3T /t/3 %#CrystallineTabSelToTab#' 178 | \ . '%#CrystallineTab#%4T /t/4 %#CrystallineTabToTabFill#' 179 | \ . '%#CrystallineTabFill#%T' 180 | let l:two_tabs = '%#CrystallineTabType# TABS %#CrystallineTabTypeToTab#' 181 | \ . '%#CrystallineTab#%2T /t/2 %#CrystallineTabToTabSel#' 182 | \ . '%#CrystallineTabSel#%3T /t/3 %#CrystallineTabSelToTabFill#' 183 | \ . '%#CrystallineTabFill#%T' 184 | let l:one_tab = '%#CrystallineTabType# TABS %#CrystallineTabTypeToTabSel#' 185 | \ . '%#CrystallineTabSel#%3T /t/3 %#CrystallineTabSelToTabFill#' 186 | \ . '%#CrystallineTabFill#%T' 187 | 188 | " Tabline: ' TABS > /t/1 > /t/2 > /t/3 > /t/4 > /t/5 >' 189 | " Width: 1 10 20 30 40 190 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_width': 42 }) ==# l:five_tabs 191 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_width': 41 }) ==# l:four_tabs 192 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_width': 35 }) ==# l:four_tabs 193 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_width': 34 }) ==# l:three_tabs 194 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_width': 28 }) ==# l:three_tabs 195 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_width': 27 }) ==# l:two_tabs 196 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_width': 21 }) ==# l:two_tabs 197 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_width': 20 }) ==# l:one_tab 198 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_width': 0 }) ==# l:one_tab 199 | end 200 | 201 | it 'does not exceed max tabs' 202 | e /tmp/1 203 | for l:i in range(2, 5) 204 | exec 'tabe /tmp/' . l:i 205 | endfor 206 | normal 3gt 207 | 208 | let l:five_tabs = '%#CrystallineTabType# TABS %#CrystallineTabTypeToTab#' 209 | \ . '%#CrystallineTab#%1T /t/1 ' 210 | \ . '%2T /t/2 %#CrystallineTabToTabSel#' 211 | \ . '%#CrystallineTabSel#%3T /t/3 %#CrystallineTabSelToTab#' 212 | \ . '%#CrystallineTab#%4T /t/4 ' 213 | \ . '%5T /t/5 %#CrystallineTabToTabFill#' 214 | \ . '%#CrystallineTabFill#%T' 215 | let l:four_tabs = '%#CrystallineTabType# TABS %#CrystallineTabTypeToTab#' 216 | \ . '%#CrystallineTab#%1T /t/1 ' 217 | \ . '%2T /t/2 %#CrystallineTabToTabSel#' 218 | \ . '%#CrystallineTabSel#%3T /t/3 %#CrystallineTabSelToTab#' 219 | \ . '%#CrystallineTab#%4T /t/4 %#CrystallineTabToTabFill#' 220 | \ . '%#CrystallineTabFill#%T' 221 | let l:three_tabs = '%#CrystallineTabType# TABS %#CrystallineTabTypeToTab#' 222 | \ . '%#CrystallineTab#%2T /t/2 %#CrystallineTabToTabSel#' 223 | \ . '%#CrystallineTabSel#%3T /t/3 %#CrystallineTabSelToTab#' 224 | \ . '%#CrystallineTab#%4T /t/4 %#CrystallineTabToTabFill#' 225 | \ . '%#CrystallineTabFill#%T' 226 | let l:two_tabs = '%#CrystallineTabType# TABS %#CrystallineTabTypeToTab#' 227 | \ . '%#CrystallineTab#%2T /t/2 %#CrystallineTabToTabSel#' 228 | \ . '%#CrystallineTabSel#%3T /t/3 %#CrystallineTabSelToTabFill#' 229 | \ . '%#CrystallineTabFill#%T' 230 | let l:one_tab = '%#CrystallineTabType# TABS %#CrystallineTabTypeToTabSel#' 231 | \ . '%#CrystallineTabSel#%3T /t/3 %#CrystallineTabSelToTabFill#' 232 | \ . '%#CrystallineTabFill#%T' 233 | 234 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_tabs': 6 }) ==# l:five_tabs 235 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_tabs': 5 }) ==# l:five_tabs 236 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_tabs': 4 }) ==# l:four_tabs 237 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_tabs': 3 }) ==# l:three_tabs 238 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_tabs': 2 }) ==# l:two_tabs 239 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_tabs': 1 }) ==# l:one_tab 240 | Expect crystalline#DefaultTabline({ 'enable_sep': 1, 'max_tabs': 0 }) ==# l:one_tab 241 | end 242 | 243 | it 'does not modify groups by default' 244 | Expect crystalline#Sep(0, 'A', 'B') ==# '%#CrystallineAToB#%#CrystallineB#' 245 | Expect crystalline#HiItem('A') ==# '%#CrystallineA#' 246 | 247 | e /tmp/1 248 | tabe /tmp/2 249 | tabe /tmp/3 250 | normal 2gt 251 | Expect crystalline#Tabs({ 'enable_mouse': 0, 'enable_sep': 1 }) ==# '%#CrystallineTab# /t/1 %#CrystallineTabToTabSel#' 252 | \ . '%#CrystallineTabSel# /t/2 %#CrystallineTabSelToTab#' 253 | \ . '%#CrystallineTab# /t/3 %#CrystallineTabToTabFill#' 254 | \ . '%#CrystallineTabFill#' 255 | end 256 | 257 | it 'auto-prefixes mode' 258 | let g:crystalline_auto_prefix_groups = 1 259 | Expect crystalline#Sep(0, 'A', 'B') ==# '%#CrystallineCommandModeAToCommandModeB#%#CrystallineCommandModeB#' 260 | Expect crystalline#HiItem('A') ==# '%#CrystallineCommandModeA#' 261 | 262 | e /tmp/1 263 | tabe /tmp/2 264 | tabe /tmp/3 265 | normal 2gt 266 | Expect crystalline#Tabs({ 'enable_mouse': 0, 'enable_sep': 1 }) ==# '%#CrystallineCommandModeTab# /t/1 %#CrystallineCommandModeTabToCommandModeTabSel#' 267 | \ . '%#CrystallineCommandModeTabSel# /t/2 %#CrystallineCommandModeTabSelToCommandModeTab#' 268 | \ . '%#CrystallineCommandModeTab# /t/3 %#CrystallineCommandModeTabToCommandModeTabFill#' 269 | \ . '%#CrystallineCommandModeTabFill#' 270 | end 271 | 272 | it 'auto-prefixes inactive' 273 | let g:crystalline_auto_prefix_groups = 1 274 | let g:crystalline_inactive = 1 275 | Expect crystalline#Sep(0, 'A', 'B') ==# '%#CrystallineInactiveAToInactiveB#%#CrystallineInactiveB#' 276 | Expect crystalline#HiItem('A') ==# '%#CrystallineInactiveA#' 277 | 278 | e /tmp/1 279 | tabe /tmp/2 280 | tabe /tmp/3 281 | normal 2gt 282 | Expect crystalline#Tabs({ 'enable_mouse': 0, 'enable_sep': 1 }) ==# '%#CrystallineCommandModeTab# /t/1 %#CrystallineCommandModeTabToCommandModeTabSel#' 283 | \ . '%#CrystallineCommandModeTabSel# /t/2 %#CrystallineCommandModeTabSelToCommandModeTab#' 284 | \ . '%#CrystallineCommandModeTab# /t/3 %#CrystallineCommandModeTabToCommandModeTabFill#' 285 | \ . '%#CrystallineCommandModeTabFill#' 286 | end 287 | 288 | it 'adds group suffix' 289 | let g:crystalline_group_suffix = '1' 290 | Expect crystalline#Sep(0, 'A', 'B') ==# '%#CrystallineA1ToB1#%#CrystallineB1#' 291 | Expect crystalline#HiItem('A') ==# '%#CrystallineA1#' 292 | 293 | e /tmp/1 294 | tabe /tmp/2 295 | tabe /tmp/3 296 | normal 2gt 297 | Expect crystalline#Tabs({ 'enable_mouse': 0, 'enable_sep': 1, 'group_suffix': '1' }) ==# '%#CrystallineTab1# /t/1 %#CrystallineTab1ToTabSel1#' 298 | \ . '%#CrystallineTabSel1# /t/2 %#CrystallineTabSel1ToTab1#' 299 | \ . '%#CrystallineTab1# /t/3 %#CrystallineTab1ToTabFill1#' 300 | \ . '%#CrystallineTabFill1#' 301 | end 302 | end 303 | 304 | " vim:set et sw=2 ts=2 fdm=marker: 305 | -------------------------------------------------------------------------------- /vim9/autoload/crystalline.vim: -------------------------------------------------------------------------------- 1 | if !has('vim9script') 2 | finish 3 | endif 4 | 5 | vim9script 6 | 7 | # Statusline Utils {{{ 8 | 9 | export def PlainSep(sep_index: any, left_group: string, right_group: string): string 10 | var key = sep_index .. left_group .. right_group 11 | if !has_key(g:crystalline_sep_cache, key) 12 | g:crystalline_sep_cache[key] = crystalline#GetSep(sep_index, left_group, right_group) 13 | endif 14 | return g:crystalline_sep_cache[key] 15 | enddef 16 | 17 | export def Sep(sep_index: any, _left_group: string, _right_group: string): string 18 | var left_group: string 19 | var right_group: string 20 | if g:crystalline_auto_prefix_groups 21 | if g:crystalline_inactive 22 | left_group = 'Inactive' .. _left_group .. g:crystalline_group_suffix 23 | right_group = 'Inactive' .. _right_group .. g:crystalline_group_suffix 24 | else 25 | var m = g:crystalline_mode_hi_groups[mode()] 26 | left_group = m .. _left_group .. g:crystalline_group_suffix 27 | right_group = m .. _right_group .. g:crystalline_group_suffix 28 | endif 29 | else 30 | left_group = _left_group .. g:crystalline_group_suffix 31 | right_group = _right_group .. g:crystalline_group_suffix 32 | endif 33 | var key = sep_index .. left_group .. right_group 34 | if !has_key(g:crystalline_sep_cache, key) 35 | g:crystalline_sep_cache[key] = crystalline#GetSep(sep_index, left_group, right_group) 36 | endif 37 | return g:crystalline_sep_cache[key] 38 | enddef 39 | 40 | # }}} 41 | 42 | # Tabline Utils {{{ 43 | 44 | export def DefaultTab(_, buf: number, max_width: number, _): list 45 | # Return early 46 | if max_width <= 0 47 | return ['', 0] 48 | endif 49 | 50 | # Get left/right components 51 | var left = g:crystalline_tab_left 52 | var right = getbufvar(buf, '&mod') ? g:crystalline_tab_mod : g:crystalline_tab_nomod 53 | var lr_width = strchars(left) + strchars(right) 54 | var max_name_width = max_width - lr_width 55 | 56 | # Get name 57 | var name = bufname(buf) 58 | var name_width: number 59 | if name == '' 60 | name = g:crystalline_tab_empty 61 | name_width = strchars(name) 62 | else 63 | name = pathshorten(name) 64 | name_width = strchars(name) 65 | if name_width > max_name_width 66 | var split_name = split(name, '/') 67 | if len(split_name) > g:crystalline_tab_min_path_parts 68 | name = join(split_name[-g:crystalline_tab_min_path_parts : ], '/') 69 | name_width = strchars(name) 70 | endif 71 | endif 72 | endif 73 | 74 | # Shorten tab 75 | var tab: string 76 | var tabwidth: number 77 | if max_name_width <= 0 78 | tab = strcharpart(name, name_width - max_width) 79 | tabwidth = min([name_width, max_width]) 80 | else 81 | tab = left .. strcharpart(name, name_width - max_name_width) .. right 82 | tabwidth = lr_width + min([name_width, max_name_width]) 83 | endif 84 | 85 | return [crystalline#EscapeStatuslineString(tab), tabwidth] 86 | enddef 87 | 88 | export def DefaultHideBuffer(buf: number): bool 89 | return (!buflisted(buf) && bufnr('%') != buf) || getbufvar(buf, '&ft') == 'qf' 90 | enddef 91 | 92 | export def TabsOrBuffers(_opts: dict): string 93 | # Get args 94 | var opts = empty(_opts) ? {} : _opts 95 | 96 | # Get options 97 | var is_buffers = get(opts, 'is_buffers', 0) 98 | var enable_mouse = !is_buffers && get(opts, 'enable_mouse', 1) 99 | var enable_sep = get(opts, 'enable_sep', 0) 100 | var sep_index = get(opts, 'sep_index', 0) 101 | var sep = get(g:crystalline_separators, sep_index, { 'ch': '' }) 102 | var dir = get(opts, 'dir', sep.dir) 103 | var min_width = get(opts, 'min_width', 24) 104 | var max_width = get(opts, 'max_width', max([&columns, min_width])) 105 | var min_tab_width = get(opts, 'min_tab_width', 106 | strchars(g:crystalline_tab_left .. g:crystalline_tab_empty) 107 | + max([strchars(g:crystalline_tab_mod), strchars(g:crystalline_tab_nomod)])) 108 | var min_tab_sel_width = get(opts, 'min_tab_width', min_tab_width) 109 | var max_tabs = max([1, get(opts, 'max_tabs', 26)]) 110 | 111 | # Get group options 112 | var auto_prefix_groups = get(opts, 'auto_prefix_groups', g:crystalline_auto_prefix_groups) 113 | var group_suffix = get(opts, 'group_suffix', g:crystalline_group_suffix) 114 | var tab_group = '' 115 | var tab_sel_group = '' 116 | var tab_fill_group = '' 117 | if auto_prefix_groups 118 | var m = g:crystalline_mode_hi_groups[mode()] 119 | tab_group = get(opts, 'tab_group', m .. 'Tab' .. group_suffix) 120 | tab_sel_group = get(opts, 'tab_sel_group', m .. 'TabSel' .. group_suffix) 121 | tab_fill_group = get(opts, 'tab_fill_group', m .. 'TabFill' .. group_suffix) 122 | else 123 | tab_group = get(opts, 'tab_group', 'Tab' .. group_suffix) 124 | tab_sel_group = get(opts, 'tab_sel_group', 'TabSel' .. group_suffix) 125 | tab_fill_group = get(opts, 'tab_fill_group', 'TabFill' .. group_suffix) 126 | endif 127 | var left_group = get(opts, 'left_group', dir == '<' ? tab_fill_group : '') 128 | var right_group = get(opts, 'right_group', dir == '<' ? '' : tab_fill_group) 129 | 130 | # Init variables 131 | var o = '' 132 | var tab_count = 0 133 | var width = 0 134 | var sep_width = enable_sep ? strchars(sep.ch) : 0 135 | var first_group = tab_group 136 | var last_group = tab_group 137 | 138 | # Make sure there's room for leftmost/rightmost separator 139 | var enable_left_sep = enable_sep && left_group !=# '' 140 | var enable_right_sep = enable_sep && right_group !=# '' 141 | var lr_sep_width = 0 142 | if enable_left_sep 143 | # Count left sep 144 | width += sep_width 145 | lr_sep_width = sep_width 146 | endif 147 | if enable_right_sep 148 | # Count right sep 149 | width += sep_width 150 | lr_sep_width = sep_width 151 | endif 152 | 153 | # Get tab data 154 | var tabselidx = -1 155 | var ntabs = 0 156 | var tabbufs = [] 157 | if is_buffers 158 | var bufsel = bufnr() 159 | if exists('*getbufinfo') 160 | for buf in getbufinfo() 161 | var buf_bufnr = buf.bufnr 162 | if !g:CrystallineHideBufferFn(buf_bufnr) 163 | if bufsel == buf_bufnr 164 | tabselidx = ntabs 165 | endif 166 | add(tabbufs, buf_bufnr) 167 | ntabs += 1 168 | endif 169 | endfor 170 | else 171 | for bufnr in range(1, bufnr('$')) 172 | if bufexists(bufnr) && !g:CrystallineHideBufferFn(bufnr) 173 | if bufsel == bufnr 174 | tabselidx = ntabs 175 | endif 176 | add(tabbufs, bufnr) 177 | ntabs += 1 178 | endif 179 | endfor 180 | endif 181 | else 182 | tabselidx = tabpagenr() - 1 183 | ntabs = tabpagenr('$') 184 | for tabidx in range(1, ntabs) 185 | add(tabbufs, tabpagebuflist(tabidx)[tabpagewinnr(tabidx) - 1]) 186 | endfor 187 | endif 188 | 189 | # Calculate remaining width for tabs 190 | var remaining_width = max_width - lr_sep_width 191 | # Calculate max tab width 192 | var max_tab_width = max([remaining_width / min([ntabs, max_tabs]), min_tab_width + sep_width]) - sep_width 193 | # Calculate max selected tab width 194 | var max_tab_sel_width = max([max_tab_width, min_tab_sel_width]) 195 | # Handle different width for selected tabs 196 | if tabselidx >= 0 && max_tab_sel_width != max_tab_width 197 | # Recalculate remaining width for non-selected tabs 198 | remaining_width = max_width - max_tab_sel_width - lr_sep_width 199 | # Recalculate max tab width 200 | max_tab_width = max([remaining_width / min([ntabs - 1, max_tabs]), min_tab_width + sep_width]) - sep_width 201 | endif 202 | 203 | # Add selected tab first to ensure it's always added 204 | if tabselidx >= 0 205 | var [tab, tabwidth] = g:CrystallineTabFn(tabselidx + 1, tabbufs[tabselidx], max_tab_sel_width, v:true) 206 | if enable_mouse 207 | tab = '%' .. (tabselidx + 1) .. 'T' .. tab 208 | endif 209 | o ..= tab 210 | tab_count += 1 211 | width += tabwidth 212 | first_group = tab_sel_group 213 | last_group = tab_sel_group 214 | endif 215 | 216 | # Add at least one tab to left of selected if present and there's space 217 | var add_left_tabs = tabselidx > 0 && tabselidx < ntabs && width < max_width && tab_count < max_tabs 218 | if add_left_tabs 219 | var [tab, tabwidth] = g:CrystallineTabFn(tabselidx, tabbufs[tabselidx - 1], max_tab_width, v:false) 220 | if enable_sep 221 | tab ..= PlainSep(sep_index, tab_group, first_group) 222 | tabwidth += sep_width 223 | elseif first_group == tab_sel_group 224 | tab ..= '%#Crystalline' .. tab_sel_group .. '#' 225 | endif 226 | if enable_mouse 227 | tab = '%' .. tabselidx .. 'T' .. tab .. '' 228 | endif 229 | add_left_tabs = width + tabwidth <= max_width 230 | if add_left_tabs 231 | o = tab .. o 232 | tab_count += 1 233 | width += tabwidth 234 | first_group = tab_group 235 | endif 236 | endif 237 | 238 | # Add at least one tab to right of selected if present and there's space 239 | var add_right_tabs = width < max_width && tabselidx + 1 < ntabs && tab_count < max_tabs 240 | if add_right_tabs 241 | var [tab, tabwidth] = g:CrystallineTabFn(tabselidx + 2, tabbufs[tabselidx + 1], max_tab_width, v:false) 242 | if enable_mouse 243 | tab = '%' .. (tabselidx + 2) .. 'T' .. tab 244 | endif 245 | if enable_sep 246 | tab = PlainSep(sep_index, last_group, tab_group) .. tab 247 | tabwidth += sep_width 248 | elseif last_group == tab_sel_group 249 | tab = '%#Crystalline' .. tab_group .. '#' .. tab 250 | endif 251 | add_right_tabs = width + tabwidth <= max_width 252 | if add_right_tabs 253 | o ..= tab 254 | tab_count += 1 255 | width += tabwidth 256 | last_group = tab_group 257 | endif 258 | endif 259 | 260 | # Get tab separator 261 | var tab_sep = '' 262 | if enable_sep 263 | tab_sep = PlainSep(sep_index, tab_group, tab_group) 264 | endif 265 | 266 | # Add tabs to left of selected 267 | var tabidx = add_left_tabs ? tabselidx - 2 : -1 268 | while tabidx >= 0 && width < max_width && tab_count < max_tabs 269 | var [tab, tabwidth] = g:CrystallineTabFn(tabidx + 1, tabbufs[tabidx], max_tab_width, v:false) 270 | if enable_sep 271 | tab ..= tab_sep 272 | tabwidth += sep_width 273 | endif 274 | if enable_mouse 275 | tab = '%' .. (tabidx + 1) .. 'T' .. tab 276 | endif 277 | if width + tabwidth > max_width 278 | break 279 | endif 280 | o = tab .. o 281 | tab_count += 1 282 | width += tabwidth 283 | tabidx -= 1 284 | endwhile 285 | 286 | # Add other tabs to right of selected 287 | tabidx = add_right_tabs ? tabselidx + 2 : ntabs 288 | while tabidx < ntabs && width < max_width && tab_count < max_tabs 289 | var [tab, tabwidth] = g:CrystallineTabFn(tabidx + 1, tabbufs[tabidx], max_tab_width, v:false) 290 | if enable_mouse 291 | tab = '%' .. (tabidx + 1) .. 'T' .. tab 292 | endif 293 | if enable_sep 294 | tab = tab_sep .. tab 295 | tabwidth += sep_width 296 | endif 297 | if width + tabwidth > max_width 298 | break 299 | endif 300 | o ..= tab 301 | tab_count += 1 302 | width += tabwidth 303 | tabidx += 1 304 | endwhile 305 | 306 | if enable_left_sep 307 | # Draw left separator 308 | o = PlainSep(sep_index, left_group, first_group) .. o 309 | else 310 | # Draw first group 311 | o = '%#Crystalline' .. first_group .. '#' .. o 312 | endif 313 | 314 | if enable_right_sep 315 | # Draw right separator 316 | o ..= PlainSep(sep_index, last_group, right_group) 317 | elseif right_group !=# '' 318 | # Draw right group 319 | o ..= '%#Crystalline' .. right_group .. '#' 320 | endif 321 | 322 | # End final tab 323 | if enable_mouse 324 | o ..= '%T' 325 | endif 326 | 327 | return o 328 | enddef 329 | 330 | # }}} 331 | 332 | # vim:set et sw=2 ts=2 fdm=marker: 333 | --------------------------------------------------------------------------------