How do I inspect all syntax highlight groups stacked under the cursor to debug colorscheme or syntax issues?
Answer
:echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')
Explanation
When syntax highlighting looks wrong or a colorscheme override isn't taking effect, you need to know exactly which highlight groups are active under the cursor. The synstack() function returns a list of all syntax group IDs at a given position (innermost first), and combining it with synIDattr() and map() gives you the human-readable group names — all in one command.
How it works
line('.')— the current line numbercol('.')— the current column numbersynstack(line, col)— returns a list of syntax IDs active at that position (deepest/innermost first)synIDattr(id, 'name')— converts a syntax ID to its group namemap(list, expr)— applies the expression to each element of the list:echo— prints the resulting list of group names
The output looks like: ['goFunction', 'goFunctionCall', 'Function'] showing all the stacked groups from deepest to shallowest.
Example
With the cursor on a function call in a Go file:
:echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')
['goFunctionCall', 'goFunction']
Now you know to override goFunctionCall or goFunction in your colorscheme.
Tips
- Map this to a key for easy repeated inspection:
nnoremap <F10> :echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')<CR> - Use
synIDattr(synID(line('.'), col('.'), 1), 'name')to get just the effective (resolved) highlight group - In Neovim 0.9+,
:Inspectdoes this visually —synstack()works in both Vim and Neovim - Get the linked-to group with
'fg#'or'bg#'attrs:synIDattr(synIDtrans(synID(line('.'),col('.'),1)), 'fg#')