-
Notifications
You must be signed in to change notification settings - Fork 4
feat: add virtual text counter display #9
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
base: main
Are you sure you want to change the base?
Changes from all commits
54df939
9a2c688
a83a906
58e1c96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| local M = {} | ||
|
|
||
| ---Namespace for counter virtual text extmarks | ||
| local counter_namespace = vim.api.nvim_create_namespace('RefjumpCounter') | ||
|
|
||
| ---Name of the highlight group for the counter | ||
| local counter_hl_name = 'RefjumpCounter' | ||
|
|
||
| ---Create highlight group linked to WarningMsg if it doesn't exist | ||
| function M.create_hl_group() | ||
| local hl = vim.api.nvim_get_hl(0, { name = counter_hl_name }) | ||
|
|
||
| if vim.tbl_isempty(hl) then | ||
| vim.api.nvim_set_hl(0, counter_hl_name, { link = 'WarningMsg' }) | ||
| end | ||
| end | ||
|
|
||
| ---Show virtual text counter at the end of the current line | ||
| ---@param current_index integer Current reference index (1-based) | ||
| ---@param total_count integer Total number of references | ||
| ---@param bufnr integer Buffer number | ||
| function M.show(current_index, total_count, bufnr) | ||
| -- Get current cursor position | ||
| local cursor = vim.api.nvim_win_get_cursor(0) | ||
| local line = cursor[1] - 1 -- Convert to 0-indexed | ||
|
|
||
| -- Clear any existing counter in this buffer | ||
| M.clear(bufnr) | ||
|
|
||
| -- Format the counter text | ||
| local text = string.format(' [%d/%d]', current_index, total_count) | ||
|
|
||
| -- Add virtual text at end of line | ||
| vim.api.nvim_buf_set_extmark(bufnr, counter_namespace, line, 0, { | ||
| virt_text = { { text, counter_hl_name } }, | ||
| virt_text_pos = 'eol', | ||
| priority = 100, | ||
| }) | ||
| end | ||
|
|
||
| ---Clear counter virtual text from buffer | ||
| ---@param bufnr integer Buffer number (0 for current buffer) | ||
| function M.clear(bufnr) | ||
| bufnr = bufnr or 0 | ||
| vim.api.nvim_buf_clear_namespace(bufnr, counter_namespace, 0, -1) | ||
| end | ||
|
|
||
| return M |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,6 +41,12 @@ function M.enable(references, bufnr) | |
| highlight_references = true | ||
| end | ||
|
|
||
| ---Check if reference highlights are currently active | ||
| ---@return boolean | ||
| function M.is_active() | ||
| return highlight_references | ||
| end | ||
|
|
||
| ---@deprecated Use `disable()` instead | ||
| function M.disable_reference_highlights() | ||
| local message = 'refjump.nvim: `disable_reference_highlights()` has been renamed to `disable()`' | ||
|
|
@@ -51,6 +57,8 @@ end | |
| function M.disable() | ||
| if not highlight_references then | ||
| vim.api.nvim_buf_clear_namespace(0, highlight_namespace, 0, -1) | ||
| require('refjump.counter').clear(0) | ||
| require('refjump.state').clear() | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The state shouldn't be cleared here, right? If the user just wants to disables the highlights, they might still want to repeat the same reference jump with demicolon.nvim, and so in that case it's still useful to reuse the state You'll then have to change your statusline example in the README to use the |
||
| else | ||
| highlight_references = false | ||
| end | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,12 +9,16 @@ local M = {} | |
| ---@field enable? boolean Highlight the LSP references on jump | ||
| ---@field auto_clear boolean Automatically clear highlights when cursor moves | ||
|
|
||
| ---@class RefjumpCounterOptions | ||
| ---@field enable? boolean Show virtual text counter at end of line | ||
|
|
||
| ---@class RefjumpIntegrationOptions | ||
| ---@field demicolon? { enable?: boolean } Make `]r`/`[r` repeatable with `;`/`,` using demicolon.nvim | ||
|
|
||
| ---@class RefjumpOptions | ||
| ---@field keymaps? RefjumpKeymapOptions | ||
| ---@field highlights? RefjumpHighlightOptions | ||
| ---@field counter? RefjumpCounterOptions | ||
| ---@field integrations? RefjumpIntegrationOptions | ||
| ---@field verbose? boolean Print message if no reference is found | ||
| local options = { | ||
|
|
@@ -27,6 +31,9 @@ local options = { | |
| enable = true, | ||
| auto_clear = true, | ||
| }, | ||
| counter = { | ||
| enable = true, | ||
| }, | ||
| integrations = { | ||
| demicolon = { | ||
| enable = true, | ||
|
|
@@ -55,8 +62,17 @@ function M.setup(opts) | |
| require('refjump.highlight').auto_clear_reference_highlights() | ||
| end | ||
| end | ||
|
|
||
| if options.counter.enable then | ||
| require('refjump.counter').create_hl_group() | ||
| end | ||
| end | ||
|
|
||
| M.reference_jump = require('refjump.jump').reference_jump | ||
|
|
||
| ---Get info about current reference position (for statusline use) | ||
| ---@param bufnr? integer Buffer number (defaults to current buffer) | ||
| ---@return { index: integer|nil, total: integer } | ||
|
Comment on lines
+73
to
+75
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need to repeat this documentation, it gets reused from the assigned |
||
| M.get_reference_info = require('refjump.state').get_reference_info | ||
|
|
||
| return M | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,6 +63,29 @@ local function jump_to(next_reference) | |
| vim.cmd('normal! zv') | ||
| end | ||
|
|
||
| ---Find the index of a reference in the references list | ||
| ---@param reference RefjumpReference | ||
| ---@param references RefjumpReference[] | ||
| ---@return integer|nil | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a very minor nit, but everywhere where you have |
||
| local function find_reference_index(reference, references) | ||
| local idx, _ = vim.iter(references):enumerate():find(function(_, ref) | ||
| return ref.range.start.line == reference.range.start.line | ||
| and ref.range.start.character == reference.range.start.character | ||
| end) | ||
| return idx | ||
| end | ||
|
|
||
| ---Display the reference counter if enabled | ||
| ---@param current_index integer | ||
| ---@param total_count integer | ||
| ---@param bufnr integer | ||
| local function show_counter(current_index, total_count, bufnr) | ||
| if not require('refjump').get_options().counter.enable then | ||
| return | ||
| end | ||
| require('refjump.counter').show(current_index, total_count, bufnr) | ||
| end | ||
|
|
||
| ---@param next_reference RefjumpReference | ||
| ---@param forward boolean | ||
| ---@param references RefjumpReference[] | ||
|
|
@@ -74,6 +97,15 @@ local function jump_to_next_reference(next_reference, forward, references) | |
|
|
||
| if next_reference then | ||
| jump_to(next_reference) | ||
|
|
||
| -- Find current index and update state | ||
| local current_index = find_reference_index(next_reference, references) | ||
| local bufnr = vim.api.nvim_get_current_buf() | ||
|
|
||
| if current_index then | ||
| require('refjump.state').set(references, current_index, bufnr) | ||
| show_counter(current_index, #references, bufnr) | ||
| end | ||
| else | ||
| vim.notify('refjump.nvim: Could not find the next reference', vim.log.levels.WARN) | ||
| end | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| local M = {} | ||
|
|
||
| ---@class RefjumpBufferState | ||
| ---@field references RefjumpReference[] | ||
| ---@field current_index integer|nil | ||
|
|
||
| ---Per-buffer state storage | ||
| ---@type table<integer, RefjumpBufferState> | ||
| local buffer_states = {} | ||
|
|
||
| ---Get or create state for a buffer | ||
| ---@param bufnr integer | ||
| ---@return RefjumpBufferState | ||
| local function get_buffer_state(bufnr) | ||
| if not buffer_states[bufnr] then | ||
| buffer_states[bufnr] = { | ||
| references = {}, | ||
| current_index = nil, | ||
| } | ||
| end | ||
| return buffer_states[bufnr] | ||
| end | ||
|
|
||
| ---Get info about current reference position (for statusline use) | ||
| ---@param bufnr? integer Buffer number (defaults to current buffer) | ||
| ---@return { index: integer|nil, total: integer } | ||
| function M.get_reference_info(bufnr) | ||
| bufnr = bufnr or vim.api.nvim_get_current_buf() | ||
| local state = get_buffer_state(bufnr) | ||
| return { | ||
| index = state.current_index, | ||
| total = #state.references, | ||
| } | ||
| end | ||
|
|
||
| ---Check if reference navigation is currently active | ||
| ---@return boolean | ||
| function M.is_active() | ||
| return require('refjump.highlight').is_active() | ||
| end | ||
|
Comment on lines
+36
to
+40
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps this method should be moved to |
||
|
|
||
| ---Update state after jumping to a reference (internal use) | ||
| ---@param references RefjumpReference[] | ||
| ---@param current_index integer|nil | ||
| ---@param bufnr? integer Buffer number (defaults to current buffer) | ||
| function M.set(references, current_index, bufnr) | ||
| bufnr = bufnr or vim.api.nvim_get_current_buf() | ||
| local state = get_buffer_state(bufnr) | ||
| state.references = references or {} | ||
| state.current_index = current_index | ||
| end | ||
|
|
||
| ---Clear state for a buffer (internal use) | ||
| ---@param bufnr? integer Buffer number (defaults to current buffer) | ||
| function M.clear(bufnr) | ||
| bufnr = bufnr or vim.api.nvim_get_current_buf() | ||
| buffer_states[bufnr] = nil | ||
| end | ||
|
|
||
| ---Clean up state when buffer is deleted | ||
| local function setup_buffer_cleanup() | ||
| vim.api.nvim_create_autocmd('BufDelete', { | ||
| group = vim.api.nvim_create_augroup('refjump_state_cleanup', { clear = true }), | ||
| callback = function(event) | ||
| buffer_states[event.buf] = nil | ||
| end, | ||
| }) | ||
| end | ||
|
|
||
| setup_buffer_cleanup() | ||
|
|
||
| return M | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| -- Minimal init for running tests | ||
| local plenary_path = vim.fn.stdpath('data') .. '/lazy/plenary.nvim' | ||
|
|
||
| if vim.fn.isdirectory(plenary_path) == 0 then | ||
| vim.fn.system({ | ||
| 'git', | ||
| 'clone', | ||
| '--depth=1', | ||
| 'https://github.com/nvim-lua/plenary.nvim', | ||
| plenary_path, | ||
| }) | ||
| end | ||
|
|
||
| vim.opt.rtp:prepend(plenary_path) | ||
| vim.opt.rtp:prepend(vim.fn.getcwd()) | ||
|
|
||
| vim.cmd('runtime plugin/plenary.vim') |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this conditional neccessary? Isn't this already covered by lines 3-4 in this file?