如何使用 vim 作为 unix 过滤器来缩进源代码
How to use vim as a unix filter to indent source code
我想使用 vim 作为通用源代码压头。
这是我对 shell 函数的初步尝试,它包装了 vim 的调用,使 vim 根据文件类型和 shiftwidth 参数重新缩进 STDIN:
vim-indent () {
local ext=
local width=
local file=$(mktemp --suffix=."$ext")
cat >| "$file"
vim -E +"set sw=$width|normal! gg=G" +'x' -- "$file" >/dev/null
cat "$file"
}
测试 1:用 2 space 缩进
重新缩进 c 源代码
vim-indent c 2 << "EOF"
int main(int argc, char** argv) {
char operator;
printf("Enter an operator (+, -): ");
scanf("%c", &operator);
switch (operator) {
case '+':
case '-':
printf(operator);
break;
default:
printf("Error! operator is not correct");
}
return 0;
}
EOF
成功。 c 源代码重新缩进了 2 space 缩进:
int main(int argc, char** argv) {
char operator;
printf("Enter an operator (+, -): ");
scanf("%c", &operator);
switch (operator) {
case '+':
case '-':
printf(operator);
break;
default:
printf("Error! operator is not correct");
}
return 0;
}
测试 2:使用 2 space 缩进 space 重新缩进 bash 源代码
vim-indent sh 2 << "EOF"
#!/usr/bin/bash
hello() {
echo "Hello World"
}
if true; then
echo "It is true"
fi
EOF
失败。函数体缩进正确,但 if 语句不缩进:
#!/usr/bin/bash
hello() {
echo "Hello World"
}
if true; then
echo "It is true"
fi
测试 3:用 2 space 缩进 space 重新缩进 html 源代码
vim-indent html 2 << "EOF"
<html>
<body>
<div>
<p>Hello</p>
</div>
</body>
</html>
EOF
失败。完全没有缩进:
<html>
<body>
<div>
<p>Hello</p>
</div>
</body>
</html>
当我编辑 bash
和 html
文件到 vim 时,我可以重新缩进它们。
为什么上面的测试对 c
源代码成功,但对 bash
和 html
源代码失败?
结论
我结合了答案中的建议并创建了一个工作 shell 脚本(在下面作为答案提交),我可以将其用作通用源代码缩进器。
将此添加到 .vimrc
:
filetype plugin indent on
根据您的 html 缩进首选项,您可能还需要将此行添加到 .vimrc
:
let g:html_indent_inctags="html,body,head"
这一行是必需的,因为在某些 Vim 版本中,默认的 html 缩进文件(位于 :e $VIMRUNTIME/indent/html.vim
)不会在 <html>
、[=16] 中缩进行=] 和 <head>
标签。
由于 .vim/indent
文件夹,您还可以定义不同的缩进行为。然后在此文件夹中添加一个 html.vim 和一个 c.vim 文件。您可以描述每种语言的所有所需行为,并且您将能够像以前一样使用 =
快捷方式。
将此与 Sergio 之前的评论结合起来,您将获得一种合适的方法来缩进不同类型的文件。
这个 shell 脚本通过了我问题中描述的 3 个测试。
文件:vim-indent
:
#!/usr/bin/bash
filetype=${1:?"Usage: vim-indent FILETYPE [WIDTH]"}
shiftwidth=${2:-4} # default indent width is 4
file=$(mktemp) || { echo "Couldn't create temp file" >&2; exit 1; }
trap "rm $file" EXIT
cat > "$file"
/usr/bin/vim -u NONE -E \
+'let g:html_indent_inctags = "p,html,body,head,tbody"' \
+'filetype plugin indent on' \
+"set filetype=$filetype" \
+"syntax on" \
+"set expandtab" \
+"set shiftwidth=$shiftwidth|normal! gg=G" \
+'x' -- "$file" >/dev/null
cat "$file"
与我最初的 shell 功能相比,我做了以下改进:
- 将其设为 shell 脚本而不是 shell 函数
- 采纳了 Sergio 关于使用
filetype plugin indent on
的建议
- 我把初始化文件设置为NONE。我直接在 vim 调用中执行初始化命令,以保持脚本独立。
- 添加了一些额外的 HTML 标签以缩进
- 在 EXIT 时添加了一个陷阱来清理临时文件
2020-07-02:添加了syntax on
; xml
文件和其他文件需要。
我想使用 vim 作为通用源代码压头。
这是我对 shell 函数的初步尝试,它包装了 vim 的调用,使 vim 根据文件类型和 shiftwidth 参数重新缩进 STDIN:
vim-indent () {
local ext=
local width=
local file=$(mktemp --suffix=."$ext")
cat >| "$file"
vim -E +"set sw=$width|normal! gg=G" +'x' -- "$file" >/dev/null
cat "$file"
}
测试 1:用 2 space 缩进
重新缩进 c 源代码vim-indent c 2 << "EOF"
int main(int argc, char** argv) {
char operator;
printf("Enter an operator (+, -): ");
scanf("%c", &operator);
switch (operator) {
case '+':
case '-':
printf(operator);
break;
default:
printf("Error! operator is not correct");
}
return 0;
}
EOF
成功。 c 源代码重新缩进了 2 space 缩进:
int main(int argc, char** argv) {
char operator;
printf("Enter an operator (+, -): ");
scanf("%c", &operator);
switch (operator) {
case '+':
case '-':
printf(operator);
break;
default:
printf("Error! operator is not correct");
}
return 0;
}
测试 2:使用 2 space 缩进 space 重新缩进 bash 源代码
vim-indent sh 2 << "EOF"
#!/usr/bin/bash
hello() {
echo "Hello World"
}
if true; then
echo "It is true"
fi
EOF
失败。函数体缩进正确,但 if 语句不缩进:
#!/usr/bin/bash
hello() {
echo "Hello World"
}
if true; then
echo "It is true"
fi
测试 3:用 2 space 缩进 space 重新缩进 html 源代码
vim-indent html 2 << "EOF"
<html>
<body>
<div>
<p>Hello</p>
</div>
</body>
</html>
EOF
失败。完全没有缩进:
<html>
<body>
<div>
<p>Hello</p>
</div>
</body>
</html>
当我编辑 bash
和 html
文件到 vim 时,我可以重新缩进它们。
为什么上面的测试对 c
源代码成功,但对 bash
和 html
源代码失败?
结论
我结合了答案中的建议并创建了一个工作 shell 脚本(在下面作为答案提交),我可以将其用作通用源代码缩进器。
将此添加到 .vimrc
:
filetype plugin indent on
根据您的 html 缩进首选项,您可能还需要将此行添加到 .vimrc
:
let g:html_indent_inctags="html,body,head"
这一行是必需的,因为在某些 Vim 版本中,默认的 html 缩进文件(位于 :e $VIMRUNTIME/indent/html.vim
)不会在 <html>
、[=16] 中缩进行=] 和 <head>
标签。
由于 .vim/indent
文件夹,您还可以定义不同的缩进行为。然后在此文件夹中添加一个 html.vim 和一个 c.vim 文件。您可以描述每种语言的所有所需行为,并且您将能够像以前一样使用 =
快捷方式。
将此与 Sergio 之前的评论结合起来,您将获得一种合适的方法来缩进不同类型的文件。
这个 shell 脚本通过了我问题中描述的 3 个测试。
文件:vim-indent
:
#!/usr/bin/bash
filetype=${1:?"Usage: vim-indent FILETYPE [WIDTH]"}
shiftwidth=${2:-4} # default indent width is 4
file=$(mktemp) || { echo "Couldn't create temp file" >&2; exit 1; }
trap "rm $file" EXIT
cat > "$file"
/usr/bin/vim -u NONE -E \
+'let g:html_indent_inctags = "p,html,body,head,tbody"' \
+'filetype plugin indent on' \
+"set filetype=$filetype" \
+"syntax on" \
+"set expandtab" \
+"set shiftwidth=$shiftwidth|normal! gg=G" \
+'x' -- "$file" >/dev/null
cat "$file"
与我最初的 shell 功能相比,我做了以下改进:
- 将其设为 shell 脚本而不是 shell 函数
- 采纳了 Sergio 关于使用
filetype plugin indent on
的建议
- 我把初始化文件设置为NONE。我直接在 vim 调用中执行初始化命令,以保持脚本独立。
- 添加了一些额外的 HTML 标签以缩进
- 在 EXIT 时添加了一个陷阱来清理临时文件
2020-07-02:添加了syntax on
; xml
文件和其他文件需要。