4

I've noticed in bash/shell it highlights $(...) in red, for example:

enter image description here

However, if I change the syntax from ft=sh to ft=bash, it does not do this:

enter image description here

What's the reason for this? Am I doing something wrong with the ft=sh, or why is that highlighted in red when it's a legitimate syntax construct?

2 Answers 2

5

This is because the original Bourne shell only understands `...` - the standard $( ... ) syntax was added later. From syntax/sh.vim:

" $() and $(()): {{{1
" $(..) is not supported by sh (Bourne shell).  However, apparently
" some systems (HP?) have as their /bin/sh a (link to) Korn shell
" (ie. Posix compliant shell).  /bin/ksh should work for those
" systems too, however, so the following syntax will flag $(..) as
" an Error under /bin/sh.  By consensus of vimdev'ers!

You can set the variable g:is_bash to tell the sh syntax file that sh is actually bash, if indeed it is actually bash (does sh --version show the Bash version?). Or you can set g:is_posix if sh is POSIX compliant.

7
  • This "consensus of vimdev'ers" comment can be traced back to a Vim 7.001 commit from back in 2004, so it's been around for over 15 years, maybe even more than twenty... Looks like back in 2008 people were already asking about it and someone objected because Solaris /bin/sh still wouldn't recognize it. Maybe in 2020 it's time to revert that already?
    – filbranden
    Jul 15, 2020 at 4:48
  • 1
    Looking at the manpage, that still seems to be the case for Oracle Solaris 11.1. Sigh. Maybe g:is_posix should be set by default and g:is_sh should be set only for systems with the broken sh.
    – muru
    Jul 15, 2020 at 4:57
  • Yeah... But is Solaris even relevant anymore? I thought even Oracle was mostly pushing Linux at this point...
    – filbranden
    Jul 15, 2020 at 5:04
  • 1
    I went through the discussions there and in bugs.debian.org/cgi-bin/bugreport.cgi?bug=361177, and I don't know if we have a compelling argument against "backwards compatibility" there. Think it's worth posting again on vim-dev?
    – muru
    Jul 15, 2020 at 7:52
  • 2
    @David542 so macOS, where /bin/sh is not a symlink to /bin/bash but a copy or hardlink, which is why it's not guessing correctly. Put let g:is_posix = 1 in your vimrc.
    – muru
    Jul 15, 2020 at 19:39
4

Shell originally used only backticks for command substitution:

less `find . -type f`

But these do not nest and suffer from other problems. Bash (and probably ksh, but I’m not up on the history there) used $() as a newer, improved command substitution.

But that explains the difference and why the filetype matters—in fact, the shebang (#! line) matters! If you use /bin/sh, you should only use POSIX sh features. Otherwise, use the path to a known interpreter and use it’s features.

As pointed out in the comments, POSIX allows the newer command substitution, so it should be safe even in sh scripts.

3
  • 1
    $( ... ) is perfectly fine for POSIX. (See, e.g, even the older versions of the standard.)
    – muru
    Jul 15, 2020 at 3:30
  • How should I fix this then? Should I set an autocommand that if ft=sh set ft=bash ?
    – David542
    Jul 15, 2020 at 19:11
  • 1
    @David542 try :let g:is_bash = 1 in your vimrc—:help ft-sh-syntax
    – D. Ben Knoble
    Jul 15, 2020 at 19:12

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.