Vim 在编辑 html 文件时意外地使用 javascript 缩进文件类型插件
Vim unexpectedly sources javascript indent filetype plugin on editing html files
TL;DR:vim 似乎在编辑 html 文件时同时采购 indent/javascript.vim
和 indent/html.vim
;这是故意的还是错误?我怎样才能使 html 文件仅源 html.vim
?
最近我发现 vim 似乎在编辑 html 文件时对 javascript 和 html 使用缩进文件类型插件,我做了一些基于此行为在最小 vim 配置上进行测试。
这是我的单行.vimrc
:
filetype plugin indent on
在我的 .vim
目录中:
~ % tree .vim
.vim
└── indent
├── html.vim
└── javascript.vim
1 directory, 2 files
其中:
~ % cat .vim/indent/javascript.vim
setlocal formatprg=js-beautify
let g:testvar_js="js testvar"
let g:testvar="testvar defined in javascript.vim"
和
~ % cat .vim/indent/html.vim
setlocal formatprg=html-beautify
let g:testvar_html="html testvar"
let g:testvar="testvar defined in html.vim"
然后我用 vim foo.html
打开一个新的空 vim 缓冲区,并用一些命令进行测试:
:set filetype?
filetype=html
:set formatprg?
formatprg=js-beautify
:echo g:testvar
testvar defined in javascript.vim
:echo g:testvar_html
html testvar
:echo g:testvar_js
js testvar
好像 vim 来源两个缩进文件类型插件,首先 indent/html.vim
然后 indent/javascript.vim
。
因此,我的问题是:
- 我是不是犯了什么愚蠢的错误?
- 如果不是,那么这是一个有意的设计,一个错误,还是 vim 与此无关?
- 有没有办法在编辑 html 文件时使 vim 仅在
html.vim
上提供源代码?
一些可能有用的附加信息:
- 我在 vim 8.2,macOS arm64,使用 Terminal.app
- Neovim 表现出相同的行为;实际上这是我第一次注意到它的地方
- 此行为不会发生在
ftplugin/
,只有 indent/
- javascript 文件不受
indent/html.vim
影响:在 indent/html.vim
中定义的变量在 javascript 缓冲区中都是未定义的
formatprg
的 html 个文件在打开时总是 js-beautify
,无论里面是否有任何 javascript 代码片段或 <script>
标签 html 文件
- 一个
indent/css.vim
在编辑的时候根本不会参与html——我测试过
js-beautify
和 html-beautify
是两个独立的可执行文件(存储库是 here)
bin % ls -n js-beautify
lrwxr-xr-x 1 501 80 53 Apr 19 17:59 js-beautify -> ../lib/node_modules/js-beautify/js/bin/js-beautify.js
bin % ls -n html-beautify
lrwxr-xr-x 1 501 80 55 Apr 19 17:59 html-beautify -> ../lib/node_modules/js-beautify/js/bin/html-beautify.js
如果你想让我做一些额外的测试或需要更多信息,请大声喊叫。
非常感谢
这是一个完全有效的 HTML 示例:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Sample</title>
<script>
console.log('Hello, World!');
</script>
<style>
body {
background: orange;
}
</style>
</head>
<body>
<h1>Sample</h1>
</body>
</html>
您会注意到其中嵌入了一点点 JavaScript,这是 $VIMRUNTIME/indent/html.vim
来源 $VIMRUNTIME/indent/javascript.vim
的充分理由。毕竟,javascript
缩进脚本应该知道如何缩进 JavaScript,所以为什么不在 可以 包含的 html
缓冲区中使用它呢?嵌入式 JavaScript?
FWIW,这是导致该行为的代码片段:
if !exists('*GetJavascriptIndent')
runtime! indent/javascript.vim
endif
请注意,$VIMRUNTIME/indent/html.vim
的维护者为 javascript
选择了外部路由,为 css
选择了内部路由。也许是因为 $VIMRUNTIME/indent/css.vim
不符合要求?我不知道,坦率地说,我认为这不重要。
现在,让我们回顾一下你的错误……
Filetype-specific 脚本(缩进、语法、ftplugins)按以下顺序获取:
~/.vim/indent/<filetype>.vim
,
$VIMRUNTIME/indent/<filetype>.vim
~/.vim/after/indent/<filetype>.vim
如果您不小心,您放入较早脚本中的内容可能会在获取较晚脚本时被覆盖。出于这个原因,将您自己的东西放在 after/
.
下的脚本中更有意义
以下几行在缩进脚本中无所事事:
setlocal formatprg=js-beautify
setlocal formatprg=html-beautify
它们应该在 ftplugins 中:
" after/ftplugin/javascript.vim
setlocal formatprg=js-beautify
" after/ftplugin/html.vim
setlocal formatprg=html-beautify
所以……
Did I make any silly mistakes?
是的,见上文。
If no, then is this an intentional design, a bug, or is that vim has nothing to do with this at all?
嗯,是的,这是一个非常有效的有意设计。它只是因为你误用了它才导致问题。
Is there a way to make vim only source on html.vim
when editing html files?
indent/html.vim
?是的,这当然是可能的,但你为什么要这样做?
ftplugin/html.vim
?它已经按照你想要的方式工作,而且它是你错误地放入 indent/html.vim
开始的东西的正确位置。
--- 编辑 ---
Just curious, indent/
files are supposed to set indentation options right, then why shouldn't I set the indentation program there?
Filetype-specific 脚本通常在相应文件类型的文件加载到缓冲区中时获取一次。因为将语言嵌入其他语言(JavaScript in HTML)或其他语言的超集(C++ vs C)的语言是相对常见的,Vim 使得从其他语言中获取资源成为可能filetype-specific 个脚本。这几乎是代码重用的具体示例,通常被认为是一件好事。
缩进脚本可以作为其他缩进脚本的源,语法脚本可以作为其他语法脚本的源,ftplugins 可以作为其他 ftplugins 的源。
因此 Vim 为我们提供了一个有用的 low-level 机制,但由我们决定将什么放在哪里,这始终取决于上下文。
在 HTML 的情况下,使用现有的 JavaScript 缩进内容是有意义的,因此 $VIMRUNTIME/indent/html.vim
尽早获取 $VIMRUNTIME/indent/javascript.vim
然后继续设置 HTML-specific 东西。最终结果是一个 html
缩进脚本,它也支持嵌入 JavaScript。 html
语法脚本使用类似的机制来突出显示嵌入的 JavaScript。在一些简单的情况下,您甚至可以让一个 ftplugin 采购另一个 ftplugin,但 $VIMRUNTIME/ftplugin/html.vim
不会。
但它并不总是有意义:选项可能会被覆盖,映射可能会被覆盖或在它们没有意义的上下文中定义,等等。在这个特定的在这种情况下,用于格式化的外部工具是高度 context-sensitive:您不能真正期望 js-beautify
正确格式化 HTML 或 html-beautify
正确格式化 JavaScript因此必须为 javascript
和 html
文件类型分别设置 formatprg
。
这就是你犯第一个错误的地方。
这里再次显示了 $VIMRUNTIME/indent/javascript.vim
来自 $VIMRUNTIME/indent/html.vim
的片段:
if !exists('*GetJavascriptIndent')
runtime! indent/javascript.vim
endif
:help :runtime
是 :help :source
的智能替代品,它在 :help 'runtimepath'
中查找文件。因为您的 ~/.vim/indent/javascript.vim
在您的 runtimepath
中,所以它会被获取。因为有一个 !
,每个匹配的文件都将被获取。因为它在 runtimepath
中排在第一位,所以它可能会被后面的脚本覆盖。
在您的情况下,$VIMRUNTIME/indent/html.vim
会自动获取您的 ~/.vim/indent/javascript.vim
,其中包含不应在 html
缓冲区中设置的内容。
after
目录允许您对给定文件类型的设置有最终决定权,因为 built-in 脚本很少(如果有的话)执行 runtime! after/indent/<filetype>.vim
这就解释了为什么不小心把你的 filetype-specific 东西放在 ~/.vim/{ftplugin,indent,syntax}/
里是个坏主意,为什么你应该把它放在 ~/.vim/after/{ftplugin,indent,syntax}/
里。
TL;DR:vim 似乎在编辑 html 文件时同时采购 indent/javascript.vim
和 indent/html.vim
;这是故意的还是错误?我怎样才能使 html 文件仅源 html.vim
?
最近我发现 vim 似乎在编辑 html 文件时对 javascript 和 html 使用缩进文件类型插件,我做了一些基于此行为在最小 vim 配置上进行测试。
这是我的单行.vimrc
:
filetype plugin indent on
在我的 .vim
目录中:
~ % tree .vim
.vim
└── indent
├── html.vim
└── javascript.vim
1 directory, 2 files
其中:
~ % cat .vim/indent/javascript.vim
setlocal formatprg=js-beautify
let g:testvar_js="js testvar"
let g:testvar="testvar defined in javascript.vim"
和
~ % cat .vim/indent/html.vim
setlocal formatprg=html-beautify
let g:testvar_html="html testvar"
let g:testvar="testvar defined in html.vim"
然后我用 vim foo.html
打开一个新的空 vim 缓冲区,并用一些命令进行测试:
:set filetype?
filetype=html
:set formatprg?
formatprg=js-beautify
:echo g:testvar
testvar defined in javascript.vim
:echo g:testvar_html
html testvar
:echo g:testvar_js
js testvar
好像 vim 来源两个缩进文件类型插件,首先 indent/html.vim
然后 indent/javascript.vim
。
因此,我的问题是:
- 我是不是犯了什么愚蠢的错误?
- 如果不是,那么这是一个有意的设计,一个错误,还是 vim 与此无关?
- 有没有办法在编辑 html 文件时使 vim 仅在
html.vim
上提供源代码?
一些可能有用的附加信息:
- 我在 vim 8.2,macOS arm64,使用 Terminal.app
- Neovim 表现出相同的行为;实际上这是我第一次注意到它的地方
- 此行为不会发生在
ftplugin/
,只有indent/
- javascript 文件不受
indent/html.vim
影响:在indent/html.vim
中定义的变量在 javascript 缓冲区中都是未定义的 formatprg
的 html 个文件在打开时总是js-beautify
,无论里面是否有任何 javascript 代码片段或<script>
标签 html 文件- 一个
indent/css.vim
在编辑的时候根本不会参与html——我测试过 js-beautify
和html-beautify
是两个独立的可执行文件(存储库是 here)bin % ls -n js-beautify lrwxr-xr-x 1 501 80 53 Apr 19 17:59 js-beautify -> ../lib/node_modules/js-beautify/js/bin/js-beautify.js bin % ls -n html-beautify lrwxr-xr-x 1 501 80 55 Apr 19 17:59 html-beautify -> ../lib/node_modules/js-beautify/js/bin/html-beautify.js
如果你想让我做一些额外的测试或需要更多信息,请大声喊叫。
非常感谢
这是一个完全有效的 HTML 示例:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Sample</title>
<script>
console.log('Hello, World!');
</script>
<style>
body {
background: orange;
}
</style>
</head>
<body>
<h1>Sample</h1>
</body>
</html>
您会注意到其中嵌入了一点点 JavaScript,这是 $VIMRUNTIME/indent/html.vim
来源 $VIMRUNTIME/indent/javascript.vim
的充分理由。毕竟,javascript
缩进脚本应该知道如何缩进 JavaScript,所以为什么不在 可以 包含的 html
缓冲区中使用它呢?嵌入式 JavaScript?
FWIW,这是导致该行为的代码片段:
if !exists('*GetJavascriptIndent')
runtime! indent/javascript.vim
endif
请注意,$VIMRUNTIME/indent/html.vim
的维护者为 javascript
选择了外部路由,为 css
选择了内部路由。也许是因为 $VIMRUNTIME/indent/css.vim
不符合要求?我不知道,坦率地说,我认为这不重要。
现在,让我们回顾一下你的错误……
Filetype-specific 脚本(缩进、语法、ftplugins)按以下顺序获取:
~/.vim/indent/<filetype>.vim
,$VIMRUNTIME/indent/<filetype>.vim
~/.vim/after/indent/<filetype>.vim
如果您不小心,您放入较早脚本中的内容可能会在获取较晚脚本时被覆盖。出于这个原因,将您自己的东西放在
下的脚本中更有意义after/
.以下几行在缩进脚本中无所事事:
setlocal formatprg=js-beautify setlocal formatprg=html-beautify
它们应该在 ftplugins 中:
" after/ftplugin/javascript.vim setlocal formatprg=js-beautify " after/ftplugin/html.vim setlocal formatprg=html-beautify
所以……
Did I make any silly mistakes?
是的,见上文。
If no, then is this an intentional design, a bug, or is that vim has nothing to do with this at all?
嗯,是的,这是一个非常有效的有意设计。它只是因为你误用了它才导致问题。
Is there a way to make vim only source on
html.vim
when editing html files?
indent/html.vim
?是的,这当然是可能的,但你为什么要这样做?ftplugin/html.vim
?它已经按照你想要的方式工作,而且它是你错误地放入indent/html.vim
开始的东西的正确位置。
--- 编辑 ---
Just curious,
indent/
files are supposed to set indentation options right, then why shouldn't I set the indentation program there?
Filetype-specific 脚本通常在相应文件类型的文件加载到缓冲区中时获取一次。因为将语言嵌入其他语言(JavaScript in HTML)或其他语言的超集(C++ vs C)的语言是相对常见的,Vim 使得从其他语言中获取资源成为可能filetype-specific 个脚本。这几乎是代码重用的具体示例,通常被认为是一件好事。
缩进脚本可以作为其他缩进脚本的源,语法脚本可以作为其他语法脚本的源,ftplugins 可以作为其他 ftplugins 的源。
因此 Vim 为我们提供了一个有用的 low-level 机制,但由我们决定将什么放在哪里,这始终取决于上下文。
在 HTML 的情况下,使用现有的 JavaScript 缩进内容是有意义的,因此 $VIMRUNTIME/indent/html.vim
尽早获取 $VIMRUNTIME/indent/javascript.vim
然后继续设置 HTML-specific 东西。最终结果是一个 html
缩进脚本,它也支持嵌入 JavaScript。 html
语法脚本使用类似的机制来突出显示嵌入的 JavaScript。在一些简单的情况下,您甚至可以让一个 ftplugin 采购另一个 ftplugin,但 $VIMRUNTIME/ftplugin/html.vim
不会。
但它并不总是有意义:选项可能会被覆盖,映射可能会被覆盖或在它们没有意义的上下文中定义,等等。在这个特定的在这种情况下,用于格式化的外部工具是高度 context-sensitive:您不能真正期望 js-beautify
正确格式化 HTML 或 html-beautify
正确格式化 JavaScript因此必须为 javascript
和 html
文件类型分别设置 formatprg
。
这就是你犯第一个错误的地方。
这里再次显示了 $VIMRUNTIME/indent/javascript.vim
来自 $VIMRUNTIME/indent/html.vim
的片段:
if !exists('*GetJavascriptIndent')
runtime! indent/javascript.vim
endif
:help :runtime
是 :help :source
的智能替代品,它在 :help 'runtimepath'
中查找文件。因为您的 ~/.vim/indent/javascript.vim
在您的 runtimepath
中,所以它会被获取。因为有一个 !
,每个匹配的文件都将被获取。因为它在 runtimepath
中排在第一位,所以它可能会被后面的脚本覆盖。
在您的情况下,$VIMRUNTIME/indent/html.vim
会自动获取您的 ~/.vim/indent/javascript.vim
,其中包含不应在 html
缓冲区中设置的内容。
after
目录允许您对给定文件类型的设置有最终决定权,因为 built-in 脚本很少(如果有的话)执行 runtime! after/indent/<filetype>.vim
这就解释了为什么不小心把你的 filetype-specific 东西放在 ~/.vim/{ftplugin,indent,syntax}/
里是个坏主意,为什么你应该把它放在 ~/.vim/after/{ftplugin,indent,syntax}/
里。