在没有有效文件扩展名的情况下在vim中检测文件类型

6
我正在寻找一种方法来确定vim文件的文件类型,并根据文件类型设置语法高亮。唯一的问题是,我不能使用文件扩展名来确定文件类型。
我的情况是:我使用vimdiff或gvimdiff作为我的P4DIFF工具,它显示了我本地副本中的文件与来自Perforce服务器的文件之间的更改。Perforce似乎将文件从Perforce服务器带入/tmp目录并使用PID命名文件,例如:
/tmp/tmp.24673.23

这是一个C++源文件。

在perforce代码库中,我经常遇到的文件类型包括C/C++源文件和头文件、Makefile、Python脚本、Perl脚本、Ruby脚本和Tcl脚本。

  • 我尝试使用modeline,但我们的代码库中大部分源文件都没有嵌入此信息。

  • 这篇文章提到了一种可能的方法来搜索和识别魔术模式。但我无法找到任何一致的魔术模式,能够得到高成功率。

  • 我尝试在我的Linux机器上使用file二进制文件来查看结果。它似乎可以很好地识别C/C++源文件,但对于Makefile甚至Python脚本(它们没有hashbang),则失败了。

好的一点是,在比较的两个文件中,右侧的文件来自我的本地副本,因此具有正确的文件名和扩展名,因此对于右侧的文件启用了正确的语法突出显示。

有没有办法利用这一点来设置左侧显示的文件相同的语法突出显示?

对于这个问题的任何替代解决方案也欢迎。

2个回答

6
这是一个有趣的谜题。 :)
aug SmartDiffType
  au!
  au VimEnter * :if &diff && len(&ft) | call setwinvar(2/winnr(),'&ft',&ft) | elseif &diff | let &ft=getwinvar(2/winnr(),'&ft') | endif
aug END

注:

  • 上述的四行中,您只需要 需要 au VimEnter 行,但通常最好将自动命令放在一些自动命令组中,并在顶部进行重置(au!)。
  • VimEnter 上设置自动命令,否则 diff 或窗口尚未正确初始化
  • vimdiff 可能已触发右侧或左侧的旧文件,因此我们考虑两种情况。
  • 2/winnr() 是一种数学技巧,用于在 1 和 2 之间翻转(2/2 = 1,2/1=2)

太棒了!这个真的很好用...只需将if-endif移入一个函数中,并用函数调用替换命令即可。 :) - Tuxdude

3

假设你只打开了两个split,而左边的split是你的本地文件,那么你可以按照以下步骤操作:

:windo let &ft = getwinvar(1, '&ft')

这将为所有窗口设置filetype的值为左上角最上面窗口的值。

更多帮助请参见:

:h :windo
:h 'ft'
:h getwinvar(

谢谢,它有效。我不得不使用windo let &ft = getwinvar(2, '&ft'),因为右窗口有正确的文件类型。是否有一种方法将其添加到.vimrc中,以便对于每个vimdiff,它都会自动执行此操作?仅将windo命令添加到.vimrc中并没有起作用。我猜它可能会被后面的内容覆盖。 - Tuxdude
虽然我确信可以创建这样一个“autocmd”,但我觉得最简单的解决方案是创建自定义命令:“command!-bar -nargs = 0 SameFiletype exe 'windo set ft ='。&ft”将其添加到您的“~ / .vimrc”文件中。下次出现这种情况时,移动到具有正确文件类型的缓冲区并执行“:SameFiletype”。 - Peter Rincker
谢谢,那听起来是个合理的方法 :) - Tuxdude

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接