Vimscript 缩进和调试 ftplugin 脚本
Vimscript indent and debugging ftplugin scripts
我正在尝试使用 ftplugin 脚本为 .tex
文件手动定义缩进级别。
~/.vim/ftplugin/tex/indent.vim
:
1 setlocal indentexpr=TeXIndent(v:lnum)
2
3 function! TeXIndent(lnum)
4 if a:lnum == 0
5 return 0
6 endif
7
8 let prev = getline(a:lnum - 1)
9 let line = getline(a:lnum)
10
11 " sections have hardcoded indentation; environments are always subordinate to sections
12 if prev =~ '^\s*\section'
13 return 1
14 elseif prev =~ '^\s*\subsection'
15 return 2
16 elseif prev =~ '^\s*\subsubsection'
17 return 3
18 elseif prev =~ '^\s*\paragraph'
19 return 4
20 " environment indentation
21 elseif prev =~ '\begin'
22 return indent(a:lnum - 1) + 1 " increase indentation by 1 if previous line has \begin
23 elseif line =~ '\end'
24 return indent(a:lnum - 1) - 1 " decrease indentation by 1 if line has \end
25 else
26 return indent(a:lnum - 1) " use previous indentation
27 endif
28 endfunction
当我键入 \section
时,我希望按 enter
将光标移动到下一行的缩进级别 1(其他条件相同,在 TeXIndent
中指定) ), 而事实并非如此。使用更简单的函数进行测试,每次 returns 2 也没有这种行为,所以我怀疑我的方法有缺陷。我如何实现预期的行为?
一般情况下,ftplugin脚本如何调试?
调试 ftplugin 时所有常用方法都可用。
:debug exe "normal keysequence"
可用于调试映射
:debug Command
可用于调试命令、函数(使用:debug call
或:debug echo
)...
:verbose
可用于了解实际定义的内容以及定义的位置——请参阅 vi.SE 上的专用 Q/A:https://vi.stackexchange.com/q/7722/626
- 也可以使用日志——参见 my framework
- 我们甚至可以添加一些断言以在编程错误时快速失败——请参阅我的 other framework(来自相同的库插件)
现在您的问题不在于 ftplugins,而在于缩进表达式。如果我没记错的话,它面临着与折叠表达式相同的问题:indenting/folding 函数由 Vim 每行自动调用一次。消息将被静音,:debug
的内部使用将以噩梦告终。
我们能做什么:
log 到一个文件,或者其他地方像 qf window
不要将函数绑定到 v:lnum
以便能够独立调用该函数。太完美了,你已经做到了。我们可以使用
测试所有调用的响应
:echo map(range(1, line('$')), 'the_expr_function(v:val)')
玩气球(需要gvim而不是vim)
玩符号
您会在我维护的 folding plugin 中找到这些方法。
(另见 vi.SE 上的 Q/A:https://vi.stackexchange.com/a/19916/626)
PS:缩进插件应该进入{rtp}/indent/
,而不是{rtp}/ftplugin/
,我们通常分析最后一个非空行。你应该在 $VIMRUNTIME/indent
中找到示例,我有几个 Johannes Zellner 大约在 2002 年编写的 TeX 缩进插件。
我正在尝试使用 ftplugin 脚本为 .tex
文件手动定义缩进级别。
~/.vim/ftplugin/tex/indent.vim
:
1 setlocal indentexpr=TeXIndent(v:lnum)
2
3 function! TeXIndent(lnum)
4 if a:lnum == 0
5 return 0
6 endif
7
8 let prev = getline(a:lnum - 1)
9 let line = getline(a:lnum)
10
11 " sections have hardcoded indentation; environments are always subordinate to sections
12 if prev =~ '^\s*\section'
13 return 1
14 elseif prev =~ '^\s*\subsection'
15 return 2
16 elseif prev =~ '^\s*\subsubsection'
17 return 3
18 elseif prev =~ '^\s*\paragraph'
19 return 4
20 " environment indentation
21 elseif prev =~ '\begin'
22 return indent(a:lnum - 1) + 1 " increase indentation by 1 if previous line has \begin
23 elseif line =~ '\end'
24 return indent(a:lnum - 1) - 1 " decrease indentation by 1 if line has \end
25 else
26 return indent(a:lnum - 1) " use previous indentation
27 endif
28 endfunction
当我键入 \section
时,我希望按 enter
将光标移动到下一行的缩进级别 1(其他条件相同,在 TeXIndent
中指定) ), 而事实并非如此。使用更简单的函数进行测试,每次 returns 2 也没有这种行为,所以我怀疑我的方法有缺陷。我如何实现预期的行为?
一般情况下,ftplugin脚本如何调试?
调试 ftplugin 时所有常用方法都可用。
:debug exe "normal keysequence"
可用于调试映射:debug Command
可用于调试命令、函数(使用:debug call
或:debug echo
)...:verbose
可用于了解实际定义的内容以及定义的位置——请参阅 vi.SE 上的专用 Q/A:https://vi.stackexchange.com/q/7722/626- 也可以使用日志——参见 my framework
- 我们甚至可以添加一些断言以在编程错误时快速失败——请参阅我的 other framework(来自相同的库插件)
现在您的问题不在于 ftplugins,而在于缩进表达式。如果我没记错的话,它面临着与折叠表达式相同的问题:indenting/folding 函数由 Vim 每行自动调用一次。消息将被静音,:debug
的内部使用将以噩梦告终。
我们能做什么:
log 到一个文件,或者其他地方像 qf window
不要将函数绑定到
测试所有调用的响应v:lnum
以便能够独立调用该函数。太完美了,你已经做到了。我们可以使用:echo map(range(1, line('$')), 'the_expr_function(v:val)')
玩气球(需要gvim而不是vim)
玩符号
您会在我维护的 folding plugin 中找到这些方法。
(另见 vi.SE 上的 Q/A:https://vi.stackexchange.com/a/19916/626)
PS:缩进插件应该进入{rtp}/indent/
,而不是{rtp}/ftplugin/
,我们通常分析最后一个非空行。你应该在 $VIMRUNTIME/indent
中找到示例,我有几个 Johannes Zellner 大约在 2002 年编写的 TeX 缩进插件。