在&#34之后从插入模式返回正常模式;执行正常"

时间:2014-11-12 10:00:31

标签: vim

您可以在Ex模式下以编程方式执行普通模式命令,通过执行normal,例如

:execute "normal" "iNEWTEXT\<Esc>0"

切换到插入模式(i),写入&#34; NEWTEXT&#34;,转到正常模式(\&lt; Esc&gt;),然后移动到行的开头(0)。

但是,使用非常量字符串(寄存器或变量),行为是不同的。例如,假设您在任何文件(不一定是vimscript文件)中的行上保存了相同的命令:

iNEWTEXT\<Esc>0

然后,您可以通过"zy$将文本复制到任何寄存器(此处为z),并通过@z执行注册。但这一次,输出是不同的:

NEWTEXT\<Esc>0

进入插入模式后,Escape不再被视为特殊字符,而是按字面意思进行处理。其他形式如\ 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的答案的两个功能。它们的工作方式大致相同,但最终可以将用户置于插入模式(而根据我的最小信息,在其他上下文中,我认为是不完整的命令而不执行,并且:startinsert可以& #39; t在那种情况下使用)。 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

2 个答案:

答案 0 :(得分:4)

如果你确实需要这个(用例是可疑的),你必须:execute两次:一次将寄存器的内容插入一个双引号字符串,然后一次用于{{1评估字符串。

:normal

PS:请提供更多背景;你的最终目标是什么?当一个问题只是一个小技术步骤时,很难提供一个好的答案。如果你没有告诉我们为什么你想要这个,那么很容易屈服于XY problem

答案 1 :(得分:1)

我宁愿使用feedkeys()函数。例如。对于您的样本,这应该有效:

exe ':call feedkeys("'.@".'", "t")'

(如果你将你的行拉入未命名的寄存器,否则相应地调整寄存器名称)。请注意,引用可能会变得难看。

要了解发生了什么,这就是做了什么:

exe ':call feedkeys('           - First part of the feedkeys() function call
    "                           - Start of Quote for the first argument
    .                           - String concatenation
    @"                          - content of the unnamed register
    .                           - String concatenation
    '                           - Start of second part of the feedkeys function call
    "                           - End of Quote for the first argument
    , "t")'                     - Second argument of feedkeys() function call

你也可以分两步完成:

   exe ':let a="'. @". '"'       - Also needs to quote @" correctly.
   call feedkeys(a, 't')

应该更容易理解。 exe调用只是将规范化的键表示法转换为文字键。