Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improve scope detection and calculation #805

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/indent_blankline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,8 @@ config.scope *ibl.config.scope*
this is to the right of the indent guide) and an
underline on the last line of the scope ending at
the exact end of the scope.
Also activates exact highlighting of one line
scopes.

Default: `false` ~

Expand Down
17 changes: 14 additions & 3 deletions lua/ibl/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ M.refresh = function(bufnr)
local scope
local scope_start_line, scope_end_line
if not scope_disabled and config.scope.enabled then
scope = scp.get(bufnr, config)
scope = scp.get(bufnr, config, global_buffer_state[bufnr] or {})
if scope and scope:start() >= 0 then
local scope_start = scope:start()
local scope_end = scope:end_()
Expand Down Expand Up @@ -432,10 +432,21 @@ M.refresh = function(bufnr)
if config.scope.show_exact_scope then
scope_col_start_draw = exact_scope_col_start - 1
scope_show_end_cond = #whitespace_tbl >= scope_col_start_single

-- one line scopes
if scope_start and scope_end then
vim.api.nvim_buf_set_extmark(bufnr, namespace, row - 1, scope_col_start_draw, {
end_col = scope_col_end,
hl_group = scope_hl.underline,
priority = config.scope.priority,
strict = false,
})
inlay_hints.set(bufnr, row - 1, #whitespace, scope_hl.underline, scope_hl.underline)
end
end

-- Scope start
if config.scope.show_start and scope_start then
if config.scope.show_start and scope_start and not scope_end then
vim.api.nvim_buf_set_extmark(bufnr, namespace, row - 1, scope_col_start_draw, {
end_col = #line,
hl_group = scope_hl.underline,
Expand All @@ -446,7 +457,7 @@ M.refresh = function(bufnr)
end

-- Scope end
if config.scope.show_end and scope_end and scope_show_end_cond then
if config.scope.show_end and scope_end and scope_show_end_cond and not scope_start then
vim.api.nvim_buf_set_extmark(bufnr, namespace, row - 1, scope_col_start, {
end_col = scope_col_end,
hl_group = scope_hl.underline,
Expand Down
20 changes: 15 additions & 5 deletions lua/ibl/scope.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ local M = {}

---@param win number
---@return table<number, number>
M.get_cursor_range = function(win)
---@return table<number, number>
M.get_cursor_ranges = function(win)
local pos = vim.api.nvim_win_get_cursor(win)
local row, col = pos[1] - 1, pos[2]
return { row, 0, row, col }
return { row, 0, row, col }, { row, col, row, col }
end

--- Takes a language tree and a range, and returns the child language tree for that range
Expand All @@ -34,8 +35,9 @@ end

---@param bufnr number
---@param config ibl.config.full
---@param buffer_state { scope: TSNode?, left_offset: number, top_offset: number, tick: number }
---@return TSNode?
M.get = function(bufnr, config)
M.get = function(bufnr, config, buffer_state)
local lang_tree_ok, lang_tree = pcall(vim.treesitter.get_parser, bufnr)
if not lang_tree_ok or not lang_tree then
return nil
Expand All @@ -51,7 +53,7 @@ M.get = function(bufnr, config)
win = 0
end

local range = M.get_cursor_range(win)
local range, cursor_range = M.get_cursor_ranges(win)
lang_tree = M.language_for_range(lang_tree, range, config)
if not lang_tree then
return nil
Expand All @@ -62,10 +64,18 @@ M.get = function(bufnr, config)
return nil
end

local node = lang_tree:named_node_for_range(range, { bufnr = bufnr })
local node = lang_tree:named_node_for_range(cursor_range, { bufnr = bufnr })
if not node then
return nil
end
if node:start() == node:end_() and not config.scope.show_exact_scope then
node = lang_tree:named_node_for_range(range, { bufnr = bufnr }) or node
end

-- if the scope didn't change, return node immediately
if buffer_state.scope and buffer_state.scope:equal(node) then
return node
end

local excluded_node_types =
utils.tbl_join(config.scope.exclude.node_type["*"] or {}, config.scope.exclude.node_type[lang] or {})
Expand Down
Loading