Vim语法不一致地突出显示bash文件

Vim语法不一致地突出显示bash文件,vim,syntax-highlighting,vim-syntax-highlighting,Vim,Syntax Highlighting,Vim Syntax Highlighting,当我用vim打开一些bash脚本文件时,它有时会将它们标识为conf文件,没关系,我可以通过使用:setf sh将文件类型设置为sh来纠正这一点 太好了,不过我注意到这并不能完全解决问题: 请注意,shopt在左侧正确高亮显示,但在右侧没有,我在右侧手动将文件类型设置为sh 这意味着,当vim将文件标识为bash或sh时,它会将文件类型设置为sh,但随后会执行一些额外的步骤,这是我手动设置文件类型时没有执行的步骤 有人知道这可能是什么,以及我如何修复它吗?尝试查看有效的语法设置 :windo

当我用vim打开一些bash脚本文件时,它有时会将它们标识为
conf
文件,没关系,我可以通过使用
:setf sh
将文件类型设置为
sh
来纠正这一点

太好了,不过我注意到这并不能完全解决问题:

请注意,
shopt
在左侧正确高亮显示,但在右侧没有,我在右侧手动将文件类型设置为
sh

这意味着,当vim将文件标识为
bash
sh
时,它会将文件类型设置为
sh
,但随后会执行一些额外的步骤,这是我手动设置文件类型时没有执行的步骤


有人知道这可能是什么,以及我如何修复它吗?

尝试查看有效的语法设置

:windo echo b:current_syntax
(我希望第一个窗口显示
bash
,第二个窗口显示
sh
。)

还可以尝试使用synatx同步:

:windo syn sync fromstart
:windo syn sync minlines=300
大体上

:he syn-sync
更多信息


附言 长镜头,但其他一些突出显示可能会干扰:

:windo se @/=''
:match none
:2match none
:3match none

事实证明,
syntax/sh.vim
包括对KornBashsh的特定突出显示,您只需告诉它您正在使用哪个。这分别通过
b:is_kornshell
b:is_bash
b:is_sh
完成

根据具体情况,我想我将使用以下方法:

ftdetect/bash.vim: 模型线: 键映射
nmap b:let g:is_bash=1:setf sh

默认情况下,vim已经识别了许多文件类型。它们中的大多数都是通过文件扩展名工作的,但在这种情况下,vim还将分析文件的内容以猜测正确的类型

vim自动为特定文件名设置文件类型,如
.bashrc
.tcshrc
等。但是扩展名为
.sh
的文件将被识别为csh、ksh或bash脚本。为了确定这到底是什么类型的脚本,vim读取文件的第一行以查看#!线路

如果第一行包含单词
bash
,则该文件被标识为bash脚本。通常你会看到
#/bin/bash
如果要直接执行脚本,那么对于其他一些shell配置文件,应该使用文件扩展名
.bash


vim中的帮助在
:help ft bash syntax
中也解释了这一点。您还可以在.vimrc中使用
let g:is_bash=1
使bash语法突出显示所有文件的默认值
filetype=sh
。如果您想查看详细信息,这是在
$VIMRUNTIME/filetype.vim

中实现的,类似于Peter Coulton的解决方案,并在“filetype”vim帮助的“new filetype”部分中记录了该解决方案。
~/.vim/filetype.vim
文件可能包含以下代码:

if exists("did_load_filetypes")
  finish
endif

augroup filetypedetect
  au! BufRead,BufNewFile *bash* let b:is_bash = 1 | setfiletype sh
augroup END
这种方法具有以下含义:

  • ~/.vim/ftdetect
    目录下,每个文件类型都有一个
    ~/.vim/filetype.vim
    文件,而不是一个
  • 通过将
    b:is\u bash
    变量称为
    g:is\u bash
    将其设置为缓冲区的本地变量,而不是全局变量

  • +1个甜点!modeline方法将是我的最爱。(如果我真的很在意这样的小偏差:)@Peter Coulton:你不是想将
    b:is_bash
    变量设置为缓冲区的局部变量,而不是
    g:is_bash
    变量的全局变量吗。至少您的代码片段没有反映这种情况。您还可以将两个
    au
    命令连接在一起,方法是在第一个命令末尾加上
    let b:is_bash=1 | setfiletype sh
    。我不认为每次加载文件名为“bash”的文件时设置全局值有什么好处,而只需在
    中设置一次.vimrc
    并完成它。不幸的是,在这个用例中,无法在modeline.Non-ideal中设置变量。全局启用
    g:is_bash=1
    为所有非bash shell脚本缓冲区(例如Bourne、Korn)启用特定于bash的语法高亮显示,这很糟糕。本地启用
    b:is_bash=1
    是非常可取的。同样,每个文件类型
    ftdetect/
    文件在很大程度上已被统一所有文件类型检测的单个
    filetype.vim
    文件淘汰。对于解决这两个问题的解决方案,请参阅。我将此标记为答案,因为它很好地解释了原因,并提供了一个完全合理的解决方案。我还添加了一个答案,详细说明了我自己的解决方案。虽然介绍性概要很有帮助,但给出的解决方案(例如,
    .vimrc
    中的
    let g:is_bash=1
    )没有帮助。为什么?因为这样做会强制非Bash shell脚本缓冲区(例如,Bourne、Korn)使用Bash特定的语法高亮显示。换个角度考虑。@ CeCulCury,这就是为什么我添加了一个公平的警告,它会影响到每个文件的<代码>文件类型= SH < /代码>。实际上,我刚刚复制了
    :help ft bash syntax
    建议添加到
    .vimrc
    中的内容,以使其成为全局默认值。它不会对所有shell文件强制使用此语法。一个更具体的shebang,比如
    #/bin/ksh
    仍将覆盖此默认选择,因此我无法重现您的担忧。
    # vim:let g:is_bash=1:set filetype=sh:
    
    nmap <silent> <leader>b :let g:is_bash=1<cr> :setf sh<cr> 
    
    if exists("did_load_filetypes")
      finish
    endif
    
    augroup filetypedetect
      au! BufRead,BufNewFile *bash* let b:is_bash = 1 | setfiletype sh
    augroup END