Skip to content

Commit

Permalink
improve highlight current
Browse files Browse the repository at this point in the history
  • Loading branch information
glepnir committed May 2, 2024
1 parent ff7d4f4 commit 732a18d
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 35 deletions.
68 changes: 36 additions & 32 deletions lua/indentmini/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local au, nvim_buf_set_extmark = api.nvim_create_autocmd, api.nvim_buf_set_extma
local ns = api.nvim_create_namespace('IndentLine')
local g = api.nvim_create_augroup('IndentMini', { clear = true })
local indent_fn = vim.fn.indent
local UP, DOWN = -1, 1

---check column in screen
local function col_in_screen(col)
Expand All @@ -22,6 +23,26 @@ local function on_win(_, winid, bufnr, _)
api.nvim_win_set_hl_ns(winid, ns)
end

local function find_row(bufnr, row, direction, render)
local target_row = row + direction
local count = api.nvim_buf_line_count(bufnr)
local curindent = indent_fn(row + 1)
while true do
local ok, lines = pcall(api.nvim_buf_get_text, bufnr, target_row, 0, target_row, -1, {})
if not ok or target_row < 0 or target_row > count - 1 then
break
end
local non_empty = #lines[1] ~= 0
local target_indent = indent_fn(target_row + 1)
if target_indent == 0 and non_empty and direction ~= DOWN and render then
break
elseif non_empty and (render and target_indent > curindent or target_indent < curindent) then
return target_row
end
target_row = target_row + direction
end
end

local config = {
virt_text_pos = 'overlay',
hl_mode = 'combine',
Expand Down Expand Up @@ -55,27 +76,15 @@ local function indentline(opt)
local line_is_empty = #lines[1] == 0
local shiftw = vim.fn.shiftwidth()
if indent == 0 and line_is_empty then
local prev_row = row - 1
while true do
ok, lines = pcall(api.nvim_buf_get_text, bufnr, prev_row, 0, prev_row, -1, {})
if not ok then
break
end
local prev_indent = indent_fn(prev_row + 1)
if prev_indent == 0 and #lines[1] ~= 0 then
break
elseif #lines[1] ~= 0 and prev_indent > 0 then
indent = prev_indent
break
end
prev_row = prev_row - 1
local target_row = find_row(bufnr, row, DOWN, true)
if target_row then
indent = indent_fn(target_row + 1)
end
end

for i = 1, indent - 1, shiftw do
local col = i - 1
local indent_level = math.floor(col / shiftw) + 1
local hi_name = ('IndentLine%d'):format(indent_level)
local hi_name = ('IndentLine%d%d'):format(row + 1, col + 1)
if col_in_screen(col) and is_space(row, col) then
config.virt_text[1][2] = hi_name
if line_is_empty and col > 0 then
Expand All @@ -91,29 +100,24 @@ local function indentline(opt)
au('CursorMoved', {
group = g,
buffer = bufnr,
callback = function()
callback = function(data)
local cur_hi = 'IndentLineCurrent'
local line, _ = unpack(api.nvim_win_get_cursor(0))
local level = math.floor(indent_fn(line) / vim.fn.shiftwidth())
local curindent = indent_fn(line)
local srow = find_row(data.buf, line - 1, UP, false) or 0
local erow = find_row(data.buf, line - 1, DOWN, false) or 0
local hls = api.nvim_get_hl(ns, {})
if level < 1 then
for k, v in pairs(hls) do
if v.link and v.link == cur_hi then
api.nvim_set_hl(ns, k, { link = 'IndentLine' })
break
end
for k, v in pairs(hls) do
if v.link and v.link == cur_hi then
api.nvim_set_hl(ns, k, { link = 'IndentLine', force = true })
end
return
end
local name = ('IndentLine%d'):format(level)
if hls[name] and hls[name].link and hls[name].link == cur_hi then
if erow < 1 then
return
end
api.nvim_set_hl(ns, name, { link = cur_hi })
for k, _ in pairs(hls) do
if k ~= name then
api.nvim_set_hl(ns, k, { link = 'IndentLine' })
end
for i = srow, erow, 1 do
local hi_name = ('IndentLine%d%d'):format(i + 1, curindent - 1)
api.nvim_set_hl(ns, hi_name, { link = cur_hi })
end
end,
})
Expand Down
34 changes: 34 additions & 0 deletions test.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,41 @@
local function test_b()
local a = 10

if true then
if true then
local b = 20

while true do
print('hello')
end

print('here')
end
end
end

local function test()
local a = 10

if true then
if true then
local b = 20

while true do
print('hello')
end

print('here')
end
end
end

local function test_a()
while true do
if true then
if true then
print('test')
end
end
end
end
87 changes: 84 additions & 3 deletions test/indentmini_spec.lua
Original file line number Diff line number Diff line change
@@ -1,13 +1,54 @@
local api = vim.api
require('indentmini').setup({})

local function screen(lines)
local channel, job_id

local function clean()
vim.fn.jobstop(job_id)
job_id = nil
channel = nil
end

local function nvim_instance()
local address = vim.fn.tempname()
vim.fn.jobstart({ 'nvim', '--clean', '-n', '--listen', address }, { pty = true })
job_id = vim.fn.jobstart({ 'nvim', '--clean', '-n', '--listen', address }, { pty = true })
vim.loop.sleep(200)
return vim.fn.sockconnect('pipe', address, { rpc = true })
end

local channel = vim.fn.sockconnect('pipe', address, { rpc = true })
local function nvim_set_cursor(line, col)
vim.rpcrequest(channel, 'nvim_win_set_cursor', 0, {line, col})
end

local function get_indent_ns()
local t = vim.rpcrequest(channel, 'nvim_get_namespaces' )
for k, v in pairs(t) do
if k:find('Indent') then
return v
end
end
end

local function nvim_get_hl(ns)
return vim.rpcrequest(channel, 'nvim_get_hl', ns, {})
end

local function match_current_hl(srow, erow ,col)
local cur_hi = 'IndentLineCurrent'
local ns = get_indent_ns()
local t = {}
for k, v in pairs(nvim_get_hl(ns) or {}) do
if v.link and v.link == cur_hi then
t[#t + 1] = k:match('IndentLine(%d+)5')
end
end
return #t
end

local function screen(lines)
if not channel then
channel = nvim_instance()
end
local current_dir = vim.fn.getcwd()
vim.rpcrequest(channel, 'nvim_set_option_value', 'rtp', current_dir, { scope = 'global' })
vim.rpcrequest(channel, 'nvim_exec_lua', 'require("indentmini").setup({})', {})
Expand Down Expand Up @@ -139,4 +180,44 @@ describe('indent mini', function()
}
assert.same(expected, screenstr)
end)

it('works on highlight current level', function ()
local lines= {
'local function test_b()',
' local a = 10 ',
' ',
' if true then ',
' if true then ',
' local b = 20 ',
' ',
' while true do ',
' print("hello") ',
' end ',
' ',
' print("here") ',
' end ',
' end ',
'end ',
' ',
'local function test() ',
' local a = 10 ',
' ',
' if true then ',
' if true then ',
' local b = 20 ',
' ',
' while true do ',
' print("hello") ',
' end ',
' ',
' print("here") ',
' end ',
' end ',
'end ',
}
screen(lines)
nvim_set_cursor(6, 8)
local ns = get_indent_ns()
assert.same(9, match_current_hl(6, 12, 5))
end)
end)

0 comments on commit 732a18d

Please sign in to comment.