【发布时间】:2014-11-14 02:07:39
【问题描述】:
您可以在 Ex 模式下以编程方式执行正常模式命令,例如执行正常,例如
:execute "normal" "iNEWTEXT\<Esc>0"
这会切换到插入模式 (i),写入“NEWTEXT”,转义到正常模式 (\
但是,使用非常量字符串(寄存器或变量)时,行为是不同的。例如,假设您在任何文件(不一定是 vimscript 文件)的一行中保存了上面相同的命令:
iNEWTEXT\<Esc>0
然后您可以通过"zy$ 将文本复制到任何寄存器(此处为z)并通过@z 执行该寄存器。不过,这一次的输出有所不同:
NEWTEXT\<Esc>0
进入插入模式后,转义不再被视为特殊字符,而是按字面意思理解。像 \e 这样的替代形式也不起作用。有没有解决的办法?
编辑:使用 Ingo 的回答,我创建了以下函数。基本上,用途是在文件文本中嵌入一组正常/插入命令,并能够执行它们。更常见的是,running Ex commands from a line of text 使用了类似的东西,但我找不到任何可以在正常和插入模式下执行此操作的东西。
因此,您的文件中将包含如下文本:
jy10j10jpO\<Esc>jEll
在该行上,您可以调用函数或重映射,然后命令将执行(在此示例中,复制和粘贴 10 行,并将 2 列移到第一个单词之后)。 Ingo 的替代方案更适合认真使用,即从另一个文件中获取命令,在 .vimrc 中包含命令,或文件类型特定的选项。由会话保存的宏也可以正常工作,并且比将命令分散在文件中更实用。就我而言,我正在跨多个设备进行同步,并且不想拥有另一个文件或使用这个非常特定的命令弄乱我的 vimrc,但不介意弄乱这个特定的文件本身。把它想象成一个可移植的宏。
" Execute current line as Vim normal mode commands.
nnoremap <A-y> :call EvaluateLineAsNormalModeCmd()<CR>
function! EvaluateLineAsNormalModeCmd()
let g:getCurrentLine = getline(".")
"have to :execute twice: once to get the contents of the
"register inserted into a double-quoted string, and then once for
"the :normal to evaluate the string.
execute 'execute "normal" "' . g:getCurrentLine . '"'
endfunction
EDIT2/3:这里有两个函数使用 Christian Brabandt 的答案。它们的工作原理大致相同,但可以在最后将用户置于插入模式(而根据我的最少信息,其他上下文中的 'i' 被认为是不完整的命令并且未执行,并且 :startinsert 不能用于那种情况)。 PS:请不要问我那些单引号和双引号在做什么,因为我无法理解它O_o
function! EvaluateLineAsNormalModeCmd()
normal! 0y$
execute ':call feedkeys("'.@".'", "t")'
endfunction
function! EvaluateLineAsNormalModeCmd()
let g:getCurrentLine = getline(".")
execute ':call feedkeys("'.g:getCurrentLine.'", "t")'
endfunction
【问题讨论】:
-
您是否尝试过将
\<Esc>序列更改为^[? (即<C-v><Esc>) -
试过这个,但它遇到了同样的问题:一切都是字面意思。 Ingo 的双重执行功能解决了这个问题。
标签: vim