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: allow more completion highlight control #1972

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

dmun
Copy link

@dmun dmun commented Jun 30, 2024

Related: #1887

This PR allows more highlight control by allowing vim.CompletedItem.{field}_hl_group values to be of type table with the following structure:

-- inside the cmp.FormattingConfig.format method
vim_item.abbr_hl_group = {
    { '@function', range = { 0, 5 } },
    { 'Comment', range = { 5, 10 } },
}

Examples

Simple

A simple use case of this is having different highlights for function parameters:

image
Code
local format = function(entry, vim_item)
    local kind = entry:get_kind()

    if vim.tbl_contains({ 2, 3 }, kind) then -- if kind is a Function (2) or Method (3)
        local start_index, end_index = vim_item.abbr:find('%(.*')
        if start_index then
            vim_item.abbr_hl_group = {
                { '@function', range = { 0, start_index - 1 } },
                { 'Comment', range = { start_index - 1, end_index } },
            }
        else
            vim_item.abbr_hl_group = '@function'
        end
    end

    return vim_item
end

Treesitter-based

You can also have more complex highlights by using treesitter for example:

image
Code (borrowed from @xzbdmw)
format = function(entry, vim_item)
    local highlights = {}

    -- you will likely not want to get this query every single time for performance but this is an example
    local query = vim.treesitter.query.get(vim.bo.filetype, 'highlights')

    local success, parser = pcall(vim.treesitter.get_string_parser, str, vim.bo.filetype)
    if success then
        local tree = parser:parse(true)[1]
        local root = tree:root()
        for id, node in query:iter_captures(root, str, 0, -1) do
            local name = '@' .. query.captures[id] .. '.' .. vim.bo.filetype
            local hl = vim.api.nvim_get_hl_id_by_name(name)
            local range = { node:range() }
            local _, nscol, _, necol = range[1], range[2], range[3], range[4]

            table.insert(highlights, { hl, range = { nscol, necol } })
        end
    end

    vim_item.abbr_hl_group = highlights

    return vim_item
end,

Notes

LSP doesn't specify exactly how to use the label fields of a CompletionItem, as a result the usage of these values differ a lot between LSP implementations (see table below). This makes getting syntactically correct function signatures inconsistent across different LSP implementations.

LS label detail labelDetails.detail labelDetails.description
lua_ls require(modname) function - -
zls addManyAt fn (self: *Self, index: usize, count: usize) Allocator.Error![]T (index: usize, count: usize) Allocator.Error![]T
rust-analyzer find_map(…) fn(&mut self, F) -> Option<B> (as Iterator) fn(&mut self, F) -> Option<B>

I don't think nvim-cmp should be responsible for properly formatting/highlighting the function signatures. Instead, that logic should be configurable by the user, or delegated to some other plugin in similar style of lspkind-nvim.

Suggestions are very welcome!

@xzbdmw
Copy link

xzbdmw commented Jul 1, 2024

That’s much simpler in cmp side👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants