The neovim syntax for shell scripts doesn't check if keywords like echo, done, exit etc.. are surrounded by blank spaces or if they're part of a bigger Word.

This results in the following bad highlighting

enter image description here

How can I patch it? I know I probably need to create a file in ~/.config/nvim/after/syntax/sh.vim, but what should I put inside it?

  • It looks like the syntax in nvim for the sh.vim might be using the syn keyword echo, which matches the keywords specified and has the highest highlighting priority. I would try adding syn match TestKeyword "\s*echo\s\+" and then add hi def link TestKeyword Comment and see if that helps. I tried to reproduce in ViM and couldn't.
    – Vee
    Dec 15 '20 at 19:43
  • That leaves echo_foo as it is in the screenshot, while echo gets the same highlighting as comments.
    – noibe
    Dec 15 '20 at 20:31

This behavior is happening because your 'iskeyword' did not include "_" as a valid keyword character when the syntax was first loaded.

The syntax for sh (among many other languages) use the :syn keyword command to define syntax based on keywords, and where the keywords are recognized (regarding the delimiters around them) depends on the 'iskeyword' setting by default.

To track down where "_" was removed from 'iskeyword', you can find where it was last set with the following command:

:verbose set iskeyword?

This should show you the current setting (where you'll notice it's missing _ in the list) and also the file and line number of the script where it was last set (which hopefully will be the place where _ was removed.)

If you fix it back with :set iskeyword+=_, you'll still have to reload the syntax (easiest is by using :set ft=sh) for it to highlight the keywords correctly.

There is also a :syn iskeyword command to override the global 'iskeyword' settings when interpreting syntax keyword elements.

The syntax file for filetype=sh does set a specific :syn iskeyword (thanks @ChristianBrabandt for pointing it out!) But it uses the value of the 'iskeyword' setting in its definition. (It uses the :syn iskeyword command to add - and : to a keyword definition for syntax purposes.)

You can override the :syn keyword definition by creating a new syntax/sh.vim file in your local Vim after/ directory (~/.vim/after/syntax/sh.vim, or ~/config/nvim/after/syntax/sh.vim for NeoVim), with the following line in its contents:

syntax iskeyword @,48-57,_,192-255,-,:

This hardcodes the default 'iskeyword' settings, which include the "_" as a keyword character, and also includes the modifications of the shipped syntax for sh which adds - and :.

  • Is there a way to let iskeyword contain _ while at the same time considering _ as a word delimiter (I'd like to stop at _ when I press w).
    – noibe
    Dec 15 '20 at 21:43
  • Thanks! I fixed it by adding syntax iskeyword @,48-57,192-255,_,- to ~/.config/nvim/after/syntax/sh.vim.
    – noibe
    Dec 15 '20 at 22:05
  • 1
    the recommended way for runtime syntax plugins is to use :syn iskeyword setting and do not mess with the 'iskeyword' option. Because it doesn't mess with word motions etc. Any syntax file that still uses the old version of setting the 'iskeyword' option, should be fixed Dec 16 '20 at 8:09
  • 1
    @filbranden it looks like the syntax script does setup the syn iskeyword thing: github.com/vim/vim/blob/… is that wrong? Dec 16 '20 at 15:35
  • 1
    @filbranden I see. Will contact Charles Dec 16 '20 at 16:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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