├── .gitignore ├── FUNDING.yml ├── LICENSE ├── README.md ├── autoload └── mistfly.vim ├── doc └── mistfly.txt └── plugin └── mistfly-statusline.vim /.gitignore: -------------------------------------------------------------------------------- 1 | doc/tags 2 | -------------------------------------------------------------------------------- /FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: bluz71 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-present vim-mistfly-statusline authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | mistfly statusline 2 | ================== 3 | 4 | _mistfly statusline_ is a simple, fast and informative `statusline` for Vim. 5 | 6 | :point_right: Neovim users should use the pure-Lua 7 | [linefly](https://github.com/bluz71/nvim-linefly) plugin instead of _mistfly_. 8 | 9 | _mistfly_ provides a number of useful builtin components: 10 | 11 | - Git changes 12 | - Diagnostic status 13 | - Macro-recording status 14 | - Current search count 15 | - Spell status 16 | - Indent status (tabs or spaces and their associated width) 17 | 18 | _mistfly_ also provides optional `tabline` support when the appropriate setting 19 | is enabled; refer to 20 | [`mistflyTabLine`](https://github.com/bluz71/vim-mistfly-statusline#mistflytabline). 21 | 22 | _mistfly_ will adapt it's colors to the colorscheme currently in effect. Colors 23 | can also be 24 | [customized](https://github.com/bluz71/vim-mistfly-statusline#highlight-groups-and-colors) 25 | if desired. 26 | 27 | Lastly, _mistfly_ is a lean `statusline` plugin clocking in at about 500 lines 28 | of code. For comparison, the 29 | [lightline](https://github.com/itchyny/lightline.vim) and 30 | [airline](https://github.com/vim-airline/vim-airline) `statusline` plugins 31 | contain over 3,700 and 7,400 lines of code respectively. In fairness, the latter 32 | plugins are more featureful, configurable and visually pleasing. 33 | 34 | :warning: _mistfly_ has a predominantly fixed layout, this will **not** be an 35 | appropriate `statusline` plugin if layout flexibility is desired. 36 | 37 | Screenshots 38 | ----------- 39 | 40 | ![normal](https://raw.githubusercontent.com/bluz71/misc-binaries/master/statusline/statusline-normal.png) 41 | ![insert](https://raw.githubusercontent.com/bluz71/misc-binaries/master/statusline/statusline-insert.png) 42 | ![visual](https://raw.githubusercontent.com/bluz71/misc-binaries/master/statusline/statusline-visual.png) 43 | ![command](https://raw.githubusercontent.com/bluz71/misc-binaries/master/statusline/statusline-command.png) 44 | ![replace](https://raw.githubusercontent.com/bluz71/misc-binaries/master/statusline/statusline-replace.png) 45 | 46 | The above screenshots are using the 47 | [nightfly](https://github.com/bluz71/vim-moonfly-colors) colorscheme and the 48 | [Iosevka](https://github.com/be5invis/Iosevka) font with Git changes, 49 | diagnostics and indent-status enabled. 50 | 51 | Statusline Startup Comparison 52 | ----------------------------- 53 | 54 | A startup comparison of _mistfly_ against various popular `statusline` 55 | plugins, with their out-of-the-box defaults, on a clean and minimal Vim setup 56 | with the [moonfly](https://github.com/bluz71/vim-moonfly-colors) colorscheme. 57 | The Vim startup times in the following table are provived by the 58 | [dstein64/vim-startuptime](https://github.com/dstein64/vim-startuptime) plugin. 59 | 60 | Startup times are the average of five consecutive runs. Note, `stock` is run 61 | without any `statusline` plugin. 62 | 63 | | stock | mistfly | lightline | airline 64 | |--------|---------|-----------|-------- 65 | | 18.0ms | 18.7ms | 22.0ms | 76.0ms 66 | 67 | Startup times as of March 2024 on my system; performance on other systems 68 | will vary. 69 | 70 | Plugins, Linters and Diagnostics supported 71 | ------------------------------------------ 72 | 73 | - [vim-devicons](https://github.com/ryanoasis/vim-devicons) and 74 | [nvim-web-devicons](https://github.com/kyazdani42/nvim-web-devicons) 75 | 76 | - [Gitsigns](https://github.com/lewis6991/gitsigns.nvim) 77 | 78 | - [GitGutter](https://github.com/airblade/vim-gitgutter) 79 | 80 | - [Signify](https://github.com/mhinz/vim-signify) 81 | 82 | - [ALE](https://github.com/dense-analysis/ale) 83 | 84 | - [Coc](https://github.com/neoclide/coc.nvim) 85 | 86 | - [Obsession](https://github.com/tpope/vim-obsession) 87 | 88 | :zap: Requirements 89 | ------------------ 90 | 91 | _mistfly_ requires Vim 8 (or later), Neovim is not supported. The pure-Lua 92 | [linefly](https://github.com/bluz71/nvim-linefly) plugin should instead be used 93 | with Neovim. 94 | 95 | Please also make sure that the `laststatus` option is set to either: `1`, `2` 96 | or `3`. 97 | 98 | Installation 99 | ------------ 100 | 101 | Install **bluz71/vim-mistfly-statusline** with your preferred plugin manager. 102 | 103 | [vim-plug](https://github.com/junegunn/vim-plug): 104 | 105 | ```vim 106 | Plug 'bluz71/vim-mistfly-statusline' 107 | ``` 108 | 109 | [lazy.nvim](https://github.com/folke/lazy.nvim): 110 | 111 | ```lua 112 | { 'bluz71/vim-mistfly-statusline' }, 113 | ``` 114 | 115 | Please do **not** lazy-load _mistfly_. 116 | 117 | Layout And Default Colors 118 | ------------------------- 119 | 120 | The *mistfly-statusline* layout consists of two groupings, the left-side and 121 | right-side as follows: 122 | 123 | ``` 124 | +-------------------------------------------------+ 125 | | A | B | C | D W | X | Y | Z | 126 | +-------------------------------------------------+ 127 | ``` 128 | 129 | | Section | Purpose 130 | |---------|------------------ 131 | | A`*` | Mode status (normal, insert, visual, command and replace modes) 132 | | B | Filename (refer below for details) 133 | | C`*` | Git branch name (if applicable) 134 | | D`*` | Plugins notification (git, diagnostic and session status) 135 | | W | Optional search count and spell status 136 | | X | Current position 137 | | Y`*` | Total lines and current location as percentage 138 | | Z | Optional indent status (spaces and tabs shift width) 139 | 140 | Sections marked with a `*` are linked to a highlight group and are colored, 141 | refer to the next section for details. 142 | 143 | Sections C, D & W will **not** be displayed when the `statusline` width is less 144 | than 80 columns. 145 | 146 | Note, filenames will be displayed as follows: 147 | 148 | - Pathless filenames only for files in the current working directory 149 | 150 | - Relative paths in preference to absolute paths for files not in the current 151 | working directory 152 | 153 | - `~`-style home directory paths in preference to absolute paths 154 | 155 | - Possibly shortened, for example `foo/bar/bazz/hello.txt` will be displayed as 156 | `f/b/b/hello.txt` when `statusline` width is less than 120 columns. 157 | 158 | - Possibly trimmed. A maximum of four path components will be displayed for a 159 | filename; if a filename is more deeply nested then only the four most 160 | significant components, including the filename, will be displayed with an 161 | ellipsis prefix symbol used to indicate path trimming. 162 | 163 | Highlight Groups And Colors 164 | --------------------------- 165 | 166 | Sections marked with `*` in the previous section are linked to the following 167 | custom highlight groups with their associated fallbacks if the current 168 | colorscheme does not support _mistfly_. 169 | 170 | | Segment | Custom Highlight Group | Synthesized Highlight Fallback 171 | |--------------------------|------------------------|------------------------------- 172 | | Normal Mode | `MistflyNormal` | `Directory` 173 | | Insert Mode | `MistflyInsert` | `String` 174 | | Visual Mode | `MistflyVisual` | `Statement` 175 | | Command Mode | `MistflyCommand` | `WarningMsg` 176 | | Replace Mode | `MistflyReplace` | `Error` 177 | 178 | Note, the following colorschemes support _mistfly_, either within the 179 | colorscheme (moonfly & nightfly) or within this plugin (all others): 180 | 181 | - [moonfly](https://github.com/bluz71/vim-moonfly-colors) 182 | 183 | - [nightfly](https://github.com/bluz71/vim-nightfly-guicolors) 184 | 185 | - [dracula](https://github.com/dracula/vim) 186 | 187 | - [edge](https://github.com/sainnhe/edge) 188 | 189 | - [embark](https://github.com/embark-theme/vim) 190 | 191 | - [everforest](https://github.com/sainnhe/everforest) 192 | 193 | - [gruvbox](https://github.com/gruvbox-community/gruvbox) 194 | 195 | - [gruvbox-material](https://github.com/sainnhe/gruvbox-material) 196 | 197 | - [retrobox](https://github.com/vim/colorschemes) 198 | 199 | - [sonokai](https://github.com/sainnhe/sonokai) 200 | 201 | Lastly, if the fallback colors do not suit then it is very easy to override with 202 | your own highlights. 203 | 204 | :gift: Here is a simple example of customized _mistfly_ colors. Save the 205 | following at the end of your initialization file after setting your 206 | `colorscheme`. 207 | 208 | ```vim 209 | highlight! link MistflyNormal DiffChange 210 | highlight! link MistflyInsert WildMenu 211 | highlight! link MistflyVisual IncSearch 212 | highlight! link MistflyCommand WildMenu 213 | highlight! link MistflyReplace ErrorMsg 214 | ``` 215 | 216 | :wrench: Options 217 | ---------------- 218 | 219 | | Option | Default State 220 | |--------|-------------- 221 | | [mistflySeparatorSymbol](https://github.com/bluz71/vim-mistfly-statusline#mistflyseparatorsymbol) | `⎪` 222 | | [mistflyProgressSymbol](https://github.com/bluz71/vim-mistfly-statusline#mistflyprogresssymbol) | `↓` 223 | | [mistflyActiveTabSymbol](https://github.com/bluz71/vim-mistfly-statusline#mistflyactivetabsymbol) | `▪` 224 | | [mistflyGitBranchSymbol](https://github.com/bluz71/vim-mistfly-statusline#mistflygitbranchsymbol) | `` 225 | | [mistflyErrorSymbol](https://github.com/bluz71/vim-mistfly-statusline#mistflyerrorsymbol) | `E` 226 | | [mistflyWarningSymbol](https://github.com/bluz71/vim-mistfly-statusline#mistflywarningsymbol) | `W` 227 | | [mistflyInformationSymbol](https://github.com/bluz71/vim-mistfly-statusline#mistflyinformationsymbol) | `I` 228 | | [mistflyEllipsisSymbol](https://github.com/bluz71/vim-mistfly-statusline#mistflyellipsissymbol) | `…` 229 | | [mistflyTabLine](https://github.com/bluz71/vim-mistfly-statusline#mistflytabline) | Disabled 230 | | [mistflyWithFileIcon](https://github.com/bluz71/vim-mistfly-statusline#mistflywithfileicon) | Enabled 231 | | [mistflyWithGitBranch](https://github.com/bluz71/vim-mistfly-statusline#mistflywithgitbranch) | Enabled 232 | | [mistflyWithGitStatus](https://github.com/bluz71/vim-mistfly-statusline#mistflywithgitstatus) | Enabled 233 | | [mistflyWithDiagnosticStatus](https://github.com/bluz71/vim-mistfly-statusline#mistflywithdiagnosticstatus) | Enabled 234 | | [mistflyWithSessionStatus](https://github.com/bluz71/vim-mistfly-statusline#mistflywithsessionstatus) | Enabled 235 | | [mistflyWithSearchCount](https://github.com/bluz71/vim-mistfly-statusline#mistflywithsearchcount) | Disabled 236 | | [mistflyWithSpellStatus](https://github.com/bluz71/vim-mistfly-statusline#mistflyWithspellstatus) | Disabled 237 | | [mistflyWithIndentStatus](https://github.com/bluz71/vim-mistfly-statusline#mistflywithindentstatus) | Disabled 238 | 239 | --- 240 | 241 | ### mistflySeparatorSymbol 242 | 243 | The `mistflySeparatorSymbol` option specifies which character symbol to use 244 | for segment separators in the `statusline`. 245 | 246 | By default, the `⎪` character (Unicode `U+23AA`) will be displayed. 247 | 248 | To specify your own separator symbol please add the following to your 249 | initialization file: 250 | 251 | ```vim 252 | " Vimscript initialization file 253 | let g:mistflySeparatorSymbol = '<>' 254 | ``` 255 | 256 | ```lua 257 | -- Lua initialization file 258 | vim.g.mistflySeparatorSymbol = '<>' 259 | ``` 260 | 261 | --- 262 | 263 | ### mistflyProgressSymbol 264 | 265 | The `mistflyProgressSymbol` option specifies which character symbol to use to 266 | indicate location-as-percentage in the `statusline`. 267 | 268 | By default, the `↓` character (Unicode `U+2193`) will be displayed. 269 | 270 | To specify your own progress symbol, or no symbol at all, please add the 271 | following to your initialization file: 272 | 273 | ```vim 274 | " Vimscript initialization file 275 | let g:mistflyProgressSymbol = '<>' 276 | ``` 277 | 278 | ```lua 279 | -- Lua initialization file 280 | vim.g.mistflyProgressSymbol = '<>' 281 | ``` 282 | 283 | --- 284 | 285 | ### mistflyActiveTabSymbol 286 | 287 | The `mistflyActiveTabSymbol` option specifies which character symbol to use to 288 | signify the active tab in the `tabline`. 289 | 290 | By default, the `▪` character (Unicode `U+25AA`) will be displayed. 291 | 292 | To specify your own active tab symbol please add the following to your 293 | initialization file: 294 | 295 | ```vim 296 | " Vimscript initialization file 297 | let g:mistflyActiveTabSymbol = '<>' 298 | ``` 299 | 300 | ```lua 301 | -- Lua initialization file 302 | vim.g.mistflyActiveTabSymbol = '<>' 303 | ``` 304 | 305 | --- 306 | 307 | ### mistflyGitBranchSymbol 308 | 309 | The `mistflyGitBranchSymbol` option specifies which character symbol to use 310 | when displaying Git branch details. 311 | 312 | By default, the `` character (Powerline `U+E0A0`) will be displayed. Many 313 | modern monospace fonts will contain that character. 314 | 315 | To specify your own Git branch symbol, or no symbol at all, please add the 316 | following to your initialization file: 317 | 318 | ```vim 319 | " Vimscript initialization file 320 | let g:mistflyGitBranchSymbol = '<>' 321 | ``` 322 | 323 | ```lua 324 | -- Lua initialization file 325 | vim.g.mistflyGitBranchSymbol = '<>' 326 | ``` 327 | 328 | --- 329 | 330 | ### mistflyErrorSymbol 331 | 332 | The `mistflyErrorSymbol` option specifies which character symbol to use when 333 | displaying diagnostic errors. 334 | 335 | By default, the `E` character will be displayed. 336 | 337 | To specify your own error symbol please add the following to your 338 | initialization file: 339 | 340 | ```vim 341 | " Vimscript initialization file 342 | let g:mistflyErrorSymbol = '<>' 343 | ``` 344 | 345 | ```lua 346 | -- Lua initialization file 347 | vim.g.mistflyErrorSymbol = '<>' 348 | ``` 349 | 350 | --- 351 | 352 | ### mistflyWarningSymbol 353 | 354 | The `mistflyWarningSymbol` option specifies which character symbol to use when 355 | displaying diagnostic warnings. 356 | 357 | By default, the `W` character will be displayed. 358 | 359 | To specify your own warning symbol please add the following to your 360 | initialization file: 361 | 362 | ```vim 363 | " Vimscript initialization file 364 | let g:mistflyWarningSymbol = '<>' 365 | ``` 366 | 367 | ```lua 368 | -- Lua initialization file 369 | vim.g.mistflyWarningSymbol = '<>' 370 | ``` 371 | 372 | --- 373 | 374 | ### mistflyInformationSymbol 375 | 376 | The `mistflyInformationSymbol` option specifies which character symbol to use 377 | when displaying diagnostic information. 378 | 379 | By default, the `I` character will be displayed. 380 | 381 | To specify your own information symbol please add the following to your 382 | initialization file: 383 | 384 | ```vim 385 | " Vimscript initialization file 386 | let g:mistflyInformationSymbol = '<>' 387 | ``` 388 | 389 | ```lua 390 | -- Lua initialization file 391 | vim.g.mistflyInformationSymbol = '<>' 392 | ``` 393 | 394 | --- 395 | 396 | ### mistflyEllipsisSymbol 397 | 398 | The `mistflyEllipsisSymbol` option specifies which character symbol to use when 399 | indicating truncation, for example, deeply nested path truncation. 400 | 401 | By default, the `…` character will be displayed. 402 | 403 | To specify your own ellipsis symbol please add the following to your 404 | initialization file: 405 | 406 | ```vim 407 | " Vimscript initialization file 408 | let g:mistflyEllipsisSymbol = '<>' 409 | ``` 410 | 411 | ```lua 412 | -- Lua initialization file 413 | vim.g.mistflyEllipsisSymbol = '<>' 414 | ``` 415 | 416 | --- 417 | 418 | ### mistflyTabLine 419 | 420 | The `mistflyTabLine` option specifies whether to let this plugin manage the 421 | `tabline` in addition to the `statusline`. 422 | 423 | By default, `tabline` management will not be undertaken. 424 | 425 | If enabled, _mistfly_ will render a simple numbered, and clickable, 426 | window-space layout in the `tabline`; note, no buffers will be displayed in 427 | the `tabline` since there are many plugins that already provide that 428 | capability. 429 | 430 | To enable `tabline` support please add the following to your initialization 431 | file: 432 | 433 | ```vim 434 | " Vimscript initialization file 435 | let g:mistflyTabLine = v:true 436 | ``` 437 | 438 | ```lua 439 | -- Lua initialization file 440 | vim.g.mistflyTabLine = true 441 | ``` 442 | 443 | :bulb: Mappings, such as the following, may be useful to quickly switch between 444 | the numbered window-spaces: 445 | 446 | ```vim 447 | nnoremap 1 1gt 448 | nnoremap 2 2gt 449 | nnoremap 3 3gt 450 | nnoremap 4 4gt 451 | nnoremap 5 5gt 452 | nnoremap 6 6gt 453 | nnoremap 7 7gt 454 | nnoremap 8 8gt 455 | nnoremap 9 9gt 456 | ``` 457 | 458 | A screenshot of the `tabline`: 459 | 460 | ![tabline](https://raw.githubusercontent.com/bluz71/misc-binaries/master/statusline/tabline.png) 461 | 462 | --- 463 | 464 | ### mistflyWithFileIcon 465 | 466 | The `mistflyWithFileIcon` option specifies whether a filetype icon, from a 467 | Nerd Font, will be displayed prior to the filename in the `statusline`. 468 | 469 | Note, a [Nerd Font](https://www.nerdfonts.com) must be active **and** the 470 | [vim-devicons](https://github.com/ryanoasis/vim-devicons) or 471 | [nvim-web-devicons](https://github.com/kyazdani42/nvim-web-devicons) plugin 472 | must also be installed and active. 473 | 474 | By default, a filetype icon will be displayed if possible. 475 | 476 | To disable the display of a filetype icon please add the following to your 477 | initialization file: 478 | 479 | ```vim 480 | " Vimscript initialization file 481 | let g:mistflyWithFileIcon = v:false 482 | ``` 483 | 484 | ```lua 485 | -- lua initialization file 486 | vim.g.mistflyWithFileIcon = false 487 | ``` 488 | 489 | --- 490 | 491 | ### mistflyWithGitBranch 492 | 493 | The `mistflyWithGitBranch` option specifies whether to display Git branch 494 | details in the `statusline`. 495 | 496 | By default, Git branches will be displayed in the `statusline`. 497 | 498 | To disable the display of Git branches in the `statusline` please add the 499 | following to your initialization file: 500 | 501 | ```vim 502 | " Vimscript initialization file 503 | let g:mistflyWithGitBranch = v:false 504 | ``` 505 | 506 | ```lua 507 | -- Lua initialization file 508 | vim.g.mistflyWithGitBranch = false 509 | ``` 510 | 511 | --- 512 | 513 | ### mistflyWithGitStatus 514 | 515 | The `mistflyWithGitStatus` option specifies whether to display the Git status 516 | of the current buffer in the `statusline`. 517 | 518 | The [Gitsigns](https://github.com/lewis6991/gitsigns.nvim), 519 | [GitGutter](https://github.com/airblade/vim-gitgutter) and 520 | [Signify](https://github.com/mhinz/vim-signify) plugins are supported. 521 | 522 | By default, the Git status will be displayed if one of the above plugins is 523 | loaded. 524 | 525 | To disable the display of Git status in the `statusline` please add the 526 | following to your initialization file: 527 | 528 | ```vim 529 | " Vimscript initialization file 530 | let g:mistflyWithGitStatus = v:false 531 | ``` 532 | 533 | ```lua 534 | -- Lua initialization file 535 | vim.g.mistflyWithGitStatus = false 536 | ``` 537 | 538 | --- 539 | 540 | ### mistflyWithDiagnosticStatus 541 | 542 | The `mistflyWithDiagnosticStatus` option specifies whether to indicate the 543 | presence of the diagnostics in the current buffer. 544 | 545 | [ALE](https://github.com/dense-analysis/ale) and 546 | [Coc](https://github.com/neoclide/coc.nvim) are supported. 547 | 548 | By default, diagnostics will be displayed if one of the above plugins is 549 | loaded. 550 | 551 | If diagnostic display is not wanted then please add the following to your 552 | initialization file: 553 | 554 | ```vim 555 | " Vimscript initialization file 556 | let g:mistflyWithDiagnosticStatus = v:false 557 | ``` 558 | 559 | ```lua 560 | -- Lua initialization file 561 | vim.g.mistflyWithDiagnosticStatus = false 562 | ``` 563 | 564 | --- 565 | 566 | ### mistflyWithSessionStatus 567 | 568 | The `mistflyWithSessionStatus` option specifies whether to display 569 | [Obsession](https://github.com/tpope/vim-obsession) session details in the 570 | `statusline`. 571 | 572 | By default, session details will be displayed if the plugin is loaded. 573 | 574 | To disable the display of session details in the `statusline` please add the 575 | following to your initialization file: 576 | 577 | ```vim 578 | " Vimscript initialization file 579 | let g:mistflyWithSessionStatus = v:false 580 | ``` 581 | 582 | ```lua 583 | -- Lua initialization file 584 | vim.g.mistflyWithSessionStatus = false 585 | ``` 586 | 587 | --- 588 | 589 | ### mistflyWithSearchCount 590 | 591 | The `mistflyWithSearchCount` option specifies whether to display the search 592 | count in the `statusline`. 593 | 594 | By default, search count will not be displayed. 595 | 596 | To enable the display of the search count in the `statusline` please add the 597 | following to your initialization file: 598 | 599 | ```vim 600 | " Vimscript initialization file 601 | let g:mistflyWithSearchCount = v:true 602 | ``` 603 | 604 | ```lua 605 | -- Lua initialization file 606 | vim.g.mistflyWithSearchCount = true 607 | ``` 608 | 609 | Note, the search count is only displayed when the `hlsearch` option is set and 610 | the search count result is not zero. 611 | 612 | --- 613 | 614 | ### mistflyWithSpellStatus 615 | 616 | The `mistflyWithSpellStatus` option specifies whether to display the spell 617 | status in the `statusline`. 618 | 619 | By default, spell status will not be displayed. 620 | 621 | To enable spell status in the `statusline` please add the following to your 622 | initialization file: 623 | 624 | ```vim 625 | " Vimscript initialization file 626 | let g:mistflyWithSpellStatus = v:true 627 | ``` 628 | 629 | ```lua 630 | -- Lua initialization file 631 | vim.g.mistflyWithSpellStatus = true 632 | ``` 633 | 634 | --- 635 | 636 | ### mistflyWithIndentStatus 637 | 638 | The `mistflyWithIndentStatus` option specifies whether to display the 639 | indentation status as the last component in the `statusline`. 640 | 641 | By default, indentation status will not be displayed. 642 | 643 | Note, if the `expandtab` option is set, for the current buffer, then tab stop 644 | will be displayed, for example `Tab:4` (tab equals four spaces); if on the 645 | other hand `noexpandtab` option is set then shift width will be displayed 646 | instead, for example `Spc:2` ('spc' short for 'space'). 647 | 648 | To enable indentation status please add the following to your initialization 649 | file: 650 | 651 | ```vim 652 | " Vimscript initialization file 653 | let g:mistflyWithIndentStatus = v:true 654 | ``` 655 | 656 | ```lua 657 | -- Lua initialization file 658 | vim.g.mistflyWithIndentStatus = true 659 | ``` 660 | 661 | Sponsor 662 | ------- 663 | 664 | [![Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/bluz71) 665 | 666 | License 667 | ------- 668 | 669 | [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) 670 | -------------------------------------------------------------------------------- /autoload/mistfly.vim: -------------------------------------------------------------------------------- 1 | " Refer to ':help mode()' for the full list of available modes. For now only 2 | " handle the most common modes. 3 | let s:modes_map = { 4 | \ 'n': ['%#MistflyNormal#', ' normal ', '%#MistflyNormalEmphasis#'], 5 | \ 'no': ['%#MistflyNormal#', ' o-pend ', '%#MistflyNormalEmphasis#'], 6 | \ 'niI': ['%#MistflyNormal#', ' i-pend ', '%#MistflyNormalEmphasis#'], 7 | \ 'niR': ['%#MistflyNormal#', ' r-pend ', '%#MistflyNormalEmphasis#'], 8 | \ 'i': ['%#MistflyInsert#', ' insert ', '%#MistflyInsertEmphasis#'], 9 | \ 'ic': ['%#MistflyInsert#', ' i-comp ', '%#MistflyInsertEmphasis#'], 10 | \ 'ix': ['%#MistflyInsert#', ' i-comp ', '%#MistflyInsertEmphasis#'], 11 | \ 'v': ['%#MistflyVisual#', ' visual ', '%#MistflyVisualEmphasis#'], 12 | \ 'vs': ['%#MistflyVisual#', ' visual ', '%#MistflyVisualEmphasis#'], 13 | \ 'V': ['%#MistflyVisual#', ' v-line ', '%#MistflyVisualEmphasis#'], 14 | \ 'Vs': ['%#MistflyVisual#', ' v-line ', '%#MistflyVisualEmphasis#'], 15 | \ "\": ['%#MistflyVisual#', ' v-bloc ', '%#MistflyVisualEmphasis#'], 16 | \ 's': ['%#MistflyVisual#', ' select ', '%#MistflyVisualEmphasis#'], 17 | \ 'S': ['%#MistflyVisual#', ' s-line ', '%#MistflyVisualEmphasis#'], 18 | \ "\": ['%#MistflyVisual#', ' s-bloc ', '%#MistflyVisualEmphasis#'], 19 | \ 'c': ['%#MistflyCommand#', ' c-mode ', '%#MistflyCommandEmphasis#'], 20 | \ 'r': ['%#MistflyCommand#', ' prompt ', '%#MistflyCommandEmphasis#'], 21 | \ 'rm': ['%#MistflyCommand#', ' prompt ', '%#MistflyCommandEmphasis#'], 22 | \ 'r?': ['%#MistflyCommand#', ' prompt ', '%#MistflyCommandEmphasis#'], 23 | \ '!': ['%#MistflyCommand#', ' !-mode ', '%#MistflyCommandEmphasis#'], 24 | \ 'R': ['%#MistflyReplace#', ' r-mode ', '%#MistflyReplaceEmphasis#'], 25 | \ 'Rc': ['%#MistflyReplace#', ' r-comp ', '%#MistflyReplaceEmphasis#'], 26 | \ 'Rx': ['%#MistflyReplace#', ' r-comp ', '%#MistflyReplaceEmphasis#'], 27 | \ 't': ['%#MistflyInsert#', ' t-mode ', '%#MistflyInsertEmphasis#'], 28 | \ 'nt': ['%#MistflyInsert#', ' normal ', '%#MistflyInsertEmphasis#'], 29 | \} 30 | 31 | " Cache current statusline background for performance reasons; that being to 32 | " avoid needless highlight extraction and generation. 33 | let s:statusline_bg = '' 34 | 35 | "=========================================================== 36 | " Utilities 37 | "=========================================================== 38 | 39 | function! s:StatuslineWidth() abort 40 | if &laststatus == 3 41 | return &columns 42 | else 43 | return winwidth(0) 44 | end 45 | endfunction 46 | 47 | function! mistfly#File() abort 48 | let l:statusline_width = s:StatuslineWidth() 49 | 50 | return s:FileIcon() . s:FilePath(l:statusline_width < 120) 51 | endfunction 52 | 53 | function! s:FileIcon() abort 54 | if !g:mistflyWithFileIcon || bufname('%') == '' 55 | return '' 56 | endif 57 | 58 | if exists('g:nvim_web_devicons') 59 | return luaeval("require'nvim-web-devicons'.get_icon(vim.fn.expand('%'), nil, { default = true })") . ' ' 60 | elseif exists('g:loaded_webdevicons') 61 | return WebDevIconsGetFileTypeSymbol() . ' ' 62 | else 63 | return '' 64 | endif 65 | endfunction 66 | 67 | function! s:FilePath(short_path) abort 68 | if len(expand('%:f')) == 0 69 | return '' 70 | end 71 | 72 | if &buftype ==# 'terminal' 73 | return expand('%:t') 74 | endif 75 | 76 | let l:separator = '/' 77 | if has('win64') 78 | let l:separator = '\' 79 | endif 80 | 81 | if a:short_path 82 | let l:path = pathshorten(fnamemodify(expand('%:f'), ':~:.')) 83 | else 84 | let l:path = fnamemodify(expand('%:f'), ':~:.') 85 | endif 86 | let l:pathComponents = split(l:path, l:separator) 87 | let l:numPathComponents = len(l:pathComponents) 88 | if l:numPathComponents > 4 89 | let l:path = g:mistflyEllipsisSymbol . l:separator 90 | let l:path .= join(l:pathComponents[l:numPathComponents - 4:], l:separator) 91 | endif 92 | 93 | return l:path 94 | endfunction 95 | 96 | " Iterate though the windows and update the statusline for all inactive windows. 97 | " 98 | " This is needed when starting Vim with multiple splits, for example 'vim -O 99 | " file1 file2', otherwise all statuslines will be rendered as if they are 100 | " active. Inactive statuslines are usually rendered via the WinLeave and 101 | " BufLeave events, but those events are not triggered when starting Vim. 102 | " 103 | " Note - https://jip.dev/posts/a-simpler-vim-statusline/#inactive-statuslines 104 | function! mistfly#UpdateInactiveWindows() abort 105 | for winnum in range(1, winnr('$')) 106 | if winnum != winnr() 107 | call setwinvar(winnum, '&statusline', '%!mistfly#InactiveStatusLine()') 108 | endif 109 | endfor 110 | endfunction 111 | 112 | function! mistfly#GitBranchName() abort 113 | if !g:mistflyWithGitBranch || bufname('%') == '' 114 | return '' 115 | endif 116 | 117 | let l:git_branch_name = '' 118 | if exists('g:loaded_fugitive') 119 | " Fugitive is available, let's use it to access the branch name. 120 | let l:git_branch_name = FugitiveHead() 121 | elseif exists('b:git_branch_name') 122 | " Else use fallback detection. 123 | let l:git_branch_name = b:git_branch_name 124 | endif 125 | 126 | if len(l:git_branch_name) == 0 127 | return '' 128 | elseif strlen(l:git_branch_name) > 30 129 | " Truncate long branch names to 30 characters. 130 | let l:git_branch_name = strpart(l:git_branch_name, 0, 29) . g:mistflyEllipsisSymbol 131 | endif 132 | 133 | if len(g:mistflyGitBranchSymbol) == 0 134 | return ' ' . l:git_branch_name 135 | else 136 | return ' ' . g:mistflyGitBranchSymbol . ' ' . l:git_branch_name 137 | endif 138 | endfunction 139 | 140 | function! mistfly#PluginsStatus() abort 141 | let l:segments = '' 142 | let l:added = 0 143 | let l:changed = 0 144 | let l:removed = 0 145 | let l:errors = 0 146 | let l:warnings = 0 147 | let l:information = 0 148 | 149 | if g:mistflyWithGitStatus && has('nvim-0.5') && luaeval("package.loaded.gitsigns ~= nil") 150 | " Gitsigns status. 151 | let l:counts = get(b:, 'gitsigns_status_dict', {}) 152 | let l:added = get(l:counts, 'added', 0) 153 | let l:changed = get(l:counts, 'changed', 0) 154 | let l:removed = get(l:counts, 'removed', 0) 155 | elseif g:mistflyWithGitStatus && exists('g:loaded_gitgutter') && get(g:, 'gitgutter_enabled') 156 | " GitGutter status. 157 | let [l:added, l:changed, l:removed] = GitGutterGetHunkSummary() 158 | elseif g:mistflyWithGitStatus && exists('g:loaded_signify') 159 | " Signify status. 160 | let [l:added, l:changed, l:removed] = sy#repo#get_stats() 161 | endif 162 | 163 | " Git plugin status. 164 | if l:added > 0 165 | let l:segments .= ' %#MistflyGitAdd#+' . l:added . '%*' 166 | endif 167 | if l:changed > 0 168 | let l:segments .= ' %#MistflyGitChange#~' . l:changed . '%*' 169 | endif 170 | if l:removed > 0 171 | let l:segments .= ' %#MistflyGitDelete#-' . l:removed . '%*' 172 | endif 173 | if len(l:segments) > 0 174 | let l:segments .= ' ' 175 | endif 176 | 177 | if g:mistflyWithDiagnosticStatus && exists('g:loaded_ale') 178 | " ALE status. 179 | let l:counts = ale#statusline#Count(bufnr('')) 180 | if has_key(l:counts, 'error') 181 | let l:errors = l:counts['error'] 182 | endif 183 | if has_key(l:counts, 'warning') 184 | let l:warnings = l:counts['warning'] 185 | endif 186 | if has_key(l:counts, 'info') 187 | let l:information = l:counts['info'] 188 | endif 189 | elseif g:mistflyWithDiagnosticStatus && exists('g:did_coc_loaded') 190 | " Coc status. 191 | let l:counts = get(b:, 'coc_diagnostic_info', {}) 192 | if has_key(l:counts, 'error') 193 | let l:errors = l:counts['error'] 194 | endif 195 | if has_key(l:counts, 'warning') 196 | let l:warnings = l:counts['warning'] 197 | endif 198 | if has_key(l:counts, 'information') 199 | let l:information = l:counts['information'] 200 | endif 201 | endif 202 | 203 | " Display errors and warnings from any of the previous diagnostic or linting 204 | " systems. 205 | if l:errors > 0 206 | let l:segments .= ' %#MistflyDiagnosticError#' . g:mistflyErrorSymbol 207 | let l:segments .= ' ' . l:errors . '%*' 208 | endif 209 | if l:warnings > 0 210 | let l:segments .= ' %#MistflyDiagnosticWarning#' . g:mistflyWarningSymbol 211 | let l:segments .= ' ' . l:warnings . '%*' 212 | endif 213 | if l:information > 0 214 | let l:segments .= ' %#MistflyDiagnosticInformation#' . g:mistflyInformationSymbol 215 | let l:segments .= ' ' . l:information . '%*' 216 | endif 217 | if l:errors > 0 || l:warnings > 0 || l:information > 0 218 | let l:segments .= ' ' 219 | endif 220 | 221 | " Obsession plugin status. 222 | if g:mistflyWithSessionStatus && exists('g:loaded_obsession') 223 | let l:obsession_status = ObsessionStatus('obsession', '!obsession') 224 | if len(l:obsession_status) > 0 225 | let l:segments .= ' %#MistflySession#' . l:obsession_status . '%*' 226 | endif 227 | endif 228 | 229 | return l:segments 230 | endfunction 231 | 232 | function! mistfly#SearchCount() abort 233 | if !exists('*searchcount') 234 | return '' 235 | endif 236 | let l:result = searchcount(#{recompute: 1, maxcount: 0}) 237 | if empty(l:result) 238 | return '' 239 | endif 240 | if l:result.incomplete == 1 " timed out 241 | return '[?/??]' 242 | elseif l:result.incomplete == 2 " max count exceeded 243 | if l:result.total > l:result.maxcount && l:result.current > l:result.maxcount 244 | return printf('[>%d/>%d]', l:result.current, l:result.total) 245 | elseif l:result.total > l:result.maxcount 246 | return printf('[%d/>%d]', l:result.current, l:result.total) 247 | endif 248 | endif 249 | if l:result.total ==# 0 250 | return '' 251 | endif 252 | return printf('[%d/%d]', l:result.current, l:result.total) 253 | endfunction 254 | 255 | function! mistfly#IndentStatus() abort 256 | if !&expandtab 257 | return 'Tab:' . &tabstop 258 | else 259 | let l:size = &shiftwidth 260 | if l:size == 0 261 | let l:size = &tabstop 262 | end 263 | return 'Spc:' . l:size 264 | endif 265 | endfunction 266 | 267 | "=========================================================== 268 | " Status line 269 | "=========================================================== 270 | 271 | function! mistfly#ActiveStatusLine() abort 272 | let l:statusline_width = s:StatuslineWidth() 273 | 274 | let l:mode = mode() 275 | let l:separator = g:mistflySeparatorSymbol 276 | let l:progress = g:mistflyProgressSymbol 277 | let l:branch_name = mistfly#GitBranchName() 278 | let l:plugins_status = mistfly#PluginsStatus() 279 | let l:mode_emphasis = get(s:modes_map, l:mode, '%#MistflyNormalEmphasis#')[2] 280 | 281 | let l:statusline = get(s:modes_map, l:mode, '%#MistflyNormal#')[0] 282 | if l:statusline_width < 80 283 | let l:statusline .= strpart(get(s:modes_map, l:mode, 'n')[1], 0, 2) . ' ' 284 | else 285 | let l:statusline .= get(s:modes_map, l:mode, ' normal ')[1] 286 | endif 287 | let l:statusline .= '%* %<%{mistfly#File()}' 288 | let l:statusline .= "%q%{exists('w:quickfix_title')? ' ' . w:quickfix_title : ''}" 289 | let l:statusline .= "%{&modified ? '+\ ' : ' \ \ '}" 290 | let l:statusline .= "%{&readonly ? 'RO\ ' : ''}" 291 | if len(l:branch_name) > 0 && l:statusline_width >= 80 292 | let l:statusline .= '%*' . l:separator . l:mode_emphasis 293 | let l:statusline .= l:branch_name . '%* ' 294 | endif 295 | if len(l:plugins_status) > 0 && l:statusline_width >= 80 296 | let l:statusline .= mistfly#PluginsStatus() 297 | let l:statusline .= '%*' 298 | endif 299 | let l:statusline .= '%=' 300 | if g:mistflyWithSearchCount && v:hlsearch && l:statusline_width >= 80 301 | let l:search_count = mistfly#SearchCount() 302 | if len(l:search_count) > 0 303 | let l:statusline .= l:search_count . ' ' . l:separator . ' ' 304 | endif 305 | endif 306 | if g:mistflyWithSpellStatus && &spell && l:statusline_width >= 80 307 | let l:statusline .= 'Spell ' . l:separator . ' ' 308 | endif 309 | let l:statusline .= '%l:%c ' . l:separator 310 | let l:statusline .= ' ' . l:mode_emphasis . '%L%* ' . l:progress . '%P ' 311 | if g:mistflyWithIndentStatus 312 | let l:statusline .= l:separator . ' %{mistfly#IndentStatus()} ' 313 | endif 314 | 315 | return l:statusline 316 | endfunction 317 | 318 | function! mistfly#InactiveStatusLine() abort 319 | let l:separator = g:mistflySeparatorSymbol 320 | let l:progress = g:mistflyProgressSymbol 321 | 322 | let l:statusline = ' %<%{mistfly#File()}' 323 | let l:statusline .= "%{&modified?'+\ ':' \ \ '}" 324 | let l:statusline .= "%{&readonly?'RO\ ':''}" 325 | let l:statusline .= '%=%l:%c ' . l:separator . ' %L ' . l:progress . '%P ' 326 | if g:mistflyWithIndentStatus 327 | let l:statusline .= l:separator . ' %{mistfly#IndentStatus()} ' 328 | endif 329 | 330 | return l:statusline 331 | endfunction 332 | 333 | function! mistfly#NoFileStatusLine() abort 334 | return pathshorten(fnamemodify(getcwd(), ':~:.')) 335 | endfunction 336 | 337 | function! mistfly#StatusLine(active) abort 338 | if &buftype ==# 'nofile' || &filetype ==# 'netrw' 339 | " Likely a file explorer or some other special type of buffer. Set a 340 | " short path statusline for these types of buffers. 341 | setlocal statusline=%!mistfly#NoFileStatusLine() 342 | elseif &buftype ==# 'nowrite' 343 | " Don't set a custom statusline for certain special windows. 344 | return 345 | elseif a:active == v:true 346 | setlocal statusline=%!mistfly#ActiveStatusLine() 347 | elseif a:active == v:false 348 | setlocal statusline=%!mistfly#InactiveStatusLine() 349 | endif 350 | endfunction 351 | 352 | "=========================================================== 353 | " Tab line 354 | "=========================================================== 355 | 356 | function! mistfly#ActiveTabLine() abort 357 | let l:symbol = g:mistflyActiveTabSymbol 358 | let l:tabline = '' 359 | let l:counter = 0 360 | 361 | for i in range(tabpagenr('$')) 362 | let l:counter = l:counter + 1 363 | if has('tablineat') 364 | let l:tabline .= '%' . l:counter . 'T' 365 | endif 366 | if tabpagenr() == counter 367 | let l:tabline .= '%#TablineSelSymbol#' . l:symbol 368 | let l:tabline .= '%#TablineSel# Tab:' 369 | else 370 | let l:tabline .= '%#TabLine# Tab:' 371 | endif 372 | let l:tabline .= l:counter 373 | if has('tablineat') 374 | let l:tabline .= '%T' 375 | endif 376 | let l:tabline .= ' %#TabLineFill#' 377 | endfor 378 | 379 | return l:tabline 380 | endfunction 381 | 382 | function! mistfly#TabLine() abort 383 | if g:mistflyTabLine 384 | set tabline=%!mistfly#ActiveTabLine() 385 | endif 386 | endfunction 387 | 388 | "=========================================================== 389 | " Highlights 390 | "=========================================================== 391 | 392 | function! mistfly#GenerateHighlightGroups() abort 393 | if !exists('g:colors_name') 394 | return 395 | endif 396 | 397 | " Extract current StatusLine background color, we will likely need it. 398 | if synIDattr(synIDtrans(hlID('StatusLine')), 'reverse', 'gui') == 1 399 | " Need to handle reversed highlights, such as Gruvbox StatusLine. 400 | let s:statusline_bg = synIDattr(synIDtrans(hlID('StatusLine')), 'fg', 'gui') 401 | else 402 | " Most colorschemes fall through to here. 403 | let s:statusline_bg = synIDattr(synIDtrans(hlID('StatusLine')), 'bg', 'gui') 404 | endif 405 | 406 | " Mode highlights. 407 | call s:ColorSchemeModeHighlights() 408 | 409 | " Synthesize emphasis colors from the existing mode colors. 410 | call s:SynthesizeHighlight('MistflyNormalEmphasis', 'MistflyNormal', v:true) 411 | call s:SynthesizeHighlight('MistflyInsertEmphasis', 'MistflyInsert', v:true) 412 | call s:SynthesizeHighlight('MistflyVisualEmphasis', 'MistflyVisual', v:true) 413 | call s:SynthesizeHighlight('MistflyCommandEmphasis', 'MistflyCommand', v:true) 414 | call s:SynthesizeHighlight('MistflyReplaceEmphasis', 'MistflyReplace', v:true) 415 | 416 | " Synthesize plugin colors from relevant existing highlight groups. 417 | call s:ColorSchemeGitHighlights() 418 | call s:ColorSchemeDiagnosticHighlights() 419 | highlight! link LineflySession LineflyGitAdd 420 | 421 | if g:mistflyTabLine && (!hlexists('TablineSelSymbol') || synIDattr(synIDtrans(hlID('TablineSelSymbol')), 'bg') == '') 422 | highlight! link TablineSelSymbol TablineSel 423 | endif 424 | endfunction 425 | 426 | function! s:ColorSchemeModeHighlights() abort 427 | if g:colors_name == 'moonfly' || g:colors_name == 'nightfly' 428 | " Do nothing since both colorschemes already set mistfly mode colors. 429 | return 430 | elseif g:colors_name == 'edge' || g:colors_name == 'everforest' || g:colors_name == 'gruvbox-material' || g:colors_name == 'sonokai' 431 | highlight! link MistflyNormal MiniStatuslineModeNormal 432 | highlight! link MistflyInsert MiniStatuslineModeInsert 433 | highlight! link MistflyVisual MiniStatuslineModeVisual 434 | highlight! link MistflyCommand MiniStatuslineModeCommand 435 | highlight! link MistflyReplace MiniStatuslineModeReplace 436 | elseif g:colors_name == 'dracula' 437 | highlight! link MistflyNormal WildMenu 438 | highlight! link MistflyInsert Search 439 | call s:SynthesizeModeHighlight('MistflyVisual', 'String', 'WildMenu') 440 | highlight! link MistflyCommand WildMenu 441 | highlight! link MistflyReplace IncSearch 442 | elseif g:colors_name == 'gruvbox' 443 | call s:SynthesizeModeHighlight('MistflyNormal', 'GruvboxFg4', 'GruvboxBg0') 444 | call s:SynthesizeModeHighlight('MistflyInsert', 'GruvboxBlue', 'GruvboxBg0') 445 | call s:SynthesizeModeHighlight('MistflyVisual', 'GruvboxOrange', 'GruvboxBg0') 446 | call s:SynthesizeModeHighlight('MistflyCommand', 'GruvboxGreen', 'GruvboxBg0') 447 | call s:SynthesizeModeHighlight('MistflyReplace', 'GruvboxRed', 'GruvboxBg0') 448 | elseif g:colors_name == "retrobox" 449 | call s:SynthesizeModeHighlight('MistflyNormal', 'Structure', 'VertSplit') 450 | call s:SynthesizeModeHighlight('MistflyInsert', 'Directory', 'VertSplit') 451 | highlight! link MistflyVisual Visual 452 | call s:SynthesizeModeHighlight('MistflyCommand', 'MoreMsg', 'VertSplit') 453 | highlight! link MistflyReplace ErrorMsg 454 | else 455 | " Fallback for all other colorschemes. 456 | if !hlexists('MistflyNormal') || synIDattr(synIDtrans(hlID('MistflyNormal')), 'bg') == '' 457 | call s:SynthesizeModeHighlight('MistflyNormal', 'Directory', 'VertSplit') 458 | endif 459 | if !hlexists('MistflyInsert') || synIDattr(synIDtrans(hlID('MistflyInsert')), 'bg') == '' 460 | call s:SynthesizeModeHighlight('MistflyInsert', 'String', 'VertSplit') 461 | endif 462 | if !hlexists('MistflyVisual') || synIDattr(synIDtrans(hlID('MistflyVisual')), 'bg') == '' 463 | call s:SynthesizeModeHighlight('MistflyVisual', 'Statement', 'VertSplit') 464 | endif 465 | if !hlexists('MistflyCommand') || synIDattr(synIDtrans(hlID('MistflyCommand')), 'bg') == '' 466 | call s:SynthesizeModeHighlight('MistflyCommand', 'WarningMsg', 'VertSplit') 467 | endif 468 | if !hlexists('MistflyReplace') || synIDattr(synIDtrans(hlID('MistflyReplace')), 'bg') == '' 469 | call s:SynthesizeModeHighlight('MistflyReplace', 'Error', 'VertSplit') 470 | endif 471 | endif 472 | endfunction 473 | 474 | function s:ColorSchemeGitHighlights() abort 475 | if hlexists('GitSignsAdd') 476 | call s:SynthesizeHighlight('MistflyGitAdd', 'GitSignsAdd', v:false) 477 | call s:SynthesizeHighlight('MistflyGitChange', 'GitSignsChange', v:false) 478 | call s:SynthesizeHighlight('MistflyGitDelete', 'GitSignsDelete', v:false) 479 | elseif hlexists('GitGutterAdd') 480 | call s:SynthesizeHighlight('MistflyGitAdd', 'GitGutterAdd', v:false) 481 | call s:SynthesizeHighlight('MistflyGitChange', 'GitGutterChange', v:false) 482 | call s:SynthesizeHighlight('MistflyGitDelete', 'GitGutterDelete', v:false) 483 | elseif hlexists('SignifySignAdd') 484 | call s:SynthesizeHighlight('MistflyGitAdd', 'SignifySignAdd', v:false) 485 | call s:SynthesizeHighlight('MistflyGitChange', 'SignifySignChange', v:false) 486 | call s:SynthesizeHighlight('MistflyGitDelete', 'SignifySignDelete', v:false) 487 | elseif hlexists('diffAdded') 488 | call s:SynthesizeHighlight('MistflyGitAdd', 'diffAdded', v:false) 489 | call s:SynthesizeHighlight('MistflyGitChange', 'diffChanged', v:false) 490 | call s:SynthesizeHighlight('MistflyGitDelete', 'diffRemoved', v:false) 491 | else 492 | highlight! link MistflyGitAdd StatusLine 493 | highlight! link MistflyGitChange StatusLine 494 | highlight! link MistflyGitDelete StatusLine 495 | endif 496 | endfunction 497 | 498 | function s:ColorSchemeDiagnosticHighlights() abort 499 | if hlexists('DiagnosticError') 500 | call s:SynthesizeHighlight('MistflyDiagnosticError', 'DiagnosticError', v:false) 501 | elseif hlexists('ALEErrorSign') 502 | call s:SynthesizeHighlight('MistflyDiagnosticError', 'ALEErrorSign', v:false) 503 | elseif hlexists('CocErrorSign') 504 | call s:SynthesizeHighlight('MistflyDiagnosticError', 'CocErrorSign', v:false) 505 | else 506 | highlight! link MistflyDiagnosticError StatusLine 507 | endif 508 | if hlexists('DiagnosticWarn') 509 | call s:SynthesizeHighlight('MistflyDiagnosticWarning', 'DiagnosticWarn', v:false) 510 | elseif hlexists('ALEWarningSign') 511 | call s:SynthesizeHighlight('MistflyDiagnosticWarning', 'ALEWarningSign', v:false) 512 | elseif hlexists('CocWarningSign') 513 | call s:SynthesizeHighlight('MistflyDiagnosticWarning', 'CocWarningSign', v:false) 514 | else 515 | highlight! link MistflyDiagnosticWarning StatusLine 516 | endif 517 | if hlexists('DiagnosticInfo') 518 | call s:SynthesizeHighlight('MistflyDiagnosticInformation', 'DiagnosticInfo', v:false) 519 | elseif hlexists('ALEInfoSign') 520 | call s:SynthesizeHighlight('MistflyDiagnosticInformation', 'ALEInfoSign', v:false) 521 | elseif hlexists('CocInfoSign') 522 | call s:SynthesizeHighlight('MistflyDiagnosticInformation', 'CocInfoSign', v:false) 523 | else 524 | highlight! link MistflyDiagnosticInformation StatusLine 525 | endif 526 | endfunction 527 | 528 | function! s:SynthesizeModeHighlight(target, background, foreground) abort 529 | let l:mode_bg = synIDattr(synIDtrans(hlID(a:background)), 'fg', 'gui') 530 | let l:mode_fg = synIDattr(synIDtrans(hlID(a:foreground)), 'fg', 'gui') 531 | 532 | if len(l:mode_bg) > 0 && len(l:mode_fg) > 0 533 | exec 'highlight ' . a:target . ' guibg=' . l:mode_bg . ' guifg=' . l:mode_fg 534 | else 535 | " Fallback to statusline highlighting. 536 | exec 'highlight! link ' . a:target . ' StatusLine' 537 | endif 538 | endfunction 539 | 540 | function! s:SynthesizeHighlight(target, source, reverse) abort 541 | if a:reverse 542 | let l:source_fg = synIDattr(synIDtrans(hlID(a:source)), 'bg', 'gui') 543 | else 544 | let l:source_fg = synIDattr(synIDtrans(hlID(a:source)), 'fg', 'gui') 545 | endif 546 | 547 | if len(s:statusline_bg) > 0 && len(l:source_fg) > 0 548 | exec 'highlight ' . a:target . ' guibg=' . s:statusline_bg . ' guifg=' . l:source_fg 549 | else 550 | " Fallback to statusline highlighting. 551 | exec 'highlight! link ' . a:target . ' StatusLine' 552 | endif 553 | endfunction 554 | 555 | "=========================================================== 556 | " Git 557 | "=========================================================== 558 | 559 | " Detect the branch name using an old-school system call. This function will 560 | " only be called upon BufEnter, BufWrite and FocusGained events to avoid 561 | " needlessly invoking that system call every time the statusline is redrawn. 562 | function! mistfly#DetectBranchName() abort 563 | if !g:mistflyWithGitBranch || bufname('%') == '' 564 | " Don't calculate the branch name if it isn't wanted or the buffer is 565 | " empty. 566 | let b:git_branch_name = '' 567 | return 568 | endif 569 | 570 | if exists('g:loaded_fugitive') 571 | " Fugitive is available, it will provide us the current branch name. 572 | return 573 | endif 574 | 575 | " Use fallback Git branch name detection. 576 | let b:git_branch_name = trim(system("git branch --show-current 2>/dev/null")) 577 | endfunction 578 | -------------------------------------------------------------------------------- /doc/mistfly.txt: -------------------------------------------------------------------------------- 1 | *mistfly* A simple, fast and informative statusline for Vim 2 | 3 | OPTIONS *mistfly-options* 4 | 5 | Default option values: 6 | > 7 | let g:mistflySeparatorSymbol = '⎪' 8 | let g:mistflyProgressSymbol = '↓' 9 | let g:mistflyActiveTabSymbol = '▪' 10 | let g:mistflyGitBranchSymbol = '' 11 | let g:mistflyErrorSymbol = 'E' 12 | let g:mistflyWarningSymbol = 'W' 13 | let g:mistflyInformationSymbol = 'I' 14 | let g:mistflyEllipsisSymbol = '…' 15 | let g:mistflyTabLine = v:false 16 | let g:mistflyWithFileIcon = v:true 17 | let g:mistflyWithGitBranch = v:true 18 | let g:mistflyWithGitStatus = v:true 19 | let g:mistflyWithDiagnosticStatus = v:true 20 | let g:mistflyWithSessionStatus = v:true 21 | let g:mistflyWithSearchCount = v:false 22 | let g:mistflyWithSpellStatus = v:false 23 | let g:mistflyWithIndentStatus = v:false 24 | < 25 | ------------------------------------------------------------------------------ 26 | mistflySeparatorSymbol~ *g:mistflySeparatorSymbol* 27 | 28 | The `mistflySeparatorSymbol` option specifies which character symbol to use 29 | for segment separators in the `statusline`. 30 | 31 | By default, the `⎪` character (Unicode `U+23AA`) will be displayed. 32 | 33 | To specify your own separator symbol please add the following to your 34 | initialization file: 35 | > 36 | " Vimscript initialization file 37 | let g:mistflySeparatorSymbol = '<>' 38 | 39 | -- Lua initialization file 40 | vim.g.mistflySeparatorSymbol = '<>' 41 | < 42 | ------------------------------------------------------------------------------ 43 | mistflyProgressSymbol~ *g:mistflyProgressSymbol* 44 | 45 | The `mistflyProgressSymbol` option specifies which character symbol to use to 46 | indicate location-as-percentage in the `statusline`. 47 | 48 | By default, the `↓` character (Unicode `U+2193`) will be displayed. 49 | 50 | To specify your own progress symbol, or no symbol at all, please add the 51 | following to your initialization file: 52 | > 53 | " Vimscript initialization file 54 | let g:mistflyProgressSymbol = '<>' 55 | 56 | -- Lua initialization file 57 | vim.g.mistflyProgressSymbol = '<>' 58 | < 59 | ------------------------------------------------------------------------------ 60 | mistflyActiveTabSymbol~ *g:mistflyActiveTabSymbol* 61 | 62 | The `mistflyActiveTabSymbol` option specifies which character symbol to use to 63 | signify the active tab in the `tabline`. 64 | 65 | By default, the `▪` character (Unicode `U+25AA`) will be displayed. 66 | 67 | To specify your own active tab symbol please add the following to your 68 | initialization file: 69 | > 70 | " Vimscript initialization file 71 | let g:mistflyActiveTabSymbol = '<>' 72 | 73 | -- Lua initialization file 74 | vim.g.mistflyActiveTabSymbol = '<>' 75 | < 76 | ------------------------------------------------------------------------------ 77 | mistflyGitBranchSymbol~ *g:mistflyGitBranchSymbol* 78 | 79 | The `mistflyGitBranchSymbol` option specifies which character symbol to use 80 | when displaying Git branch details. 81 | 82 | By default, the `` character (Powerline `U+E0A0`) will be displayed. Many 83 | modern monospace fonts will contain that character. 84 | 85 | To specify your own Git branch symbol, or no symbol at all, please add the 86 | following to your initialization file: 87 | > 88 | " Vimscript initialization file 89 | let g:mistflyGitBranchSymbol = '<>' 90 | 91 | -- Lua initialization file 92 | vim.g.mistflyGitBranchSymbol = '<>' 93 | < 94 | ------------------------------------------------------------------------------ 95 | mistflyErrorSymbol~ *g:mistflyErrorSymbol* 96 | 97 | The `mistflyErrorSymbol` option specifies which character symbol to use when 98 | displaying diagnostic errors. 99 | 100 | By default, the `E` character will be displayed. 101 | 102 | To specify your own error symbol please add the following to your 103 | initialization file: 104 | > 105 | " Vimscript initialization file 106 | let g:mistflyErrorSymbol = '<>' 107 | 108 | -- Lua initialization file 109 | vim.g.mistflyErrorSymbol = '<>' 110 | < 111 | ------------------------------------------------------------------------------ 112 | mistflyWarningSymbol~ *g:mistflyWarningSymbol* 113 | 114 | The `mistflyWarningSymbol` option specifies which character symbol to use when 115 | displaying diagnostic warnings. 116 | 117 | By default, the `W` character will be displayed. 118 | 119 | To specify your own warning symbol please add the following to your 120 | initialization file: 121 | > 122 | " Vimscript initialization file 123 | let g:mistflyWarningSymbol = '<>' 124 | 125 | -- Lua initialization file 126 | vim.g.mistflyWarningSymbol = '<>' 127 | < 128 | ------------------------------------------------------------------------------ 129 | mistflyInformationSymbol~ *g:mistflyInformationSymbol* 130 | 131 | The `mistflyInformationSymbol` option specifies which character symbol to use 132 | when displaying diagnostic information. 133 | 134 | By default, the `I` character will be displayed. 135 | 136 | To specify your own information symbol please add the following to your 137 | initialization file: 138 | > 139 | " Vimscript initialization file 140 | let g:mistflyInformationSymbol = '<>' 141 | 142 | -- Lua initialization file 143 | vim.g.mistflyInformationSymbol = '<>' 144 | < 145 | ------------------------------------------------------------------------------ 146 | mistflyEllipsisSymbol~ *g:mistflyEllipsisSymbol* 147 | 148 | The `mistflyEllipsisSymbol` option specifies which character symbol to use when 149 | indicating truncation, for example, deeply nested path truncation. 150 | 151 | By default, the `…` character will be displayed. 152 | 153 | To specify your own ellipsis symbol please add the following to your 154 | initialization file: 155 | > 156 | " Vimscript initialization file 157 | let g:mistflyEllipsisSymbol = '<>' 158 | 159 | -- Lua initialization file 160 | vim.g.mistflyEllipsisSymbol = '<>' 161 | < 162 | ------------------------------------------------------------------------------ 163 | mistflyTabLine~ *g:mistflyTabLine* 164 | 165 | The `mistflyTabLine` option specifies whether to let this plugin manage the 166 | `tabline` in addition to the `statusline`. 167 | 168 | By default, `tabline` management will not be undertaken. 169 | 170 | If enabled, `mistfly` will render a simple numbered, and clickable, 171 | window-space layout in the `tabline`; note, no buffers will be displayed in 172 | the `tabline` since there are many plugins that already provide that 173 | capability. 174 | 175 | To enable `tabline` support please add the following to your initialization 176 | file: 177 | > 178 | " Vimscript initialization file 179 | let g:mistflyTabLine = v:true 180 | 181 | -- Lua initialization file 182 | vim.g.mistflyTabLine = true 183 | < 184 | ------------------------------------------------------------------------------ 185 | mistflyWithFileIcon~ *g:mistflyWithFileIcon* 186 | 187 | The `mistflyWithFileIcon` option specifies whether a filetype icon, from a 188 | Nerd Font, will be displayed prior to the filename in the `statusline`. 189 | 190 | Note, a Nerd Font (https://www.nerdfonts.com) must be active and the 191 | vim-devicons (https://github.com/ryanoasis/vim-devicons) or nvim-web-devicons 192 | (https://github.com/kyazdani42/nvim-web-devicons) plugin must also be 193 | installed and active. 194 | 195 | By default, a filetype icon will be displayed if possible. 196 | 197 | To disable the display of a filetype icon please add the following to your 198 | initialization file: 199 | > 200 | " Vimscript initialization file 201 | let g:mistflyWithFileIcon = v:false 202 | 203 | -- lua initialization file 204 | vim.g.mistflyWithFileIcon = false 205 | < 206 | ------------------------------------------------------------------------------ 207 | mistflyWithGitBranch~ *g:mistflyWithGitBranch* 208 | 209 | The `mistflyWithGitBranch` option specifies whether to display Git branch 210 | details in the `statusline`. 211 | 212 | By default, Git branches will be displayed in the `statusline`. 213 | 214 | To disable the display of Git branches in the `statusline` please add the 215 | following to your initialization file: 216 | > 217 | " Vimscript initialization file 218 | let g:mistflyWithGitBranch = v:false 219 | 220 | -- Lua initialization file 221 | vim.g.mistflyWithGitBranch = false 222 | < 223 | ------------------------------------------------------------------------------ 224 | mistflyWithGitStatus~ *g:mistflyWithGitStatus* 225 | 226 | The `mistflyWithGitStatus` option specifies whether to display the Git status 227 | of the current buffer in the `statusline`. 228 | 229 | The Gitsigns (https://github.com/lewis6991/gitsigns.nvim), GitGutter 230 | (https://github.com/airblade/vim-gitgutter) and Signify 231 | (https://github.com/mhinz/vim-signify) plugins are supported. 232 | 233 | By default, the Git status will be displayed if one of the above plugins is 234 | loaded. 235 | 236 | To disable the display of Git status in the `statusline` please add the 237 | following to your initialization file: 238 | > 239 | " Vimscript initialization file 240 | let g:mistflyWithGitStatus = v:false 241 | 242 | -- Lua initialization file 243 | vim.g.mistflyWithGitStatus = false 244 | < 245 | ------------------------------------------------------------------------------ 246 | mistflyWithDiagnosticStatus~ *g:mistflyWithDiagnosticStatus* 247 | 248 | The `mistflyWithDiagnosticStatus` option specifies whether to indicate the 249 | presence of the diagnostics in the current buffer. 250 | 251 | ALE (https://github.com/dense-analysis/ale) and Coc 252 | (https://github.com/neoclide/coc.nvim) are supported. 253 | 254 | By default, diagnostics will be displayed if one of the above plugins is 255 | loaded. 256 | 257 | If diagnostic display is not wanted then please add the following to your 258 | initialization file: 259 | > 260 | " Vimscript initialization file 261 | let g:mistflyWithDiagnosticStatus = v:false 262 | 263 | -- Lua initialization file 264 | vim.g.mistflyWithDiagnosticStatus = false 265 | < 266 | ------------------------------------------------------------------------------ 267 | mistflyWithSessionStatus~ *g:mistflyWithSessionStatus* 268 | 269 | The `mistflyWithSessionStatus` option specifies whether to display Obsession 270 | (https://github.com/tpope/vim-obsession) session details in the `statusline`. 271 | 272 | By default, session details will be displayed if the plugin is loaded. 273 | 274 | To disable the display of session details in the `statusline` please add the 275 | following to your initialization file: 276 | > 277 | " Vimscript initialization file 278 | let g:mistflyWithSessionStatus = v:false 279 | 280 | -- Lua initialization file 281 | vim.g.mistflyWithSessionStatus = false 282 | < 283 | ------------------------------------------------------------------------------ 284 | mistflyWithSearchCount~ *g:mistflyWithSearchCount* 285 | 286 | The `mistflyWithSearchCount` option specifies whether to display the search 287 | count in the `statusline`. 288 | 289 | By default, search count will not be displayed. 290 | 291 | To enable the display of the search count in the `statusline` please add the 292 | following to your initialization file: 293 | > 294 | " Vimscript initialization file 295 | let g:mistflyWithSearchCount = v:true 296 | 297 | -- Lua initialization file 298 | vim.g.mistflyWithSearchCount = true 299 | < 300 | 301 | Note, the search count is only displayed when the `hlsearch` option is set and 302 | the search count result is not zero. 303 | ------------------------------------------------------------------------------ 304 | mistflyWithSpellStatus~ *g:mistflyWithSpellStatus* 305 | 306 | The `mistflyWithSpellStatus` option specifies whether to display the spell 307 | status in the `statusline`. 308 | 309 | By default, spell status will not be displayed. 310 | 311 | To enable spell status in the `statusline` please add the following to your 312 | initialization file: 313 | > 314 | " Vimscript initialization file 315 | let g:mistflyWithSpellStatus = v:true 316 | 317 | -- Lua initialization file 318 | vim.g.mistflyWithSpellStatus = true 319 | < 320 | ------------------------------------------------------------------------------ 321 | mistflyWithIndentStatus~ *g:mistflyWithIndentStatus* 322 | 323 | The `mistflyWithIndentStatus` option specifies whether to display the 324 | indentation status as the last component in the `statusline`. 325 | 326 | By default, indentation status will not be displayed. 327 | 328 | Note, if the `expandtab` option is set, for the current buffer, then tab stop 329 | will be displayed, for example `Tab:4` (tab equals four spaces); if on the 330 | other hand `noexpandtab` option is set then shift width will be displayed 331 | instead, for example `Spc:2` ('spc' short for 'space'). 332 | 333 | To enable indentation status please add the following to your initialization 334 | file: 335 | > 336 | " Vimscript initialization file 337 | let g:mistflyWithIndentStatus = v:true 338 | 339 | -- Lua initialization file 340 | vim.g.mistflyWithIndentStatus = true 341 | < 342 | 343 | vim:tw=78:ts=8:noet:ft=help:norl: 344 | -------------------------------------------------------------------------------- /plugin/mistfly-statusline.vim: -------------------------------------------------------------------------------- 1 | " A simple Vim / Neovim statusline. 2 | " 3 | " URL: github.com/bluz71/vim-mistfly-statusline 4 | " License: MIT (https://opensource.org/licenses/MIT) 5 | 6 | if has('nvim') 7 | lua vim.api.nvim_echo({ 8 | \ { "vim-mistfly-statusline does not support Neovim.\n", "WarningMsg" }, 9 | \ { "Please use pure-Lua nvim-linefly (https://github.com/bluz71/nvim-linefly) instead.\n", "Normal"} }, 10 | \ false, {}) 11 | finish 12 | endif 13 | 14 | if exists('g:loaded_mistfly_statusline') 15 | finish 16 | endif 17 | let g:loaded_mistfly_statusline = 1 18 | 19 | " Options. 20 | let g:mistflySeparatorSymbol = get(g:, 'mistflySeparatorSymbol', "⎪") 21 | let g:mistflyProgressSymbol = get(g:, 'mistflyProgressSymbol', "↓") 22 | let g:mistflyActiveTabSymbol = get(g:, 'mistflyActiveTabSymbol', "▪") 23 | let g:mistflyGitBranchSymbol = get(g:, 'mistflyGitBranchSymbol', "") 24 | let g:mistflyErrorSymbol = get(g:, 'mistflyErrorSymbol', 'E') 25 | let g:mistflyWarningSymbol = get(g:, 'mistflyWarningSymbol', 'W') 26 | let g:mistflyInformationSymbol = get(g:, 'mistflyInformationSymbol', 'I') 27 | let g:mistflyEllipsisSymbol = get(g:, 'mistflyEllipsisSymbol', '…') 28 | let g:mistflyTabLine = get(g:, 'mistflyTabLine', v:false) 29 | let g:mistflyWithFileIcon = get(g:, 'mistflyWithFileIcon', v:true) 30 | let g:mistflyWithGitBranch = get(g:, 'mistflyWithGitBranch', v:true) 31 | let g:mistflyWithGitStatus = get(g:, 'mistflyWithGitStatus', v:true) 32 | let g:mistflyWithDiagnosticStatus = get(g:, 'mistflyWithDiagnosticStatus', v:true) 33 | let g:mistflyWithSessionStatus = get(g:, 'mistflyWithSessionStatus', v:true) 34 | let g:mistflyWithSearchCount = get(g:, 'mistflyWithSearchCount', v:false) 35 | let g:mistflyWithSpellStatus = get(g:, 'mistflyWithSpellStatus', v:false) 36 | let g:mistflyWithIndentStatus = get(g:, 'mistflyWithIndentStatus', v:false) 37 | 38 | augroup mistflyStatuslineEvents 39 | autocmd! 40 | autocmd VimEnter,ColorScheme * call mistfly#GenerateHighlightGroups() 41 | autocmd VimEnter * call mistfly#UpdateInactiveWindows() 42 | autocmd VimEnter * call mistfly#TabLine() 43 | autocmd WinEnter,BufWinEnter * call mistfly#StatusLine(v:true) 44 | autocmd WinLeave * call mistfly#StatusLine(v:false) 45 | autocmd BufEnter,BufWrite,FocusGained * call mistfly#DetectBranchName() 46 | augroup END 47 | --------------------------------------------------------------------------------