1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-03-23 17:49:57 +08:00

refactor(bundle): update bundle indent-blankline.nvim

0f8df7e43f
close https://github.com/SpaceVim/SpaceVim/issues/4551
This commit is contained in:
wsdjeg 2022-01-05 08:47:47 +08:00
parent da2f51ecb9
commit 76d9a53aa8
10 changed files with 1203 additions and 396 deletions

View File

@ -0,0 +1,22 @@
name: Pull request check
on:
pull_request:
jobs:
format:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: JohnnyMorganz/stylua-action@1.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
args: --check .
block-fixup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Block Fixup Commit Merge
uses: 13rac1/block-fixup-merge-action@v2.0.0

View File

@ -9,13 +9,6 @@ features so it will not work in Vim.
There is a legacy version of the plugin that supports Neovim 0.4 under the There is a legacy version of the plugin that supports Neovim 0.4 under the
branch `version-1` branch `version-1`
## Settings
A lot of [Yggdroot/indentLine](https://github.com/Yggdroot/indentLine) options
should work out of the box.
Please see `:help indent_blankline.txt`for more details.
## Install ## Install
Use your favourite plugin manager to install. Use your favourite plugin manager to install.
@ -44,27 +37,123 @@ Plug 'lukas-reineke/indent-blankline.nvim'
call plug#end() call plug#end()
``` ```
## Setup
To configure indent-blankline, either run the setup function, or set variables manually.
The setup function has a single table as argument, keys of the table match the `:help indent-blankline-variables` without the `indent_blankline_` part.
```lua
require("indent_blankline").setup {
-- for example, context is off by default, use this to turn it on
show_current_context = true,
show_current_context_start = true,
}
```
Please see `:help indent_blankline.txt`for more details and all possible values.
A lot of [Yggdroot/indentLine](https://github.com/Yggdroot/indentLine) options should work out of the box.
## Screenshots ## Screenshots
#### Default settings All screenshots use [my custom onedark color scheme](https://github.com/lukas-reineke/onedark.nvim).
### Simple
```lua
vim.opt.list = true
vim.opt.listchars:append("eol:↴")
require("indent_blankline").setup {
show_end_of_line = true,
}
```
<img width="900" src="https://i.imgur.com/3gRG5qI.png" alt="Screenshot" /> <img width="900" src="https://i.imgur.com/3gRG5qI.png" alt="Screenshot" />
#### With custom `listchars` and `g:indent_blankline_space_char` #### With custom `listchars` and `g:indent_blankline_space_char_blankline`
```lua
vim.opt.list = true
vim.opt.listchars:append("space:⋅")
vim.opt.listchars:append("eol:↴")
require("indent_blankline").setup {
show_end_of_line = true,
space_char_blankline = " ",
}
```
<img width="900" src="https://i.imgur.com/VxCThMu.png" alt="Screenshot" /> <img width="900" src="https://i.imgur.com/VxCThMu.png" alt="Screenshot" />
#### With custom `g:indent_blankline_char_highlight_list` #### With custom `g:indent_blankline_char_highlight_list`
```lua
vim.opt.termguicolors = true
vim.cmd [[highlight IndentBlanklineIndent1 guifg=#E06C75 gui=nocombine]]
vim.cmd [[highlight IndentBlanklineIndent2 guifg=#E5C07B gui=nocombine]]
vim.cmd [[highlight IndentBlanklineIndent3 guifg=#98C379 gui=nocombine]]
vim.cmd [[highlight IndentBlanklineIndent4 guifg=#56B6C2 gui=nocombine]]
vim.cmd [[highlight IndentBlanklineIndent5 guifg=#61AFEF gui=nocombine]]
vim.cmd [[highlight IndentBlanklineIndent6 guifg=#C678DD gui=nocombine]]
vim.opt.list = true
vim.opt.listchars:append("space:⋅")
vim.opt.listchars:append("eol:↴")
require("indent_blankline").setup {
space_char_blankline = " ",
char_highlight_list = {
"IndentBlanklineIndent1",
"IndentBlanklineIndent2",
"IndentBlanklineIndent3",
"IndentBlanklineIndent4",
"IndentBlanklineIndent5",
"IndentBlanklineIndent6",
},
}
```
<img width="900" src="https://i.imgur.com/E3B0PUb.png" alt="Screenshot" /> <img width="900" src="https://i.imgur.com/E3B0PUb.png" alt="Screenshot" />
#### With custom background highlight #### With custom background highlight
```lua
vim.opt.termguicolors = true
vim.cmd [[highlight IndentBlanklineIndent1 guibg=#1f1f1f gui=nocombine]]
vim.cmd [[highlight IndentBlanklineIndent2 guibg=#1a1a1a gui=nocombine]]
require("indent_blankline").setup {
char = "",
char_highlight_list = {
"IndentBlanklineIndent1",
"IndentBlanklineIndent2",
},
space_char_highlight_list = {
"IndentBlanklineIndent1",
"IndentBlanklineIndent2",
},
show_trailing_blankline_indent = false,
}
```
<img width="900" src="https://i.imgur.com/DukMZGk.png" alt="Screenshot" /> <img width="900" src="https://i.imgur.com/DukMZGk.png" alt="Screenshot" />
#### With context indent highlighted by treesitter #### With context indent highlighted by treesitter
<img width="900" src="https://i.imgur.com/mkyGPZZ.png" alt="Screenshot" /> ```lua
vim.opt.list = true
vim.opt.listchars:append("space:⋅")
vim.opt.listchars:append("eol:↴")
require("indent_blankline").setup {
space_char_blankline = " ",
show_current_context = true,
show_current_context_start = true,
}
```
<img width="900" src="https://user-images.githubusercontent.com/12900252/140518531-522aa67a-b377-498c-ad39-85113b2b56df.png" alt="Screenshot" />
## Thanks ## Thanks

View File

@ -1,7 +1,11 @@
function! indent_blankline#Refresh() function! indent_blankline#Refresh(...)
try try
lua require("indent_blankline").refresh() if a:0 > 0
call luaeval("require('indent_blankline').refresh(_A)", a:1)
else
lua require("indent_blankline").refresh()
end
catch /E12/ catch /E12/
return return
catch catch

View File

@ -1,11 +0,0 @@
function! indent_blankline#helper#GetListChar(key, fallback)
let l:list_chars = {}
for l:char in split(&listchars, ',')
let l:split = split(l:char, ':')
let l:list_chars[l:split[0]] = l:split[1]
endfor
return get(l:list_chars, a:key, a:fallback)
endfunction

View File

@ -2,17 +2,18 @@
Author: Lukas Reineke <lukas.reineke@protonmail.com> Author: Lukas Reineke <lukas.reineke@protonmail.com>
Version: 2.0.0 Version: 2.11.0
============================================================================== ==============================================================================
CONTENTS *indent-blankline* CONTENTS *indent-blankline*
1. Introduction |indent-blankline-introduction| 1. Introduction |indent-blankline-introduction|
2. Highlights |indent-blankline-highlights| 2. Highlights |indent-blankline-highlights|
3. Variables |indent-blankline-variables| 3. Setup |indent-blankline-setup|
4. Commands |indent-blankline-commands| 4. Variables |indent-blankline-variables|
5. Changelog |indent-blankline-changelog| 5. Commands |indent-blankline-commands|
6. License |indent-blankline-license| 6. Changelog |indent-blankline-changelog|
7. License |indent-blankline-license|
============================================================================== ==============================================================================
1. INTRODUCTION *indent-blankline-introduction* 1. INTRODUCTION *indent-blankline-introduction*
@ -27,11 +28,12 @@ There is a legacy version of the plugin that supports Neovim 0.4 under the
branch `version-1` branch `version-1`
============================================================================== ==============================================================================
3. HIGHLIGHTS *indent-blankline-highlights* 2. HIGHLIGHTS *indent-blankline-highlights*
To change the highlighting of either the indent character, or the whitespace To change the highlighting of either the indent character, or the whitespace
between indent characters, define or update these highlight groups. between indent characters, define or update these highlight groups.
------------------------------------------------------------------------------
IndentBlanklineChar *hl-IndentBlanklineChar* IndentBlanklineChar *hl-IndentBlanklineChar*
Highlight of indent character. Highlight of indent character.
@ -42,6 +44,7 @@ IndentBlanklineChar *hl-IndentBlanklineChar*
highlight IndentBlanklineChar guifg=#00FF00 gui=nocombine highlight IndentBlanklineChar guifg=#00FF00 gui=nocombine
------------------------------------------------------------------------------
IndentBlanklineSpaceChar *hl-IndentBlanklineSpaceChar* IndentBlanklineSpaceChar *hl-IndentBlanklineSpaceChar*
Highlight of space character. Highlight of space character.
@ -52,6 +55,7 @@ IndentBlanklineSpaceChar *hl-IndentBlanklineSpaceChar*
highlight IndentBlanklineSpaceChar guifg=#00FF00 gui=nocombine highlight IndentBlanklineSpaceChar guifg=#00FF00 gui=nocombine
------------------------------------------------------------------------------
IndentBlanklineSpaceCharBlankline *hl-IndentBlanklineSpaceCharBlankline* IndentBlanklineSpaceCharBlankline *hl-IndentBlanklineSpaceCharBlankline*
Highlight of space character on blank lines. Highlight of space character on blank lines.
@ -62,6 +66,7 @@ IndentBlanklineSpaceCharBlankline *hl-IndentBlanklineSpaceCharBlankline*
highlight IndentBlanklineSpaceCharBlankline guifg=#00FF00 gui=nocombine highlight IndentBlanklineSpaceCharBlankline guifg=#00FF00 gui=nocombine
------------------------------------------------------------------------------
IndentBlanklineContextChar *hl-IndentBlanklineContextChar* IndentBlanklineContextChar *hl-IndentBlanklineContextChar*
Highlight of indent character when base of current context. Highlight of indent character when base of current context.
@ -73,6 +78,22 @@ IndentBlanklineContextChar *hl-IndentBlanklineContextChar*
highlight IndentBlanklineContextChar guifg=#00FF00 gui=nocombine highlight IndentBlanklineContextChar guifg=#00FF00 gui=nocombine
------------------------------------------------------------------------------
IndentBlanklineContextStart *hl-IndentBlanklineContextStart*
Highlight of the first line of the current context.
Only used when |g:indent_blankline_show_current_context_start| is active
Default: takes guifg color from 'Label' as guisp and adds underline ~
Note: You need to have set |gui-colors| for the default to work.
Example: >
highlight IndentBlanklineContextStart guisp=#00FF00 gui=underline
------------------------------------------------------------------------------
When defining the highlight group, it is important to set |nocombine| as a When defining the highlight group, it is important to set |nocombine| as a
gui option. This is to make sure the character does not inherit gui options gui option. This is to make sure the character does not inherit gui options
from the underlying text, like italic or bold. from the underlying text, like italic or bold.
@ -87,16 +108,42 @@ see:
|g:indent_blankline_space_char_blankline_highlight_list| |g:indent_blankline_space_char_blankline_highlight_list|
============================================================================== ==============================================================================
3. VARIABLES *indent-blankline-variables* 3. SETUP *indent-blankline-setup*
To configure indent-blankline, either run the setup function, or set variables
manually.
The setup function has a single table as argument, keys of the table match the
|indent-blankline-variables| without the `indent_blankline_` part.
Example: >
require("indent_blankline").setup {
-- for example, context is off by default, use this to turn it on
show_current_context = true,
show_current_context_start = true,
}
==============================================================================
4. VARIABLES *indent-blankline-variables*
All variables can be set gobally |g:var|, per tab |t:var|, or per buffer |b:var|
------------------------------------------------------------------------------
g:indent_blankline_char *g:indent_blankline_char* g:indent_blankline_char *g:indent_blankline_char*
Specifies the character to be used as indent line. Specifies the character to be used as indent line.
Not used if |g:indent_blankline_char_list| is not empty. Not used if |g:indent_blankline_char_list| is not empty.
When set explicitly to empty string (""), no indentation character is
displayed at all, even when |g:indent_blankline_char_list| is not empty.
This can be useful in combination with
|g:indent_blankline_space_char_highlight_list| to only rely on different
highlighting of different indentation levels without needing to show a
special character.
Also set by |g:indentLine_char| Also set by |g:indentLine_char|
Default: '|' ~ Default: '' ~
Example: > Example: >
@ -119,7 +166,7 @@ g:indent_blankline_char_list *g:indent_blankline_char_list*
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_char_highlight_list*g:indent_blankline_char_highlight_list* g:indent_blankline_char_highlight_list *g:indent_blankline_char_highlight_list*
Specifies the list of character highlights for each indentation level. Specifies the list of character highlights for each indentation level.
Ignored if the value is an empty list. Ignored if the value is an empty list.
@ -131,26 +178,12 @@ g:indent_blankline_char_highlight_list*g:indent_blankline_char_highlight_list*
let g:indent_blankline_char_highlight_list = ['Error', 'Function'] let g:indent_blankline_char_highlight_list = ['Error', 'Function']
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_space_char *g:indent_blankline_space_char* g:indent_blankline_space_char_blankline *g:indent_blankline_space_char_blankline*
Specifies the character to be used as the space value in between indent
lines.
Default: The listchars space value ~
Example: >
let g:indent_blankline_space_char = ' '
------------------------------------------------------------------------------
g:indent_blankline_space_char_blankline*g:indent_blankline_space_char_blankline*
Specifies the character to be used as the space value in between indent Specifies the character to be used as the space value in between indent
lines when the line is blank. lines when the line is blank.
Also set by |g:indent_blankline_space_char| Default: An empty space character ~
Default: The listchars space value ~
Example: > Example: >
@ -158,7 +191,7 @@ g:indent_blankline_space_char_blankline*g:indent_blankline_space_char_blankline*
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_space_char_highlight_list*g:indent_blankline_space_char_highlight_list* g:indent_blankline_space_char_highlight_list *g:indent_blankline_space_char_highlight_list*
Specifies the list of space character highlights for each indentation Specifies the list of space character highlights for each indentation
level. level.
@ -172,7 +205,7 @@ g:indent_blankline_space_char_highlight_list*g:indent_blankline_space_char_highl
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_space_char_blankline_highlight_list*g:indent_blankline_space_char_blankline_highlight_list* g:indent_blankline_space_char_blankline_highlight_list *g:indent_blankline_space_char_blankline_highlight_list*
Specifies the list of space character highlights for each indentation Specifies the list of space character highlights for each indentation
level when the line is empty. level when the line is empty.
@ -187,7 +220,6 @@ g:indent_blankline_space_char_blankline_highlight_list*g:indent_blankline_space_
let g:indent_blankline_space_char_blankline_highlight_list = ['Error', 'Function'] let g:indent_blankline_space_char_blankline_highlight_list = ['Error', 'Function']
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_use_treesitter *g:indent_blankline_use_treesitter* g:indent_blankline_use_treesitter *g:indent_blankline_use_treesitter*
Use treesitter to calculate indentation when possible. Use treesitter to calculate indentation when possible.
@ -213,7 +245,20 @@ g:indent_blankline_indent_level *g:indent_blankline_indent_level*
let g:indent_blankline_indent_level = 4 let g:indent_blankline_indent_level = 4
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_show_first_indent_level*g:indent_blankline_show_first_indent_level* g:indent_blankline_max_indent_increase *g:indent_blankline_max_indent_increase*
The maximum indent level increase from line to line.
Set this option to 1 to make aligned trailing multiline comments not
create indentation.
Default: g:indent_blankline_indent_level ~
Example: >
let g:indent_blankline_max_indent_increase = 1
------------------------------------------------------------------------------
g:indent_blankline_show_first_indent_level *g:indent_blankline_show_first_indent_level*
Displays indentation in the first column. Displays indentation in the first column.
@ -224,7 +269,7 @@ g:indent_blankline_show_first_indent_level*g:indent_blankline_show_first_indent_
let g:indent_blankline_show_first_indent_level = v:false let g:indent_blankline_show_first_indent_level = v:false
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_show_trailing_blankline_indent*g:indent_blankline_show_trailing_blankline_indent* g:indent_blankline_show_trailing_blankline_indent *g:indent_blankline_show_trailing_blankline_indent*
Displays a trailing indentation guide on blank lines, to match the Displays a trailing indentation guide on blank lines, to match the
indentation of surrounding code. indentation of surrounding code.
@ -266,10 +311,13 @@ g:indent_blankline_show_foldtext *g:indent_blankline_show_foldtext*
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_enabled *g:indent_blankline_enabled* g:indent_blankline_enabled *g:indent_blankline_enabled*
Turns this plugin on or off globally. Turns this plugin on or off.
Also set by |g:indentLine_enabled| Also set by |g:indentLine_enabled|
Note: the buffer version of this variable overwrites all other
enabled/disalbed checks.
Default: v:true ~ Default: v:true ~
Example: > Example: >
@ -277,17 +325,17 @@ g:indent_blankline_enabled *g:indent_blankline_enabled*
let g:indent_blankline_enabled = v:false let g:indent_blankline_enabled = v:false
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
b:indent_blankline_enabled *b:indent_blankline_enabled* g:indent_blankline_disable_with_nolist *g:indent_blankline_disable_with_nolist*
Turns this plugin on or off for the buffer. When true, automatically turns this plugin off when |nolist| is set.
When false, setting |nolist| will keep displaying indentation guides but
removes whitespace characters set by |listchars|.
Also set by |b:indentLine_enabled| Default: v:false ~
Default: v:true ~
Example: > Example: >
let b:indent_blankline_enabled = v:false let g:indent_blankline_disable_with_nolist = v:true
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_filetype *g:indent_blankline_filetype* g:indent_blankline_filetype *g:indent_blankline_filetype*
@ -363,7 +411,7 @@ g:indent_blankline_strict_tabs *g:indent_blankline_strict_tabs*
let g:indent_blankline_strict_tabs = v:true let g:indent_blankline_strict_tabs = v:true
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_show_current_context*g:indent_blankline_show_current_context* g:indent_blankline_show_current_context *g:indent_blankline_show_current_context*
When on, use treesitter to determine the current context. Then show the When on, use treesitter to determine the current context. Then show the
indent character in a different highlight. indent character in a different highlight.
@ -379,7 +427,68 @@ g:indent_blankline_show_current_context*g:indent_blankline_show_current_context*
let g:indent_blankline_show_current_context = v:true let g:indent_blankline_show_current_context = v:true
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_context_highlight_list*g:indent_blankline_context_highlight_list* g:indent_blankline_show_current_context_start *g:indent_blankline_show_current_context_start*
Applies the |hl-IndentBlanklineContextStart| highlight group to the first
line of the current context.
By default this will underline.
Note: You need to have set |gui-colors| and it depends on your terminal
emulator if this works as expected.
If you are using kitty and tmux, take a look at this article to
make it work
http://evantravers.com/articles/2021/02/05/curly-underlines-in-kitty-tmux-neovim/
Default: v:false ~
Example: >
let g:indent_blankline_show_current_context_start = v:true
------------------------------------------------------------------------------
g:indent_blankline_show_current_context_start_on_current_line *g:indent_blankline_show_current_context_start_on_current_line*
Shows |g:indent_blankline_show_current_context_start| even when the cursor
is on the same line
Default: v:true ~
Example: >
let g:indent_blankline_show_current_context_start_on_current_line = v:false
------------------------------------------------------------------------------
g:indent_blankline_context_char *g:indent_blankline_context_char*
Specifies the character to be used for the current context indent line.
Not used if |g:indent_blankline_context_char_list| is not empty.
Useful to have a greater distinction between the current context indent
line and others.
Also useful in combination with |g:indent_blankline_char| set to empty string
(""), as this allows only the current context indent line to be shown.
Default: g:indent_blankline_char ~
Example: >
let g:indent_blankline_context_char = '┃'
------------------------------------------------------------------------------
g:indent_blankline_context_char_list *g:indent_blankline_context_char_list*
Equivalent of |g:indent_blankline_char_list| for
|g:indent_blankline_context_char|.
Default: [] ~
Example: >
let g:indent_blankline_context_char_list = ['┃', '║', '╬', '█']
------------------------------------------------------------------------------
g:indent_blankline_context_highlight_list *g:indent_blankline_context_highlight_list*
Specifies the list of character highlights for the current context at Specifies the list of character highlights for the current context at
each indentation level. each indentation level.
@ -411,6 +520,22 @@ g:indent_blankline_context_patterns *g:indent_blankline_context_patterns*
let g:indent_blankline_context_patterns = ['^if'] let g:indent_blankline_context_patterns = ['^if']
------------------------------------------------------------------------------
g:indent_blankline_context_pattern_highlight *g:indent_blankline_context_pattern_highlight*
Specifies a map of patterns set in
|g:indent_blankline_context_patterns| to highlight groups.
When the current matching context pattern is in the map, the context
will be highlighted with the corresponding highlight group.
Only used when |g:indent_blankline_show_current_context| is active
Default: {} ~
Example: >
let g:indent_blankline_context_pattern_highlight = {'function': 'Function'}
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_viewport_buffer *g:indent_blankline_viewport_buffer* g:indent_blankline_viewport_buffer *g:indent_blankline_viewport_buffer*
@ -424,7 +549,7 @@ g:indent_blankline_viewport_buffer *g:indent_blankline_viewport_buffer*
let g:indent_blankline_viewport_buffer = 20 let g:indent_blankline_viewport_buffer = 20
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
g:indent_blankline_disable_warning_message*g:indent_blankline_disable_warning_message* g:indent_blankline_disable_warning_message *g:indent_blankline_disable_warning_message*
Turns deprecation warning messages off. Turns deprecation warning messages off.
@ -446,8 +571,9 @@ g:indent_blankline_debug *g:indent_blankline_debug*
let g:indent_blankline_debug = v:true let g:indent_blankline_debug = v:true
============================================================================== ==============================================================================
4. COMMANDS *indent-blankline-commands* 5. COMMANDS *indent-blankline-commands*
------------------------------------------------------------------------------
:IndentBlanklineRefresh[!] *IndentBlanklineRefresh* :IndentBlanklineRefresh[!] *IndentBlanklineRefresh*
Refreshes the indent guides for the current buffer. Refreshes the indent guides for the current buffer.
@ -457,19 +583,34 @@ g:indent_blankline_debug *g:indent_blankline_debug*
With bang (IndentBlanklineRefresh!) refreshes the indent guides globally. With bang (IndentBlanklineRefresh!) refreshes the indent guides globally.
By default it is run for: By default it is run for:
1. |VimEnter| * [bang] 1. |FileChangedShellPost| *
2. |FileChangedShellPost| * 2. |TextChanged| *
3. |TextChanged| * 3. |TextChangedI| *
4. |TextChangedI| * 4. |CompleteChanged| *
5. |WinScrolled| * 5. |BufWinEnter| *
6. |BufWinEnter| * 6. |Filetype| *
7. |Filetype| * 7. |OptionSet| shiftwidth,tabstop,expandtab
8. |OptionSet| shiftwidth,tabstop,expandtab
Example: > Example: >
autocmd User ALEFixPost IndentBlanklineRefresh autocmd User ALEFixPost IndentBlanklineRefresh
------------------------------------------------------------------------------
:IndentBlanklineRefreshScroll[!] *IndentBlanklineRefreshScroll*
Refreshes the indent guides for the current buffer. But tries to reuse as
indent guides that already exist. Only used if we are sure the buffer
content did not change.
With bang (IndentBlanklineRefresh!) refreshes the indent guides globally.
By default it is run for:
1. |WinScrolled| *
Example: >
autocmd WinScrolled * IndentBlanklineRefreshScroll
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
:IndentBlanklineEnable[!] *IndentBlanklineEnable* :IndentBlanklineEnable[!] *IndentBlanklineEnable*
@ -494,7 +635,139 @@ g:indent_blankline_debug *g:indent_blankline_debug*
With bang (IndentBlanklineToggle!) toggles globally With bang (IndentBlanklineToggle!) toggles globally
============================================================================== ==============================================================================
5. CHANGELOG *indent-blankline-changelog* 6. CHANGELOG *indent-blankline-changelog*
2.11.0
* Add |g:indent_blankline_show_current_context_start_on_current_line|
2.10.6
* Update example setup in the readme and docs
2.10.5
* Run refresh without autocmds
* Check that the window is valid before returning to it after refresh
2.10.4
* Remove `nocombine` from |hl-IndentBlanklineContextStart| again..
2.10.3
* Fix context start highlight column for files indent with tab
* Fix context start highlight on lines with no indent
2.10.2
* Apply context start highlight after indentation
2.10.1
* Remove `nocombine` from |hl-IndentBlanklineContextStart|
2.10.0
* Add |g:indent_blankline_show_current_context_start|
* Add |hl-IndentBlanklineContextStart|
2.9.3
* Fix indent cache for scrolling
* Fix documentation tags
2.9.2
* Fix refresh argument types for 0.5
2.9.1
* Fix horizontal scroll update
2.9.0
* Add |g:indent_blankline_context_char|
* Add |g:indent_blankline_context_char_list|
2.8.0
* Add |IndentBlanklineRefreshScroll|
2.7.0
* Add support for 0 width |g:indent_blankline_char|
2.6.4
* Remove memo from `find_indent`, it made the performance worse
2.6.3
* Fix issue when calling setup more than once
2.6.2
* Memoize the find indent function
* Run init on VimEnter to initialize indents in all open windows
* Run init on plugin load to work with lazy loading
2.6.1
* Wait until buffer is loaded before doing anything
2.6.0
* Add |g:indent_blankline_context_pattern_highlight|
2.5.7
* Update the README to not overwrite all listchars
* Handle listchars without a tab character
2.5.6
* Fix trailing space for blanklines
2.5.5
* Fix typo in readme
* Fix initialization of |g:indent_blankline_space_char_blankline_highlight_list|
* Refactor `find_indent`
2.5.4
* Fix wrong indent for empty lines with only extra
2.5.3
* Remove old reference to `indent_blankline_space_char`
2.5.2
* Fix background highlight example
2.5.1
* Only load treesitter libs if needed
2.5.0
* Add |g:indent_blankline_max_indent_increase|
2.4.0
* Remove `indent_blankline_respect_list`
* Add |g:indent_blankline_disable_with_nolist|
2.3.0
* Add |g:indent_blankline_respect_list| option
2.2.2
* Remove old vimscript code
2.2.1
* Fix first indent on a line with whitespace less than the current shift
width
2.2.0
* Correctly display listchars under the indent guides
Huge thanks to @Daxtorim
* Remove options:
`indent_blankline_space_char` - listchars is used to get the correct space
character
2.1.4
* Fix race condition in `is_indent_blankline_enabled`
2.1.3
* Refresh on |CompleteChanged|
2.1.2
* Fix lazy loading
2.1.1
* Fix bug were setup function is not run
2.1.0
* Added setup function
* Added buffer variables
* Fix horizontal scroll
2.0.1
* Fix typo in docs
2.0.0 2.0.0
* Complete lua rewrite * Complete lua rewrite
@ -571,7 +844,7 @@ g:indent_blankline_debug *g:indent_blankline_debug*
* First release * First release
============================================================================== ==============================================================================
6. LICENSE *indent-blankline-license* 7. LICENSE *indent-blankline-license*
The MIT Licence The MIT Licence
http://www.opensource.org/licenses/mit-license.php http://www.opensource.org/licenses/mit-license.php

View File

@ -1,12 +1,15 @@
local M = {} local M = {}
M.refresh = function(bang) M.refresh = function(bang, scroll)
scroll = scroll or false
if bang then if bang then
local win = vim.api.nvim_get_current_win() local win = vim.api.nvim_get_current_win()
vim.cmd [[windo call indent_blankline#Refresh()]] vim.cmd(string.format([[noautocmd windo call indent_blankline#Refresh(v:%s)]], tostring(scroll)))
vim.api.nvim_set_current_win(win) if vim.api.nvim_win_is_valid(win) then
vim.api.nvim_set_current_win(win)
end
else else
vim.cmd [[call indent_blankline#Refresh()]] vim.cmd(string.format([[call indent_blankline#Refresh(v:%s)]], tostring(scroll)))
end end
end end
@ -14,7 +17,7 @@ M.enable = function(bang)
if bang then if bang then
vim.g.indent_blankline_enabled = true vim.g.indent_blankline_enabled = true
local win = vim.api.nvim_get_current_win() local win = vim.api.nvim_get_current_win()
vim.cmd [[windo call indent_blankline#Refresh()]] vim.cmd [[noautocmd windo call indent_blankline#Refresh()]]
vim.api.nvim_set_current_win(win) vim.api.nvim_set_current_win(win)
else else
vim.b.indent_blankline_enabled = true vim.b.indent_blankline_enabled = true

View File

@ -1,5 +1,3 @@
local ts_status, ts_query = pcall(require, "nvim-treesitter.query")
local ts_status, ts_indent = pcall(require, "nvim-treesitter.indent")
local utils = require "indent_blankline/utils" local utils = require "indent_blankline/utils"
local M = {} local M = {}
@ -8,149 +6,417 @@ local space_char_highlight = "IndentBlanklineSpaceChar"
local space_char_blankline_highlight = "IndentBlanklineSpaceCharBlankline" local space_char_blankline_highlight = "IndentBlanklineSpaceCharBlankline"
local context_highlight = "IndentBlanklineContextChar" local context_highlight = "IndentBlanklineContextChar"
M.setup = function() M.init = function()
vim.g.indent_blankline_namespace = vim.api.nvim_create_namespace("indent_blankline") if not vim.g.indent_blankline_namespace then
vim.g.indent_blankline_namespace = vim.api.nvim_create_namespace "indent_blankline"
end
utils.reset_highlights() utils.reset_highlights()
require("indent_blankline.commands").refresh(true)
end end
local refresh = function() M.setup = function(options)
if options == nil then
options = {}
end
local o = utils.first_not_nil
vim.g.indent_blankline_char = o(options.char, vim.g.indent_blankline_char, vim.g.indentLine_char, "")
vim.g.indent_blankline_char_list = o(
options.char_list,
vim.g.indent_blankline_char_list,
vim.g.indentLine_char_list
)
vim.g.indent_blankline_context_char = o(
options.context_char,
vim.g.indent_blankline_context_char,
vim.g.indent_blankline_char
)
vim.g.indent_blankline_context_char_list = o(options.context_char_list, vim.g.indent_blankline_context_char_list)
vim.g.indent_blankline_char_highlight_list = o(
options.char_highlight_list,
vim.g.indent_blankline_char_highlight_list
)
vim.g.indent_blankline_space_char_highlight_list = o(
options.space_char_highlight_list,
vim.g.indent_blankline_space_char_highlight_list
)
vim.g.indent_blankline_space_char_blankline = o(
options.space_char_blankline,
vim.g.indent_blankline_space_char_blankline,
" "
)
vim.g.indent_blankline_space_char_blankline_highlight_list = o(
options.space_char_blankline_highlight_list,
vim.g.indent_blankline_space_char_blankline_highlight_list,
options.space_char_highlight_list,
vim.g.indent_blankline_space_char_highlight_list
)
vim.g.indent_blankline_indent_level = o(options.indent_level, vim.g.indent_blankline_indent_level, 20)
vim.g.indent_blankline_enabled = o(options.enabled, vim.g.indent_blankline_enabled, true)
vim.g.indent_blankline_disable_with_nolist = o(
options.disable_with_nolist,
vim.g.indent_blankline_disable_with_nolist,
false
)
vim.g.indent_blankline_filetype = o(options.filetype, vim.g.indent_blankline_filetype, vim.g.indentLine_fileType)
vim.g.indent_blankline_filetype_exclude = o(
options.filetype_exclude,
vim.g.indent_blankline_filetype_exclude,
vim.g.indentLine_fileTypeExclude
)
vim.g.indent_blankline_bufname_exclude = o(
options.bufname_exclude,
vim.g.indent_blankline_bufname_exclude,
vim.g.indentLine_bufNameExclude
)
vim.g.indent_blankline_buftype_exclude = o(
options.buftype_exclude,
vim.g.indent_blankline_buftype_exclude,
vim.g.indentLine_bufTypeExclude
)
vim.g.indent_blankline_viewport_buffer = o(options.viewport_buffer, vim.g.indent_blankline_viewport_buffer, 10)
vim.g.indent_blankline_use_treesitter = o(options.use_treesitter, vim.g.indent_blankline_use_treesitter, false)
vim.g.indent_blankline_max_indent_increase = o(
options.max_indent_increase,
vim.g.indent_blankline_max_indent_increase,
options.indent_level,
vim.g.indent_blankline_indent_level
)
vim.g.indent_blankline_show_first_indent_level = o(
options.show_first_indent_level,
vim.g.indent_blankline_show_first_indent_level,
true
)
vim.g.indent_blankline_show_trailing_blankline_indent = o(
options.show_trailing_blankline_indent,
vim.g.indent_blankline_show_trailing_blankline_indent,
true
)
vim.g.indent_blankline_show_end_of_line = o(
options.show_end_of_line,
vim.g.indent_blankline_show_end_of_line,
false
)
vim.g.indent_blankline_show_foldtext = o(options.show_foldtext, vim.g.indent_blankline_show_foldtext, true)
vim.g.indent_blankline_show_current_context = o(
options.show_current_context,
vim.g.indent_blankline_show_current_context,
false
)
vim.g.indent_blankline_show_current_context_start = o(
options.show_current_context_start,
vim.g.indent_blankline_show_current_context_start,
false
)
vim.g.indent_blankline_show_current_context_start_on_current_line = o(
options.show_current_context_start_on_current_line,
vim.g.indent_blankline_show_current_context_start_on_current_line,
true
)
vim.g.indent_blankline_context_highlight_list = o(
options.context_highlight_list,
vim.g.indent_blankline_context_highlight_list
)
vim.g.indent_blankline_context_patterns = o(
options.context_patterns,
vim.g.indent_blankline_context_patterns,
{ "class", "function", "method" }
)
vim.g.indent_blankline_context_pattern_highlight = o(
options.context_pattern_highlight,
vim.g.indent_blankline_context_pattern_highlight
)
vim.g.indent_blankline_strict_tabs = o(options.strict_tabs, vim.g.indent_blankline_strict_tabs, false)
vim.g.indent_blankline_disable_warning_message = o(
options.disable_warning_message,
vim.g.indent_blankline_disable_warning_message,
false
)
vim.g.indent_blankline_debug = o(options.debug, vim.g.indent_blankline_debug, false)
if vim.g.indent_blankline_show_current_context then
vim.cmd [[
augroup IndentBlanklineContextAutogroup
autocmd!
autocmd CursorMoved * IndentBlanklineRefresh
augroup END
]]
end
vim.g.__indent_blankline_setup_completed = true
end
local refresh = function(scroll)
local v = utils.get_variable
local bufnr = vim.api.nvim_get_current_buf()
if not vim.api.nvim_buf_is_loaded(bufnr) then
return
end
if if
not utils.is_indent_blankline_enabled( not utils.is_indent_blankline_enabled(
vim.b.indent_blankline_enabled, vim.b.indent_blankline_enabled,
vim.g.indent_blankline_enabled, vim.g.indent_blankline_enabled,
v "indent_blankline_disable_with_nolist",
vim.opt.list:get(),
vim.bo.filetype, vim.bo.filetype,
vim.g.indent_blankline_filetype, v "indent_blankline_filetype" or {},
vim.g.indent_blankline_filetype_exclude, v "indent_blankline_filetype_exclude" or {},
vim.bo.buftype, vim.bo.buftype,
vim.g.indent_blankline_buftype_exclude, v "indent_blankline_buftype_exclude" or {},
vim.g.indent_blankline_bufname_exclude, v "indent_blankline_bufname_exclude" or {},
vim.fn["bufname"]("") vim.fn["bufname"] ""
) )
then then
if vim.b.__indent_blankline_active then
vim.schedule_wrap(utils.clear_buf_indent)(bufnr)
end
vim.b.__indent_blankline_active = false vim.b.__indent_blankline_active = false
return return
else else
vim.b.__indent_blankline_active = true vim.b.__indent_blankline_active = true
end end
local bufnr = vim.api.nvim_get_current_buf() local win_start = vim.fn.line "w0"
local offset = math.max(vim.fn.line("w0") - 1 - vim.g.indent_blankline_viewport_buffer, 0) local win_end = vim.fn.line "w$"
local range = local offset = math.max(win_start - 1 - v "indent_blankline_viewport_buffer", 0)
math.min(vim.fn.line("w$") + vim.g.indent_blankline_viewport_buffer, vim.api.nvim_buf_line_count(bufnr)) local win_view = vim.fn.winsaveview()
local left_offset = win_view.leftcol
local lnum = win_view.lnum
local left_offset_s = tostring(left_offset)
local range = math.min(win_end + v "indent_blankline_viewport_buffer", vim.api.nvim_buf_line_count(bufnr))
if not vim.b.__indent_blankline_ranges then
vim.b.__indent_blankline_ranges = {}
end
if scroll then
local updated_range
if vim.b.__indent_blankline_ranges[left_offset_s] then
local blankline_ranges = vim.b.__indent_blankline_ranges[left_offset_s]
local need_to_update = true
-- find a candidate that could contain the window
local idx_candidate = utils.binary_search_ranges(blankline_ranges, { win_start, win_end })
local candidate_start, candidate_end = unpack(blankline_ranges[idx_candidate])
-- check if the current window is contained or if a new range needs to be created
if candidate_start <= win_start then
if candidate_end >= win_end then
need_to_update = false
else
table.insert(blankline_ranges, idx_candidate + 1, { offset, range })
end
else
table.insert(blankline_ranges, idx_candidate, { offset, range })
end
if not need_to_update then
return
end
-- merge ranges and update the variable, strategies are: contains or extends
updated_range = utils.merge_ranges(blankline_ranges)
else
updated_range = { { offset, range } }
end
-- we can't assign directly to a table key, so we update the reference to the variable
local new_ranges = vim.b.__indent_blankline_ranges
new_ranges[left_offset_s] = updated_range
vim.b.__indent_blankline_ranges = new_ranges
else
vim.b.__indent_blankline_ranges = { [left_offset_s] = { { offset, range } } }
end
local lines = vim.api.nvim_buf_get_lines(bufnr, offset, range, false) local lines = vim.api.nvim_buf_get_lines(bufnr, offset, range, false)
local char = vim.g.indent_blankline_char local char = v "indent_blankline_char"
local char_list = vim.g.indent_blankline_char_list local char_list = v "indent_blankline_char_list" or {}
local char_highlight_list = vim.g.indent_blankline_char_highlight_list local context_char = v "indent_blankline_context_char"
local space_char_highlight_list = vim.g.indent_blankline_space_char_highlight_list local context_char_list = v "indent_blankline_context_char_list" or {}
local space_char_blankline_highlight_list = vim.g.indent_blankline_space_char_blankline_highlight_list local char_highlight_list = v "indent_blankline_char_highlight_list" or {}
local space_char = vim.g.indent_blankline_space_char local space_char_highlight_list = v "indent_blankline_space_char_highlight_list" or {}
local space_char_blankline = vim.g.indent_blankline_space_char_blankline local space_char_blankline_highlight_list = v "indent_blankline_space_char_blankline_highlight_list" or {}
local max_indent_level = vim.g.indent_blankline_indent_level local space_char_blankline = v "indent_blankline_space_char_blankline"
local list_chars = {}
local no_tab_character = false
-- No need to check for disable_with_nolist as this part would never be executed if "true" && nolist
if vim.opt.list:get() then
-- list is set, get listchars
local tab_characters
local space_character = vim.opt.listchars:get().space or " "
if vim.opt.listchars:get().tab then
-- tab characters can be any UTF-8 character, Lua 5.1 cannot handle this without external libraries
tab_characters = vim.fn.split(vim.opt.listchars:get().tab, "\\zs")
else
no_tab_character = true
tab_characters = { "^", "I" }
end
list_chars = {
space_char = space_character,
trail_char = vim.opt.listchars:get().trail or space_character,
lead_char = vim.opt.listchars:get().lead or space_character,
tab_char_start = tab_characters[1] or space_character,
tab_char_fill = tab_characters[2] or space_character,
tab_char_end = tab_characters[3],
eol_char = vim.opt.listchars:get().eol,
}
else
-- nolist is set, replace all listchars with empty space
list_chars = {
space_char = " ",
trail_char = " ",
lead_char = " ",
tab_char_start = " ",
tab_char_fill = " ",
tab_char_end = nil,
eol_char = nil,
}
end
local max_indent_level = v "indent_blankline_indent_level"
local max_indent_increase = v "indent_blankline_max_indent_increase"
local expandtab = vim.bo.expandtab local expandtab = vim.bo.expandtab
local use_ts_indent = vim.g.indent_blankline_use_treesitter and ts_status and ts_query.has_indents(vim.bo.filetype) local use_ts_indent = false
local first_indent = vim.g.indent_blankline_show_first_indent_level local ts_indent
local trail_indent = vim.g.indent_blankline_show_trailing_blankline_indent if v "indent_blankline_use_treesitter" then
local end_of_line = vim.g.indent_blankline_show_end_of_line local ts_query_status, ts_query = pcall(require, "nvim-treesitter.query")
local end_of_line_char = vim.fn["indent_blankline#helper#GetListChar"]("eol", "") local ts_indent_status
local strict_tabs = vim.g.indent_blankline_strict_tabs ts_indent_status, ts_indent = pcall(require, "nvim-treesitter.indent")
local foldtext = vim.g.indent_blankline_show_foldtext use_ts_indent = ts_query_status and ts_indent_status and ts_query.has_indents(vim.bo.filetype)
end
local first_indent = v "indent_blankline_show_first_indent_level"
local trail_indent = v "indent_blankline_show_trailing_blankline_indent"
local end_of_line = v "indent_blankline_show_end_of_line"
local strict_tabs = v "indent_blankline_strict_tabs"
local foldtext = v "indent_blankline_show_foldtext"
local tabs = vim.bo.shiftwidth == 0 or not expandtab local tabs = vim.bo.shiftwidth == 0 or not expandtab
local space = utils._if(tabs, vim.bo.tabstop, vim.bo.shiftwidth) local shiftwidth = utils._if(tabs, utils._if(no_tab_character, 2, vim.bo.tabstop), vim.bo.shiftwidth)
local context_highlight_list = vim.g.indent_blankline_context_highlight_list local context_highlight_list = v "indent_blankline_context_highlight_list" or {}
local context_status, context_start, context_end = false, 0, 0 local context_pattern_highlight = v "indent_blankline_context_pattern_highlight" or {}
if vim.g.indent_blankline_show_current_context then local context_status, context_start, context_end, context_pattern = false, 0, 0, nil
context_status, context_start, context_end = utils.get_current_context(vim.g.indent_blankline_context_patterns) local show_current_context_start = v "indent_blankline_show_current_context_start"
local show_current_context_start_on_current_line = v "indent_blankline_show_current_context_start_on_current_line"
if v "indent_blankline_show_current_context" then
context_status, context_start, context_end, context_pattern = utils.get_current_context(
v "indent_blankline_context_patterns"
)
end end
local get_virtual_text = function(indent, extra, blankline, context_active, context_indent) local get_virtual_text =
local virtual_text = {} function(indent, extra, blankline, context_active, context_indent, prev_indent, virtual_string)
for i = 1, math.min(math.max(indent, 0), max_indent_level) do local virtual_text = {}
local space_count = space local current_left_offset = left_offset
local context = context_active and context_indent == i local local_max_indent_level = math.min(max_indent_level, prev_indent + max_indent_increase)
if i ~= 1 or first_indent then for i = 1, math.min(math.max(indent, 0), local_max_indent_level) do
space_count = space_count - 1 local space_count = shiftwidth
table.insert( local context = context_active and context_indent == i
virtual_text, local show_indent_char = (i ~= 1 or first_indent) and char ~= ""
{ local show_context_indent_char = context and (i ~= 1 or first_indent) and context_char ~= ""
utils._if( local show_end_of_line_char = i == 1 and blankline and end_of_line and list_chars["eol_char"]
i == 1 and blankline and end_of_line and #end_of_line_char > 0, local show_indent_or_eol_char = show_indent_char or show_context_indent_char or show_end_of_line_char
end_of_line_char, if show_indent_or_eol_char then
space_count = space_count - 1
if current_left_offset > 0 then
current_left_offset = current_left_offset - 1
else
table.insert(virtual_text, {
utils._if( utils._if(
#char_list > 0, show_end_of_line_char,
utils.get_from_list(char_list, i - utils._if(not first_indent, 1, 0)), list_chars["eol_char"],
char utils._if(
) context,
), utils.get_from_list(
utils._if( context_char_list,
context, i - utils._if(not first_indent, 1, 0),
utils._if( context_char
#context_highlight_list > 0, ),
utils.get_from_list(context_highlight_list, i), utils.get_from_list(char_list, i - utils._if(not first_indent, 1, 0), char)
context_highlight )
), ),
utils._if( utils._if(
#char_highlight_list > 0, context,
utils.get_from_list(char_highlight_list, i), utils._if(
char_highlight context_pattern_highlight[context_pattern],
) context_pattern_highlight[context_pattern],
) utils.get_from_list(context_highlight_list, i, context_highlight)
} ),
) utils.get_from_list(char_highlight_list, i, char_highlight)
end ),
table.insert( })
virtual_text, end
{ end
utils._if(blankline, space_char_blankline, space_char):rep(space_count), if current_left_offset > 0 then
utils._if( local current_space_count = space_count
blankline, space_count = space_count - current_left_offset
current_left_offset = current_left_offset - current_space_count
end
if space_count > 0 then
-- ternary operator below in table.insert() doesn't work because it would evaluate each option regardless
local tmp_string
local index = 1 + (i - 1) * shiftwidth
if show_indent_or_eol_char then
if table.maxn(virtual_string) >= index + space_count then
-- first char was already set above
tmp_string = table.concat(virtual_string, "", index + 1, index + space_count)
end
else
if table.maxn(virtual_string) >= index + space_count - 1 then
tmp_string = table.concat(virtual_string, "", index, index + space_count - 1)
end
end
table.insert(virtual_text, {
utils._if( utils._if(
#space_char_blankline_highlight_list > 0, tmp_string,
utils.get_from_list(space_char_blankline_highlight_list, i), tmp_string,
space_char_blankline_highlight utils._if(blankline, space_char_blankline, list_chars["lead_char"]):rep(space_count)
), ),
utils._if( utils._if(
#space_char_highlight_list > 0, blankline,
utils.get_from_list(space_char_highlight_list, i), utils.get_from_list(space_char_blankline_highlight_list, i, space_char_blankline_highlight),
space_char_highlight utils.get_from_list(space_char_highlight_list, i, space_char_highlight)
) ),
) })
} end
) end
end
if ((blankline or extra) and trail_indent) and (first_indent or #virtual_text > 0) then
local index = math.ceil(#virtual_text / 2) + 1 local index = math.ceil(#virtual_text / 2) + 1
table.insert( local extra_context_active = context_active and context_indent == index
virtual_text,
{ if
(char ~= "" or (extra_context_active and context_char ~= ""))
and ((blankline or extra) and trail_indent)
and (first_indent or #virtual_text > 0)
and current_left_offset < 1
and indent < local_max_indent_level
then
table.insert(virtual_text, {
utils._if( utils._if(
#char_list > 0, extra_context_active,
utils.get_from_list(char_list, index - utils._if(not first_indent, 1, 0)), utils.get_from_list(context_char_list, index - utils._if(not first_indent, 1, 0), context_char),
char utils.get_from_list(char_list, index - utils._if(not first_indent, 1, 0), char)
), ),
utils._if( utils._if(
context_active and context_indent == index, extra_context_active,
utils._if( utils.get_from_list(context_highlight_list, index, context_highlight),
#context_highlight_list > 0, utils.get_from_list(char_highlight_list, index, char_highlight)
utils.get_from_list(context_highlight_list, index), ),
context_highlight })
), end
utils._if(
#char_highlight_list > 0, return virtual_text
utils.get_from_list(char_highlight_list, index),
char_highlight
)
)
}
)
end end
return virtual_text local prev_indent
end
local next_indent local next_indent
local next_extra local next_extra
local empty_line_counter = 0 local empty_line_counter = 0
@ -160,103 +426,177 @@ local refresh = function()
utils.clear_line_indent(bufnr, i + offset) utils.clear_line_indent(bufnr, i + offset)
else else
local async local async
async = async = vim.loop.new_async(function()
vim.loop.new_async( local blankline = lines[i]:len() == 0
function() local whitespace = string.match(lines[i], "^%s+") or ""
local blankline = lines[i]:len() == 0 local only_whitespace = whitespace == lines[i]
local context_active = false local context_active = false
if context_status then local context_first_line = false
context_active = offset + i > context_start and offset + i <= context_end if context_status then
end context_active = offset + i > context_start and offset + i <= context_end
context_first_line = offset + i == context_start
end
if blankline and use_ts_indent then if blankline and use_ts_indent then
vim.schedule_wrap( vim.schedule_wrap(function()
function() local indent = ts_indent.get_indent(i + offset) or 0
local indent = ts_indent.get_indent(i + offset) utils.clear_line_indent(bufnr, i + offset)
if not indent or indent == 0 then
utils.clear_line_indent(bufnr, i + offset)
return
end
indent = indent / space
if offset + i == context_start then
context_indent = (indent or 0) + 1
end
local virtual_text = if
get_virtual_text(indent, false, blankline, context_active, context_indent) context_first_line
utils.clear_line_indent(bufnr, i + offset) and show_current_context_start
xpcall( and (show_current_context_start_on_current_line or lnum ~= context_start)
vim.api.nvim_buf_set_extmark, then
utils.error_handler,
bufnr,
vim.g.indent_blankline_namespace,
i - 1 + offset,
0,
{virt_text = virtual_text, virt_text_pos = "overlay", hl_mode = "combine"}
)
end
)()
return async:close()
end
local indent, extra
if not blankline then
indent, extra = utils.find_indent(lines[i], space, strict_tabs)
elseif empty_line_counter > 0 then
empty_line_counter = empty_line_counter - 1
indent = next_indent
extra = next_extra
else
if i == #lines then
indent = 0
extra = false
else
local j = i + 1
while (j < #lines and lines[j]:len() == 0) do
j = j + 1
empty_line_counter = empty_line_counter + 1
end
indent, extra = utils.find_indent(lines[j], space, strict_tabs)
end
next_indent = indent
next_extra = extra
end
if offset + i == context_start then
context_indent = (indent or 0) + 1
end
if not indent or indent == 0 then
vim.schedule_wrap(utils.clear_line_indent)(bufnr, i + offset)
return async:close()
end
local virtual_text = get_virtual_text(indent, extra, blankline, context_active, context_indent)
vim.schedule_wrap(
function()
utils.clear_line_indent(bufnr, i + offset)
xpcall( xpcall(
vim.api.nvim_buf_set_extmark, vim.api.nvim_buf_set_extmark,
utils.error_handler, utils.error_handler,
bufnr, bufnr,
vim.g.indent_blankline_namespace, vim.g.indent_blankline_namespace,
i - 1 + offset, context_start - 1,
0, #whitespace,
{virt_text = virtual_text, virt_text_pos = "overlay", hl_mode = "combine"} {
end_col = #lines[i],
hl_group = "IndentBlanklineContextStart",
priority = 10000,
}
) )
end end
)()
if indent == 0 then
return
end
indent = indent / shiftwidth
if context_first_line then
context_indent = indent + 1
end
local virtual_text = get_virtual_text(
indent,
false,
blankline,
context_active,
context_indent,
max_indent_level,
{}
)
xpcall(
vim.api.nvim_buf_set_extmark,
utils.error_handler,
bufnr,
vim.g.indent_blankline_namespace,
i - 1 + offset,
0,
{ virt_text = virtual_text, virt_text_pos = "overlay", hl_mode = "combine" }
)
end)()
return async:close() return async:close()
end end
)
local indent, extra
local virtual_string = {}
if not blankline then
indent, extra, virtual_string = utils.find_indent(
whitespace,
only_whitespace,
shiftwidth,
strict_tabs,
list_chars
)
elseif empty_line_counter > 0 then
empty_line_counter = empty_line_counter - 1
indent = next_indent
extra = next_extra
else
if i == #lines then
indent = 0
extra = false
else
local j = i + 1
while j < #lines and lines[j]:len() == 0 do
j = j + 1
empty_line_counter = empty_line_counter + 1
end
local j_whitespace = string.match(lines[j], "^%s+")
local j_only_whitespace = j_whitespace == lines[j]
indent, extra, _ = utils.find_indent(
j_whitespace,
j_only_whitespace,
shiftwidth,
strict_tabs,
list_chars
)
end
next_indent = indent
next_extra = extra
end
if context_first_line then
context_indent = indent + 1
end
vim.schedule_wrap(utils.clear_line_indent)(bufnr, i + offset)
if
context_first_line
and show_current_context_start
and (show_current_context_start_on_current_line or lnum ~= context_start)
then
vim.schedule_wrap(function()
xpcall(
vim.api.nvim_buf_set_extmark,
utils.error_handler,
bufnr,
vim.g.indent_blankline_namespace,
context_start - 1,
#whitespace,
{
end_col = #lines[i],
hl_group = "IndentBlanklineContextStart",
priority = 10000,
}
)
end)()
end
if indent == 0 and #virtual_string == 0 and not extra then
prev_indent = 0
return async:close()
end
if not prev_indent or indent + utils._if(extra, 1, 0) <= prev_indent + max_indent_increase then
prev_indent = indent
end
local virtual_text = get_virtual_text(
indent,
extra,
blankline,
context_active,
context_indent,
prev_indent - utils._if(trail_indent, 0, 1),
virtual_string
)
vim.schedule_wrap(function()
xpcall(
vim.api.nvim_buf_set_extmark,
utils.error_handler,
bufnr,
vim.g.indent_blankline_namespace,
i - 1 + offset,
0,
{ virt_text = virtual_text, virt_text_pos = "overlay", hl_mode = "combine" }
)
end)()
return async:close()
end)
async:send() async:send()
end end
end end
end end
M.refresh = function() M.refresh = function(scroll)
xpcall(refresh, utils.error_handler) xpcall(refresh, utils.error_handler, scroll)
end end
return M return M

View File

@ -1,71 +1,72 @@
local M = {} local M = {}
M.memo = M.memo = setmetatable({
setmetatable( put = function(cache, params, result)
{ local node = cache
put = function(cache, params, result) for i = 1, #params do
local node = cache local param = vim.inspect(params[i])
for i = 1, #params do node.children = node.children or {}
local param = vim.inspect(params[i]) node.children[param] = node.children[param] or {}
node.children = node.children or {} node = node.children[param]
node.children[param] = node.children[param] or {}
node = node.children[param]
end
node.result = result
end,
get = function(cache, params)
local node = cache
for i = 1, #params do
local param = vim.inspect(params[i])
node = node.children and node.children[param]
if not node then
return nil
end
end
return node.result
end end
}, node.result = result
{ end,
__call = function(memo, func) get = function(cache, params)
local cache = {} local node = cache
for i = 1, #params do
local param = vim.inspect(params[i])
node = node.children and node.children[param]
if not node then
return nil
end
end
return node.result
end,
}, {
__call = function(memo, func)
local cache = {}
return function(...) return function(...)
local params = {...} local params = { ... }
local result = memo.get(cache, params) local result = memo.get(cache, params)
if not result then if not result then
result = {func(...)} result = { func(...) }
memo.put(cache, params, result) memo.put(cache, params, result)
end
return unpack(result)
end end
return unpack(result)
end end
} end,
) })
M.error_handler = function(err) M.error_handler = function(err)
if vim.g.indent_blankline_debug then if vim.g.indent_blankline_debug then
vim.cmd("echohl Error") vim.cmd "echohl Error"
vim.cmd('echomsg "' .. err .. '"') vim.cmd('echomsg "' .. err .. '"')
vim.cmd("echohl None") vim.cmd "echohl None"
end end
end end
M.is_indent_blankline_enabled = M.is_indent_blankline_enabled = M.memo(
M.memo(
function( function(
b_enabled, b_enabled,
g_enabled, g_enabled,
disable_with_nolist,
opt_list,
filetype, filetype,
filetype_include, filetype_include,
filetype_exclude, filetype_exclude,
buftype, buftype,
buftype_exclude, buftype_exclude,
bufname_exclude, bufname_exclude,
bufname) bufname
)
if b_enabled ~= nil then if b_enabled ~= nil then
return b_enabled return b_enabled
end end
if g_enabled == 0 then if g_enabled ~= true then
return false
end
if disable_with_nolist and not opt_list then
return false return false
end end
@ -104,7 +105,14 @@ M.clear_line_indent = function(buf, lnum)
xpcall(vim.api.nvim_buf_clear_namespace, M.error_handler, buf, vim.g.indent_blankline_namespace, lnum - 1, lnum) xpcall(vim.api.nvim_buf_clear_namespace, M.error_handler, buf, vim.g.indent_blankline_namespace, lnum - 1, lnum)
end end
M.get_from_list = function(list, i) M.clear_buf_indent = function(buf)
xpcall(vim.api.nvim_buf_clear_namespace, M.error_handler, buf, vim.g.indent_blankline_namespace, 0, -1)
end
M.get_from_list = function(list, i, default)
if not list or #list == 0 then
return default
end
return list[((i - 1) % #list) + 1] return list[((i - 1) % #list) + 1]
end end
@ -116,27 +124,56 @@ M._if = function(bool, a, b)
end end
end end
M.find_indent = function(line, shiftwidth, strict_tabs) M.find_indent = function(whitespace, only_whitespace, shiftwidth, strict_tabs, list_chars)
local indent = 0 local indent = 0
local spaces = 0 local spaces = 0
for ch in line:gmatch(".") do local tab_width
if ch == " " then local virtual_string = {}
if strict_tabs and indent == 0 and spaces ~= 0 then
return 0, false if whitespace then
for ch in whitespace:gmatch "." do
if ch == "\t" then
if strict_tabs and indent == 0 and spaces ~= 0 then
return 0, false, {}
end
indent = indent + math.floor(spaces / shiftwidth) + 1
spaces = 0
-- replace dynamic-width tab with fixed-width string (ta..ab)
tab_width = shiftwidth - table.maxn(virtual_string) % shiftwidth
-- check if tab_char_end is set, see :help listchars
if list_chars["tab_char_end"] then
if tab_width == 1 then
table.insert(virtual_string, list_chars["tab_char_end"])
else
table.insert(virtual_string, list_chars["tab_char_start"])
for _ = 1, (tab_width - 2) do
table.insert(virtual_string, list_chars["tab_char_fill"])
end
table.insert(virtual_string, list_chars["tab_char_end"])
end
else
table.insert(virtual_string, list_chars["tab_char_start"])
for _ = 1, (tab_width - 1) do
table.insert(virtual_string, list_chars["tab_char_fill"])
end
end
else
if strict_tabs and indent ~= 0 then
-- return early when no more tabs are found
return indent, true, virtual_string
end
if only_whitespace then
-- if the entire line is only whitespace use trail_char instead of lead_char
table.insert(virtual_string, list_chars["trail_char"])
else
table.insert(virtual_string, list_chars["lead_char"])
end
spaces = spaces + 1
end end
indent = indent + math.floor(spaces / shiftwidth) + 1
spaces = 0
elseif ch == " " then
if strict_tabs and indent ~= 0 then
return indent, true
end
spaces = spaces + 1
else
break
end end
end end
indent = indent + math.floor(spaces / shiftwidth)
return indent, spaces % shiftwidth ~= 0 return indent + math.floor(spaces / shiftwidth), table.maxn(virtual_string) % shiftwidth ~= 0, virtual_string
end end
M.get_current_context = function(type_patterns) M.get_current_context = function(type_patterns)
@ -149,7 +186,7 @@ M.get_current_context = function(type_patterns)
if node_type:find(rgx) then if node_type:find(rgx) then
local node_start, _, node_end, _ = cursor_node:range() local node_start, _, node_end, _ = cursor_node:range()
if node_start ~= node_end then if node_start ~= node_end then
return true, node_start + 1, node_end + 1 return true, node_start + 1, node_end + 1, rgx
end end
node_start, node_end = nil, nil node_start, node_end = nil, nil
end end
@ -161,38 +198,116 @@ M.get_current_context = function(type_patterns)
end end
M.reset_highlights = function() M.reset_highlights = function()
local whitespace_highlight = vim.fn.synIDtrans(vim.fn.hlID("Whitespace")) local whitespace_highlight = vim.fn.synIDtrans(vim.fn.hlID "Whitespace")
local label_highlight = vim.fn.synIDtrans(vim.fn.hlID("Label")) local label_highlight = vim.fn.synIDtrans(vim.fn.hlID "Label")
local whitespace_fg = { local whitespace_fg = {
vim.fn.synIDattr(whitespace_highlight, "fg", "gui"), vim.fn.synIDattr(whitespace_highlight, "fg", "gui"),
vim.fn.synIDattr(whitespace_highlight, "fg", "cterm") vim.fn.synIDattr(whitespace_highlight, "fg", "cterm"),
} }
local label_fg = { local label_fg = {
vim.fn.synIDattr(label_highlight, "fg", "gui"), vim.fn.synIDattr(label_highlight, "fg", "gui"),
vim.fn.synIDattr(label_highlight, "fg", "cterm") vim.fn.synIDattr(label_highlight, "fg", "cterm"),
} }
for highlight_name, highlight in pairs( for highlight_name, highlight in pairs {
{ IndentBlanklineChar = whitespace_fg,
IndentBlanklineChar = whitespace_fg, IndentBlanklineSpaceChar = whitespace_fg,
IndentBlanklineSpaceChar = whitespace_fg, IndentBlanklineSpaceCharBlankline = whitespace_fg,
IndentBlanklineSpaceCharBlankline = whitespace_fg, IndentBlanklineContextChar = label_fg,
IndentBlanklineContextChar = label_fg IndentBlanklineContextStart = label_fg,
} } do
) do
local current_highlight = vim.fn.synIDtrans(vim.fn.hlID(highlight_name)) local current_highlight = vim.fn.synIDtrans(vim.fn.hlID(highlight_name))
if vim.fn.synIDattr(current_highlight, "fg") == "" and vim.fn.synIDattr(current_highlight, "bg") == "" then if
vim.cmd( vim.fn.synIDattr(current_highlight, "fg") == ""
string.format( and vim.fn.synIDattr(current_highlight, "bg") == ""
"highlight %s guifg=%s ctermfg=%s gui=nocombine cterm=nocombine", and vim.fn.synIDattr(current_highlight, "sp") == ""
highlight_name, then
M._if(highlight[1] == "", "NONE", highlight[1]), if highlight_name == "IndentBlanklineContextStart" then
M._if(highlight[2] == "", "NONE", highlight[2]) vim.cmd(
string.format(
"highlight %s guisp=%s gui=underline cterm=underline",
highlight_name,
M._if(highlight[1] == "", "NONE", highlight[1])
)
) )
) else
vim.cmd(
string.format(
"highlight %s guifg=%s ctermfg=%s gui=nocombine cterm=nocombine",
highlight_name,
M._if(highlight[1] == "", "NONE", highlight[1]),
M._if(highlight[2] == "", "NONE", highlight[2])
)
)
end
end end
end end
end end
M.first_not_nil = function(...)
for _, value in pairs { ... } do
return value
end
end
M.get_variable = function(key)
if vim.b[key] ~= nil then
return vim.b[key]
end
if vim.t[key] ~= nil then
return vim.t[key]
end
return vim.g[key]
end
M.merge_ranges = function(ranges)
local merged_ranges = { { unpack(ranges[1]) } }
for i = 2, #ranges do
local current_end = merged_ranges[#merged_ranges][2]
local next_start, next_end = unpack(ranges[i])
if current_end >= next_start - 1 then
if current_end < next_end then
merged_ranges[#merged_ranges][2] = next_end
end
else
table.insert(merged_ranges, { next_start, next_end })
end
end
return merged_ranges
end
M.binary_search_ranges = function(ranges, target_range)
local exact_match = false
local idx_start = 1
local idx_end = #ranges
local idx_mid
local range_start
local target_start = target_range[1]
while idx_start < idx_end do
idx_mid = math.ceil((idx_start + idx_end) / 2)
range_start = ranges[idx_mid][1]
if range_start == target_start then
exact_match = true
break
elseif range_start < target_start then
idx_start = idx_mid -- it's important to make the low-end inclusive
else
idx_end = idx_mid - 1
end
end
-- if we don't have an exact match, choose the smallest index
if not exact_match then
idx_mid = idx_start
end
return idx_mid
end
return M return M

View File

@ -4,37 +4,6 @@ if exists('g:loaded_indent_blankline') || !has('nvim-0.5.0')
endif endif
let g:loaded_indent_blankline = 1 let g:loaded_indent_blankline = 1
let g:indent_blankline_char = get(g:, 'indent_blankline_char', get(g:, 'indentLine_char', '|'))
let g:indent_blankline_char_list = get(g:, 'indent_blankline_char_list', get(g:, 'indentLine_char_list', []))
let g:indent_blankline_char_highlight_list = get(g:, 'indent_blankline_char_highlight_list', [])
let g:indent_blankline_space_char = get(g:, 'indent_blankline_space_char', indent_blankline#helper#GetListChar('space', ' '))
let g:indent_blankline_space_char_highlight_list = get(g:, 'indent_blankline_space_char_highlight_list', [])
let g:indent_blankline_space_char_blankline = get(g:, 'indent_blankline_space_char_blankline', g:indent_blankline_space_char)
let g:indent_blankline_space_char_blankline_highlight_list = get(g:, 'indent_blankline_space_char_blankline_highlight_list', g:indent_blankline_space_char_highlight_list)
let g:indent_blankline_indent_level = get(g:, 'indent_blankline_indent_level', get(g:, 'indentLine_indentLevel', 20))
let g:indent_blankline_enabled = get(g:, 'indent_blankline_enabled', get(g:, 'indentLine_enabled', v:true))
let g:indent_blankline_filetype = get(g:, 'indent_blankline_filetype', get(g:, 'indentLine_fileType', []))
let g:indent_blankline_filetype_exclude = get(g:, 'indent_blankline_filetype_exclude', get(g:, 'indentLine_fileTypeExclude', []))
let g:indent_blankline_bufname_exclude = get(g:, 'indent_blankline_bufname_exclude', get(g:, 'indentLine_bufNameExclude', []))
let g:indent_blankline_buftype_exclude = get(g:, 'indent_blankline_buftype_exclude', get(g:, 'indentLine_bufTypeExclude', []))
let g:indent_blankline_viewport_buffer = get(g:, 'indent_blankline_viewport_buffer', 10)
let g:indent_blankline_use_treesitter = get(g:, 'indent_blankline_use_treesitter', v:false)
let g:indent_blankline_debug = get(g:, 'indent_blankline_debug', v:false)
let g:indent_blankline_disable_warning_message = get(g:, 'indent_blankline_disable_warning_message', v:false)
let g:indent_blankline_show_first_indent_level = get(g:, 'indent_blankline_show_first_indent_level', v:true)
let g:indent_blankline_show_trailing_blankline_indent = get(g:, 'indent_blankline_show_trailing_blankline_indent', v:true)
let g:indent_blankline_show_end_of_line = get(g:, 'indent_blankline_show_end_of_line', v:false)
let g:indent_blankline_show_foldtext = get(g:, 'indent_blankline_show_foldtext', v:true)
let g:indent_blankline_show_current_context = get(g:, 'indent_blankline_show_current_context', v:false)
let g:indent_blankline_context_highlight_list = get(g:, 'indent_blankline_context_highlight_list', [])
let g:indent_blankline_context_patterns = get(g:, 'indent_blankline_context_patterns', ['class', 'function', 'method'])
let g:indent_blankline_strict_tabs = get(g:, 'indent_blankline_strict_tabs', v:false)
lua require("indent_blankline").setup()
function s:try(cmd) function s:try(cmd)
try try
execute a:cmd execute a:cmd
@ -44,30 +13,29 @@ function s:try(cmd)
endfunction endfunction
command! -bang IndentBlanklineRefresh call s:try('lua require("indent_blankline.commands").refresh("<bang>" == "!")') command! -bang IndentBlanklineRefresh call s:try('lua require("indent_blankline.commands").refresh("<bang>" == "!")')
command! -bang IndentBlanklineRefreshScroll call s:try('lua require("indent_blankline.commands").refresh("<bang>" == "!", true)')
command! -bang IndentBlanklineEnable call s:try('lua require("indent_blankline.commands").enable("<bang>" == "!")') command! -bang IndentBlanklineEnable call s:try('lua require("indent_blankline.commands").enable("<bang>" == "!")')
command! -bang IndentBlanklineDisable call s:try('lua require("indent_blankline.commands").disable("<bang>" == "!")') command! -bang IndentBlanklineDisable call s:try('lua require("indent_blankline.commands").disable("<bang>" == "!")')
command! -bang IndentBlanklineToggle call s:try('lua require("indent_blankline.commands").toggle("<bang>" == "!")') command! -bang IndentBlanklineToggle call s:try('lua require("indent_blankline.commands").toggle("<bang>" == "!")')
function s:IndentBlanklineInit() if exists(':IndentLinesEnable') && !g:indent_blankline_disable_warning_message
if exists(':IndentLinesEnable') && !g:indent_blankline_disable_warning_message echohl Error
echohl Error echom 'indent-blankline does not require IndentLine anymore, please remove it.'
echom 'indent-blankline does not require IndentLine anymore, please remove it.' echohl None
echohl None endif
endif
IndentBlanklineRefresh! if !exists('g:__indent_blankline_setup_completed')
endfunction lua require("indent_blankline").setup {}
endif
lua require("indent_blankline").init()
augroup IndentBlanklineAutogroup augroup IndentBlanklineAutogroup
autocmd! autocmd!
autocmd OptionSet shiftwidth,tabstop,expandtab IndentBlanklineRefresh autocmd OptionSet list,shiftwidth,tabstop,expandtab IndentBlanklineRefresh
autocmd FileChangedShellPost,TextChanged,TextChangedI,WinScrolled,BufWinEnter,Filetype * IndentBlanklineRefresh autocmd FileChangedShellPost,TextChanged,TextChangedI,CompleteChanged,BufWinEnter,Filetype * IndentBlanklineRefresh
autocmd VimEnter * call s:IndentBlanklineInit() autocmd WinScrolled * IndentBlanklineRefreshScroll
autocmd ColorScheme * lua require("indent_blankline.utils").reset_highlights() autocmd ColorScheme * lua require("indent_blankline.utils").reset_highlights()
autocmd VimEnter * lua require("indent_blankline").init()
augroup END augroup END
if g:indent_blankline_show_current_context
augroup IndentBlanklineContextAutogroup
autocmd!
autocmd CursorMoved * IndentBlanklineRefresh
augroup END
endif

View File

@ -0,0 +1,4 @@
line_endings = "Unix"
indent_type = "Spaces"
indent_width = 4
no_call_parentheses = true