Skip to content

Commit a2eb2dc

Browse files
authored
Merge pull request #43 from savchenko/main
Improve level detection, allow disabling in specific TreeSitter classes, add toggle functionality and lazy-loading
2 parents e0f1e38 + 4117c95 commit a2eb2dc

File tree

3 files changed

+180
-32
lines changed

3 files changed

+180
-32
lines changed

README.md

Lines changed: 77 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,96 @@
11
# indentmini.nvim
22

3-
An indentation plugin born for the pursuit of **minimal**(~120 lines), **speed**(blazing fastest on files with tens of thousands of lines) and **stability**.
4-
It renders in the neovim screen redraw circle and will never make your neovim slow.
5-
6-
![indentmini](https://github.com/nvimdev/indentmini.nvim/assets/41671631/99fb6dd4-8e61-412f-aa4c-c83ee7ce3206)
3+
An indentation plugin born for the pursuit of minimalism, speed and stability.<br>
4+
It renders in the NeoVim screen redraw circle and should keep the NeoVim fast.
75

86
## Install
97

10-
install with any plugin management or default vim package.
8+
Install with any plugin manager or as a NeoVim package.
9+
10+
## Configuration
1111

12-
## Config
12+
| Key | Description | Default |
13+
|------------------|-----------------------------------------------|---------------------------|
14+
| char | Character to draw the indentation guides | `<BAR>` |
15+
| enabled | Default state of the plugin | `true` |
16+
| exclude | Disable in these filetypes | `{}` |
17+
| exclude_nodetype | TreeSitter classes where guides are not drawn | `{ 'string', 'comment' }` |
18+
| key | Hotkey to toggle the guides | `''` |
19+
| minlevel | Minimum level where indentation is drawn | `0` |
20+
| only_current | only highlight current indentation level | `false` |
1321

14-
available config values in setup table.
22+
### Example
1523

16-
- char -- string type default is ``,
17-
- exclude -- table type add exclude filetype in this table ie `{ 'markdown', 'xxx'}`
18-
- minlevel -- number the min level that show indent line default is 1
19-
- only_current -- boolean default is false when true will only highlight current range
24+
The plugin supports lazy-loading:
2025

2126
```lua
22-
config = function()
23-
require("indentmini").setup() -- use default config
24-
end,
27+
-- Either declare `vim.g.indentmini_key` before you load the plugin:
28+
vim.g.indentmini_key = '<F5>'
29+
30+
-- or use your plugin manager, for example Lazy.nvim:
31+
{
32+
url = 'https://github.com/nvimdev/indentmini.nvim',
33+
cmd = { 'IndentToggle', 'IndentEnable', 'IndentDisable' },
34+
keys = {
35+
{'<F5>', '<Cmd>IndentToggle<CR>', desc = 'Toggle indent guides'},
36+
},
37+
lazy = true,
38+
config = function()
39+
require("indentmini").setup({
40+
only_current = false,
41+
enabled = false,
42+
char = '',
43+
key = '<F5>', -- optional, can be set here if you don't lazy-load
44+
minlevel = 2,
45+
exclude = { 'markdown', 'help', 'text', 'rst' },
46+
exclude_nodetype = { 'string', 'comment' }
47+
})
48+
end
49+
}
2550
```
2651

27-
## Highlight
52+
## Toggle functionality
53+
54+
You can toggle the guides via:
55+
56+
#### Commands
2857

29-
if your colorscheme not config the `IndentLine*` relate highlight group you should config it in
30-
your neovim config.
58+
- `:IndentToggle` - Toggle indent guides on/off
59+
- `:IndentEnable` - Enable indent guides
60+
- `:IndentDisable` - Disable indent guides
61+
62+
#### Hotkey
63+
64+
For lazy-loading setups, set the global variable before the plugin loads:
65+
```lua
66+
vim.g.indentmini_key = '<F5>'
67+
```
68+
69+
For non-lazy setups, use the `key` option in `setup()`:
70+
```lua
71+
require("indentmini").setup({
72+
key = '<F5>',
73+
})
74+
```
75+
76+
#### API
77+
78+
```lua
79+
local indentmini = require("indentmini")
80+
indentmini.toggle()
81+
indentmini.enable()
82+
indentmini.disable()
83+
```
84+
85+
## Colours
86+
87+
The plugin uses `IndentLine*` highlight groups and provides no default values.
3188

3289
```lua
33-
-- Colors are applied automatically based on user-defined highlight groups.
34-
-- There is no default value.
3590
vim.cmd.highlight('IndentLine guifg=#123456')
36-
-- Current indent line highlight
3791
vim.cmd.highlight('IndentLineCurrent guifg=#123456')
3892
```
3993

40-
## License MIT
94+
## Licence
95+
96+
MIT

lua/indentmini/init.lua

Lines changed: 78 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ local ffi, treesitter = require('ffi'), vim.treesitter
55
local opt = {
66
only_current = false,
77
exclude = { 'dashboard', 'lazy', 'help', 'nofile', 'terminal', 'prompt', 'qf' },
8+
exclude_nodetype = { 'string', 'comment' },
89
config = {
910
virt_text_pos = 'overlay',
1011
hl_mode = 'combine',
1112
ephemeral = true,
1213
},
1314
}
1415

16+
local enabled = true
17+
1518
ffi.cdef([[
1619
typedef struct {} Error;
1720
typedef int colnr_T;
@@ -229,6 +232,15 @@ local function on_line(_, _, bufnr, row)
229232
if context.is_tab and not context.mixup then
230233
col = level - 1
231234
end
235+
if context.has_ts then
236+
local node = treesitter.get_node({ bufnr = bufnr, pos = { row, col }, ignore_injections = true })
237+
while node do
238+
if vim.tbl_contains(opt.exclude_nodetype, node:type()) then
239+
goto continue
240+
end
241+
node = node:parent()
242+
end
243+
end
232244
if
233245
col >= context.leftcol
234246
and level >= opt.minlevel
@@ -248,10 +260,14 @@ local function on_line(_, _, bufnr, row)
248260
buf_set_extmark(bufnr, ns, row, col, opt.config)
249261
opt.config.virt_text_win_col = nil
250262
end
263+
::continue::
251264
end
252265
end
253266

254267
local function on_win(_, winid, bufnr, toprow, botrow)
268+
if not enabled then
269+
return false
270+
end
255271
if
256272
bufnr ~= api.nvim_get_current_buf()
257273
or vim.iter(opt.exclude):find(function(v)
@@ -279,16 +295,67 @@ local function on_win(_, winid, bufnr, toprow, botrow)
279295
local pos = api.nvim_win_get_cursor(winid)
280296
context.currow = pos[1] - 1
281297
context.curcol = pos[2]
282-
find_current_range(find_in_snapshot(context.currow + 1).indent, context.currow)
298+
local cur_indent = find_in_snapshot(context.currow + 1).indent
299+
local next_indent = (context.currow + 1 < context.count) and find_in_snapshot(context.currow + 2).indent or 0
300+
-- We only want to look backwards if we are closing a block
301+
local line_text = api.nvim_get_current_line()
302+
local is_closer = line_text:find('^%s*[})%]]') or line_text:find('^%s*end')
303+
local target_indent = cur_indent
304+
if next_indent > cur_indent then
305+
target_indent = next_indent
306+
elseif is_closer then
307+
local prev_indent = context.currow > 0 and find_in_snapshot(context.currow).indent or 0
308+
if prev_indent > cur_indent then
309+
target_indent = prev_indent
310+
end
311+
end
312+
find_current_range(target_indent, context.currow)
283313
end
284314

285-
return {
286-
setup = function(conf)
287-
conf = conf or {}
288-
opt.only_current = conf.only_current or false
289-
opt.exclude = vim.list_extend(opt.exclude, conf.exclude or {})
290-
opt.config.virt_text = { { conf.char or '' } }
291-
opt.minlevel = conf.minlevel or 1
292-
set_provider(ns, { on_win = on_win, on_line = on_line })
293-
end,
294-
}
315+
local M = {}
316+
317+
function M.toggle()
318+
enabled = not enabled
319+
vim.api.nvim__redraw({
320+
buf = vim.api.nvim_get_current_buf(),
321+
valid = false
322+
})
323+
end
324+
325+
function M.enable()
326+
enabled = true
327+
vim.api.nvim__redraw({
328+
buf = vim.api.nvim_get_current_buf(),
329+
valid = false
330+
})
331+
end
332+
333+
function M.disable()
334+
enabled = false
335+
vim.api.nvim__redraw({
336+
buf = vim.api.nvim_get_current_buf(),
337+
valid = false
338+
})
339+
end
340+
341+
--- @param conf table|nil IndentMini config
342+
function M.setup(conf)
343+
conf = conf or {}
344+
enabled = conf.enabled ~= false
345+
opt.only_current = conf.only_current or false
346+
opt.exclude = vim.list_extend(opt.exclude, conf.exclude or {})
347+
opt.exclude_nodetype = vim.list_extend(opt.exclude_nodetype, conf.exclude_nodetype or {})
348+
opt.config.virt_text = { { conf.char or '' } }
349+
opt.minlevel = conf.minlevel or 1
350+
set_provider(ns, { on_win = on_win, on_line = on_line })
351+
352+
if conf.key then
353+
vim.keymap.set('n', conf.key, '<Cmd>IndentToggle<CR>', {
354+
desc = 'Toggle indent guides',
355+
noremap = true,
356+
silent = true,
357+
})
358+
end
359+
end
360+
361+
return M

plugin/indentmini.lua

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
vim.api.nvim_create_user_command(
2+
'IndentToggle',
3+
function() require('indentmini').toggle() end,
4+
{ desc = 'Toggle indent guides' }
5+
)
6+
7+
vim.api.nvim_create_user_command(
8+
'IndentEnable',
9+
function() require('indentmini').enable() end,
10+
{ desc = 'Enable indent guides' }
11+
)
12+
13+
vim.api.nvim_create_user_command(
14+
'IndentDisable',
15+
function() require('indentmini').disable() end,
16+
{ desc = 'Disable indent guides' }
17+
)
18+
19+
if vim.g.indentmini_key then
20+
vim.keymap.set('n', vim.g.indentmini_key, '<Cmd>IndentToggle<CR>', {
21+
desc = 'Toggle indent guides',
22+
noremap = true,
23+
silent = true,
24+
})
25+
end

0 commit comments

Comments
 (0)