如何在Vim ftdetect脚本中放置文件类型语法定义?
问题原因
可以直接在.vim/ftdetect脚本中编写语法定义,无需单独创建syntax目录下的独立语法文件。autocmd FileType vimjournal绑定语法规则不生效是Vim事件触发顺序与语法加载机制导致的,和ftdetect能否承载语法定义无关:
- 旧写法
autocmd BufRead *.log可正常生效,原因是BufRead事件触发时,文件类型检测、缓冲区语法初始化流程已全部执行完成,后续添加的syn match规则不会被系统流程清空,因此可以正常高亮。但从标准输入读取内容时不存在.log后缀,无法匹配对应模式,规则自然不会加载。 FileType事件触发阶段,Vim会优先执行内置语法加载逻辑:先清空当前缓冲区已有语法规则,再尝试加载对应文件类型的syntax文件。ftdetect脚本中注册的FileType自动命令优先级低于内置语法加载流程,自定义syn match执行后要么被后续的语法清空操作覆盖,要么因缓冲区未标记完成语法加载导致规则不生效。- 同脚本内其他
FileType相关配置可正常运行,是因为这类配置多为setlocal类的选项设置,不属于语法规则范畴,不会被语法加载流程重置。
解决方案
无需拆分文件,按如下逻辑修改ftdetect脚本即可,保留单软链接安装的能力:
- 补全标准输入场景的文件类型检测逻辑,确保读取.log后缀文件、从标准输入读入内容、手动执行
:set filetype=vimjournal三种场景都能正确设置文件类型 - 注册语法规则前先为当前缓冲区设置
b:current_syntax变量,告知Vim对应语法已加载完成,阻断默认的语法清空、加载外置syntax文件的流程 - 自定义语法组增加文件类型前缀,避免和其他语法文件的组名冲突,最后通过高亮链接关联到Vim默认高亮组即可
参考实现代码:
" 文件类型检测:覆盖本地文件与标准输入场景 augroup vimjournal_detect autocmd! autocmd BufRead,BufNewFile *.log set filetype=vimjournal autocmd StdinReadPre * let s:stdin_vimjournal = 1 autocmd StdinReadPost * if exists('s:stdin_vimjournal') | set filetype=vimjournal | unlet s:stdin_vimjournal | endif augroup END " 语法规则绑定 augroup vimjournal_syntax autocmd! autocmd FileType vimjournal \ let b:current_syntax = 'vimjournal' | \ syn match vimjournalHeading '^## .*$' | \ syn match vimjournalComment '^//.*$' | \ highlight default link vimjournalHeading Heading | \ highlight default link vimjournalComment Comment augroup END
配置完成后所有场景下均可正常触发对应语法高亮。
内容的提问来源于stack exchange,提问作者Roger Keays
相关产品推荐
相关产品推荐

