在vim中进行LaTeX编辑时,我记录了一些有用的宏并将它们包装到函数/命令中。我有一个可以更改Latex环境的类型,例如,当我有以下情况时:
\begin{itemize}
\item First
\item Second
\end{itemize}
我只需在环境中某处的光标处输入:ChangeEnv enumerate
,即可从逐项更改为枚举。
我的ftplugin / tex.vim中的代码如下:
function! ChangeEnv(newenv)
let l:save = @e
let @e = a:newenv
let l:line = getline('.')
" Fake change to restore undo
normal ix
normal x
if match(l:line, '\\begin{') != -1
normal mz_%f{lci}e'zf{l.`z:delma z
else
normal my?\\begin{^M_mz%f{lci}^Re^['zf{l.`y:delma yz
endif
let @e = l:save
endfunction
command -nargs=1 ChangeEnv :silent call ChangeEnv(<f-args>)
到目前为止,如果光标位于环境的if match(...
部分上,则第一部分(在\begin{...}
之后)到目前为止可以正常工作,我可以进行更改并撤消它,光标停留在应有的位置。
第二部分,专门用于环境内部,也可以很好地工作,但是当撤消更改时,光标跳到\ begin行的第一个字符。
normal ix
和normal x
部分的目的是确保在und之后恢复光标位置(我在这里有Restor Cursor Position)
我的问题是,为什么它不能用于第二个宏?有什么错误吗?
为避免破坏宏,请执行以下步骤:
my
-在当前位置设置y
标记?\\begin{^M
-向后搜索环境的起点,然后跳到那里_mz
-转到该行的第一个字符并设置z
标记%
-跳转到匹配的环境\end{...
(这是matchit vim插件的一部分,随vim一起提供,但默认情况下不处于活动状态)。f{l
-跳至{
并向右一个字符ci}
-更改内部{...} ^Re^[
-插入存储新环境名称的e
寄存器的内容,并返回普通模式'z'
-跳至z
标记(\begin{...
)的开头f{l.
-转发至{
,向右移一步,然后重复上一次更改`y
-跳至y
标记,即初始位置:delma yz
-删除y
和z
标记尽管如此,撤消行为并不是破坏交易的因素,我至少想知道为什么这样做会破坏行为。
谢谢。
答案 0 :(得分:2)
通常,当您进行多个更改时,每个更改都将分别撤消。但是在一个函数内部,所有内容都集中在一起作为一个单一的更改。
您打算在一开始(当光标尚未移动时)进行此虚拟更改的目的是,光标会在撤消后返回到该点。
但是,我认为Vim将ChangeEnv()
内所做的全部更改视为一个重大修改,它返回到更改行范围的开始(标记{{1 }}),就像撤消内置命令时一样。 “第一个”执行哪个更改命令无关紧要,重要的是更改的行的范围。当您的第二个分支向后搜索'[
并在那里进行更改时,这就是撤消后光标所在的位置。我认为这没有办法。撤消操作不受脚本的影响,因为这可能会导致不一致。
您可以做的是在进行更改后设置标记(在功能末尾:\begin
),以便您可以快速跳回那里(通过:normal! m'
或{{1} }。