5

We can get highlight group information by the following command

:hi[ghlight] {group-name}

But is it possible to get this information by given keyword? Something like this :

syn match Integer '\d\+'
hi def link Integer Constant

:hi '3'
Integer xxx links to Constant
1

2 Answers 2

13

If I understand your question correctly, it's not possible to do exactly what you're asking. Vim needs the items to be in their correct context in order to determine what highlighting applies to them.

However, you can ask Vim what syntax items are currently being applied. See the example at the end of :help synID():

:echo synIDattr(synID(line("."), col("."), 1), "name")

This will output the name of the syntax item under the cursor. So instead of typing :hi '3', you'd find a 3 in your current, syntax-highlighted buffer (or add one), place the cursor on it, and run the command.

To obtain the highlighting information, you can slot the above into a :highlight command:

execute 'hi' synIDattr(synID(line("."), col("."), 1), "name")

If your purpose is debugging syntax highlighting, then you will also find the example in :help synstack() useful. I have a little wrapper command in my .vimrc containing that code so I can check syntax items quickly:

function! s:syntax_query() abort
  for id in synstack(line("."), col("."))
    echo synIDattr(id, "name")
  endfor
endfunction
command! SyntaxQuery call s:syntax_query()

You can modify the echo line similarly, if you want this also to display highlighting info:

execute 'hi' synIDattr(id, "name")
2
  • Thank you, it's really helpful. You guessed it, I was looking for a way to debug syntax highlighting, but I didn't explain it well. Commented May 3, 2018 at 0:23
  • This answer works perfectly. I added your first codeblock to my personal vimrc! Commented Jan 21, 2020 at 18:00
4

Based on Rich answer and Drew Neil’s vimcast, one can:

A: To just read the syntax file ~/.vim/after/syntax/<filetype>.vim.

nnoremap <leader>z :call <SID>SyntaxStack()<CR>

Or B: modify syntax file appending the highlight settings of groups under cursor

nnoremap <leader>z! :call <SID>SyntaxStack(1)<CR>

A picture is worth a thousand words. Up screenshot is previous to executing the map, down the result: enter image description here

Next more complex mappings to highlight groups. With groups under cursor searched (to search for less groups, just press / - up-arrow and modify it). Mappings are more complex because 1st I must open a buffer, and then search in it, so it cannot be all in same function. Actually, cause I cannot achieve getting the return of this <SID> function directly in the mapping, my workaround is that this function must add a global variable g:str2Search_SyntaxStack, which the mapping reads.

A:

nnoremap <leader>z :call <SID>SyntaxStack()<CR>:let g:var02=':silent execute "normal /' . g:str2Search_SyntaxStack . '\' .'<' .'CR' .'>"'<CR>:execute(g:var02)<CR>:echo "Searched: ". substitute(g:str2Search_SyntaxStack, '\\\\\\', '\', 'g')<CR>

B:

nnoremap <leader>z! :call <SID>SyntaxStack(1)<CR>:let g:var02=':silent execute "normal /' . g:str2Search_SyntaxStack . '\' .'<' .'CR' .'>"'<CR>:execute(g:var02)<CR>:echo "Searched: ". substitute(g:str2Search_SyntaxStack, '\\\\\\', '\', 'g')<CR><CR>

where <SID>SyntaxStack() function:

function! <SID>SyntaxStack(append_to_file_bool=0)
  if !exists("*synstack")
    return
  endif

  let l:str2Search=List_to_strings_to_search(map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")'), 1)

  let l:file__after_syntax=Get_file__after_syntax()

  " read current highlight for <group> under cursor
  " and append to syntax file
  if (a:append_to_file_bool)
    for l:syntaxID in synstack(line("."), col("."))
      let l:hi_group=execute('hi ' . synIDattr(l:syntaxID, "name"))
      let l:hi_group=substitute(l:hi_group, "\n", '', 'g') " remove new lines 
      let l:hi_group=substitute(l:hi_group, "xxx", '', 'g') " remove 'xxx' added to show highlight settings default (I think)
      let l:hi_group="highlight " . l:hi_group
      if l:hi_group =~ "clear"
        " if cleared (noone should) from colorscheme plugin, then comment line before appending
        let l:hi_group= '" ' . l:hi_group
      endif
      call writefile([l:hi_group], l:file__after_syntax, "a")
    endfor
  endif

 " 1st I must open a buffer, and then search in it, so it cannot be all in same function
 " therefore, I need a global variable to return from an <SID> fcn
 let g:str2Search_SyntaxStack=l:str2Search

  " open syntax file with last syntaxID highlighted
  execute ":tabnew " . l:file__after_syntax

endfunc

And auxiliary functions:

function! List_to_strings_to_search(list01,slash_double_bool=0)
  " https://vim.fandom.com/wiki/Search_patterns#Finding_this_or_that
  let str01=""
  let cnt01=0
  let list01_len=len(a:list01)
  for l:str02 in a:list01
    let l:cnt01+=1
    " remove single quotes
    let l:str03=substitute(l:str02, "'", '', 'g')
    let l:str01=l:str01 . l:str03
    if l:cnt01 < l:list01_len
        if (a:slash_double_bool)
          let l:str01=l:str01 . '\\\' .'|'
        else
          let l:str01=l:str01 . '\' .'|'
        endif
    endif
  endfor
  return l:str01
endfunc

function! Get_filetype()
  let l:filetype_str=&filetype  " get filetype
  let l:filetype_str=substitute(string(l:filetype_str), "'", '', 'g') " remove single quotes
  return l:filetype_str
endfunc
function! Get_file__after_syntax()
  let l:filetype_str=Get_filetype()
  let l:file__after_syntax=expand('~/.vim/after/syntax/' . l:filetype_str . '.vim') " expand() to avoid tilde errors
  return l:file__after_syntax
endfunc
4
  • Hi @Ben, shall we remove this answer, since my new one is more modular and achieves more? Commented Dec 27, 2020 at 20:50
  • 1
    Actually, after a quick glance, the "new" one should have been an edit. Removing this one would actually cost you the rep from the up-votes. (I cannot merge them.) The simplest course of action would to be edit this post and put the new answer there (you can even leave the original details if they're relevant). Then you (or I) can delete the other.
    – D. Ben Knoble
    Commented Dec 27, 2020 at 23:37
  • I did just that, edited this answer and pasted verbatim from the other one, then deleted that one... I hope that's ok with you!
    – filbranden
    Commented Dec 28, 2020 at 4:36
  • Thanks both! All is fine for me now. Commented Dec 28, 2020 at 8:19

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.