8000 mini.nvim/lua/mini/jump2d.lua at main · cosmicbuffalo/mini.nvim · GitHub
[go: up one dir, main page]

Skip to content

Latest commit

 

History

History
1180 lines (1028 loc) · 43.5 KB

jump2d.lua

File metadata and controls

1180 lines (1028 loc) · 43.5 KB
local label_max_count = base + (label_id <= extra and 1 or 0)
for _, spot_steps in ipairs(spot_steps_arr) do
table.insert(spot_steps, label_tbl[label_id])
table.insert(cur_label_spot_steps, spot_steps)
if #cur_label_spot_steps >= label_max_count then
H.populate_spot_steps(cur_label_spot_steps, label_tbl, cur_step + 1, max_step)
label_id, cur_label_spot_steps = label_id + 1, {}
label_max_count = base + (label_id <= extra and 1 or 0)
end
end
end
H.spots_show = function(spots, opts)
spots = spots or H.cache.spots or {}
local set_extmark = vim.api.nvim_buf_set_extmark
-- Add extmark with proper virtual text to jump spots
local dim_buf_lines = {}
for _, extmark in ipairs(H.spots_to_extmarks(spots, opts)) do
local extmark_opts = {
hl_mode = 'combine',
-- Use very high priority
priority = 1000,
virt_text = extmark.virt_text,
virt_text_pos = 'overlay',
}
local buf_id, line = extmark.buf_id, extmark.line
pcall(set_extmark, buf_id, H.ns_id.spots, line, extmark.col, extmark_opts)
-- Register lines to dim
local lines = dim_buf_lines[buf_id] or {}
lines[line] = true
dim_buf_lines[buf_id] = lines
end
-- Possibly dim used lines
if opts.view.dim then
local extmark_opts = { end_col = 0, hl_eol = true, hl_group = opts.hl_group_dim, priority = 999 }
for buf_id, lines in pairs(dim_buf_lines) do
for _, l_num in ipairs(vim.tbl_keys(lines)) do
extmark_opts.end_line = l_num + 1
pcall(set_extmark, buf_id, H.ns_id.dim, l_num, 0, extmark_opts)
end
end
end
-- Redraw to force showing marks
vim.cmd('redraw')
end
H.spots_unshow = function(spots)
spots = spots or H.cache.spots or {}
-- Remove spot extmarks from all buffers they are present
local buf_ids = {}
for _, s in ipairs(spots) do
buf_ids[s.buf_id] = true
end
for _, buf_id in ipairs(vim.tbl_keys(buf_ids)) do
pcall(vim.api.nvim_buf_clear_namespace, buf_id, H.ns_id.spots, 0, -1)
pcall(vim.api.nvim_buf_clear_namespace, buf_id, H.ns_id.dim, 0, -1)
end
end
--- Convert consecutive spot labels into single extmark
---
--- This considerably increases performance in case of many spots.
---@private
H.spots_to_extmarks = function(spots, opts)
if #spots == 0 then return {} end
local hl_group, hl_group_ahead, hl_group_unique = opts.hl_group, opts.hl_group_ahead, opts.hl_group_unique
-- Compute counts for first step in order to distinguish which highlight
-- group to use: `hl_group` or `hl_group_unique`
local first_step_counts = {}
for _, s in ipairs(spots) do
local cur_first_step = s.steps[1]
local cur_count = first_step_counts[cur_first_step] or 0
first_step_counts[cur_first_step] = cur_count + 1
end
-- Define how steps for single spot are added to virtual text
local append_to_virt_text = function(virt_text_arr, steps, n_steps_to_show)
-- Use special group if current first step is unique
local first_hl_group = first_step_counts[steps[1]] == 1 and hl_group_unique or hl_group
table.insert(virt_text_arr, { steps[1], first_hl_group })
-- Add ahead steps only if they are present
local ahead_label = table.concat(steps):sub(2, n_steps_to_show)
if ahead_label ~= '' then table.insert(virt_text_arr, { ahead_label, hl_group_ahead }) end
end
-- Convert all spots to array of extmarks
local res = {}
local buf_id, line, col, virt_text = spots[1].buf_id, spots[1].line - 1, spots[1].column - 1, {}
for i = 1, #spots - 1 do
local cur_spot, next_spot = spots[i], spots[i + 1]
local n_steps = #cur_spot.steps
-- Find which spot steps can be shown
local is_in_same_line = cur_spot.buf_id == next_spot.buf_id and cur_spot.line == next_spot.line
local max_allowed_steps = is_in_same_line and (next_spot.column - cur_spot.column) or math.huge
local n_steps_to_show = math.min(n_steps, max_allowed_steps)
-- Add text for shown steps
append_to_virt_text(virt_text, cur_spot.steps, n_steps_to_show)
-- Finish creating extmark if next spot is far enough
local next_is_close = is_in_same_line and n_steps == max_allowed_steps
if not next_is_close then
table.insert(res, { buf_id = buf_id, line = line, col = col, virt_text = virt_text })
buf_id, line, col, virt_text = next_spot.buf_id, next_spot.line - 1, next_spot.column - 1, {}
end
end
local last_steps = spots[#spots].steps
append_to_virt_text(virt_text, last_steps, #last_steps)
table.insert(res, { buf_id = buf_id, line = line, col = col, virt_text = virt_text })
return res
end
H.spot_find_in_line = function(line_num, spotter_args, opts, cursor_pos)
local allowed = opts.allowed_lines
-- Adjust for cursor line
local cur_line = cursor_pos[1]
if
(not allowed.cursor_before and line_num < cur_line)
or (not allowed.cursor_at and line_num == cur_line)
or (not allowed.cursor_after and line_num > cur_line)
then
return {}
end
-- Process folds
local fold_indicator = vim.fn.foldclosed(line_num)
if fold_indicator ~= -1 then return (allowed.fold and fold_indicator == line_num) and { 1 } or {} end
-- Process blank lines
if vim.fn.prevnonblank(line_num) ~= line_num then return allowed.blank and { 1 } or {} end
-- Finally apply spotter
return opts.spotter(line_num, spotter_args)
end
-- Jump state -----------------------------------------------------------------
H.advance_jump = function(opts)
local label_tbl = vim.split(opts.labels, '')
local spots = H.cache.spots
local n_steps_ahead = opts.view.n_steps_ahead
if type(spots) ~= 'table' or #spots < 1 then
H.spots_unshow(spots)
H.cache.spots = nil
return
end
local key = H.getcharstr('Enter encoding symbol to advance jump')
if vim.tbl_contains(label_tbl, key) then
0