neoclide / coc.nvim

Nodejs extension host for vim & neovim, load extensions like VSCode and host language servers.
Other
24.15k stars 953 forks source link

Move across symbol usage highlights #4951

Closed asmodeus812 closed 3 months ago

asmodeus812 commented 3 months ago

Is your feature request related to a problem? Please describe. It would be great if along with the usage / symbol highlight action we can actually move between the highlighted symbols, and while we move with next_/prev_usage the highlights should not be cleared

Describe the solution you'd like Have an interface with next_usage / prev_usage that triggers the highlight for the current symbol under the cursor, if not already triggered, moves to the prev/next/first/last usage and does not clear the highlights while the user moves with next/prev usage api. (e.g. if we have them bound to ]r and [r)

Describe alternatives you've considered It could be possible to use the response of highlight, to resolve where the next and prev positions are.

Additional context None

asmodeus812 commented 3 months ago

Probably not worth the effort, one could simply fetch the symbol ranges and do something simple like that, for future reference to whoever comes around this issue of moving to next/prev usage in the buffer

local function lsp_moveto_usage(dir, pin)
    usages = vim.tbl_map(function(r)
        return {
            start = { row = r.start.line, col = r.start.character },
            finish = { row = r["end"].line, col = r["end"].character },
        }
    end, vim.fn.CocAction("symbolRanges") or {})

    local cursor = vim.api.nvim_win_get_cursor(0)
    local row = cursor[1] - 1; local col = cursor[2]

    local oldignore = vim.o.eventignore
    vim.o.eventignore = "CursorMoved"

    usages = usages.result -- usages
    for idx, pos in ipairs(usages) do
        local new_position = nil
        if dir > 0 and pin == 1 then
            new_position = usages[#usages]
        elseif dir < 0 and pin == 1 then
            new_position = usages[1]
        elseif row >= pos.start.row and row <= pos.finish.row and col >= pos.start.col and col <= pos.finish.col then
            if dir < 0 and idx == 1 then
                new_position = usages[#usages]
            elseif dir > 0 and idx == #usages then
                new_position = usages[1]
            else
                new_position = usages[idx + dir]
            end
        end

        if type(new_position) == "table" then
            vim.cmd.normal({ args = { "m'" } }) -- remember pos into the jumplist
            local new_cursor = { new_position.start.row, new_position.start.col }
            vim.api.nvim_win_set_cursor(0, { new_cursor[1] + 1, new_cursor[2] })
            vim.cmd.normal({ args = { "m'" } }) -- remember pos into the jumplist
            break
        end
    end

    vim.schedule(function()
        -- optionally highight also
        vim.o.eventignore = oldignore
    end)
end