My purpose is to get information which would explain why the region under cursor has that particular color. Yes, there are several very similar questions, but still my question is different.

I can get required information "manually". For example, in python file the color of a string is red. Ok, I navigate to the string and enter following commands (text after -> is a result and my comment):

:lua=vim.fn.synID(vim.fn.line("."), vim.fn.col("."), 0)    -> 550, this is id of syntax
:lua=vim.fn.synIDattr(550, 'name')                         -> "pythonString"

(I use neovim, if you use vim you can call these functions using approach described here: How to know which highlighting group is used for the background of a word?)

Ok, so the name of syntax region is "pythonString". Now I can find out the highlight group associated with this syntax group:

:highlight pythonString         -> "pythonString   xxx links to String"
:highlight String               -> "String         xxx links to Constant"
:highlight Constant             -> "Constant       xxx ctermfg=217"

and here it is, color 217 is the color used to display the string.

Now I want to automate last steps. I want to call some function from my script which would find out that syntax #550 ("pythonString") is linked to highlight group "String".

I try to use synIDtrans for this purpose:

:lua=vim.fn.synIDtrans(550)          -> 73
:lua=vim.fn.synIDattr(73, 'name')    -> "Constant"

Here is the problem: vim.fn.synIDtrans reports that "pythonString" is linked to highlight group "Constant", not to "String".

I guess this is by design. Help for synIDtrans says:

Highlight links given with ":highlight link" are followed.

Is there any workaround for this behavior? I want my script to report the full chain of links: "pythonString" -> "String" -> "Constant".


  1. I guess numeric ids of the highlight groups may be different on your installation.
  2. Highlight region id returned by synIDtrans depends on current colorscheme (!!!). If in your colorscheme the "String" is not linked to anything, the method would return id of "String" highlight group as expected.
  • Are you using Treesitter? May 8, 2023 at 4:09
  • @VivianDeSmedt, yes, I have treesitter installed. But I do not think it is important. Treesitter can help to identify the syntax region - and it is identified correctly. But I want to get a chain of highlight groups corresponding to this syntax region.
    – lesnik
    May 8, 2023 at 11:45

1 Answer 1


I had difficulty like you.
I wrote a user_create_function to workaround by lua.

ShowRootHighlightUnderCursor trace link and show "root" highlight group, even if many time link.

try this.

vim.api.nvim_create_user_command('ShowRootHighlightUnderCursor', function()
    local function findRoot(id, tree)
        local transId = vim.fn.synIDtrans(id)
        local name = vim.fn.synIDattr(id, 'name')
        table.insert(tree, name)

        if id == transId then
            print(table.concat(tree, ' -> '))
            findRoot(transId, tree)

    local id = vim.fn.synID(vim.fn.line("."), vim.fn.col("."), 0)
    findRoot(id, {})
end, {})


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.