25

假设我正在编辑我的_vimrc文件并且我刚刚添加了几行,例如一个新的键映射。我不想重新加载整个文件 ( :so %),因为这会重置很多我正在尝试的临时内容。我只想运行我目前正在处理的两条线。

我没有运气尝试将这些行复制/粘贴到命令缓冲区中,因为我不能在那里使用 put 命令。有什么方法可以将当前行(或当前选择)作为 EX 命令运行?


概括:

Anton Kovalenko的回答和Peter Rincker的评论之后,我最终得到了这些关键映射,它们要么执行当前行,要么在可视模式下执行当前选定的行:

" Execute current line or current selection as Vim EX commands.
nnoremap <F2> :exe getline(".")<CR>
vnoremap <F2> :<C-w>exe join(getline("'<","'>"),'<Bar>')<CR>
4

9 回答 9

49

要将当前行作为 ex 命令执行,您还可以使用:

yy:@"

这会将当前行拉到“-register 并执行它。我不认为这是太多的打字。

于 2013-10-22T16:16:08.880 回答
20

将光标下的行作为 Ex 命令执行:

:execute getline(".")

2条线足够方便。(我会想办法用区域来做这件事,但我不是 vim 用户)。对于当前选定的区域,以下似乎可以完成这项工作:

:execute getreg("*")

正如Peter Rincker评论的那样,此映射可用于执行当前选定的行:

:vnoremap <f2> :<c-u>exe join(getline("'<","'>"),'<bar>')<cr>
于 2013-01-17T18:53:43.323 回答
6

为此,我定义了以下命令和映射:

":[range]Execute    Execute text lines as ex commands.
"                   Handles |line-continuation|.
" The same can be achieved via "zyy@z (or yy@" through the unnamed register);
" but there, the ex command must be preceded by a colon (i.e. :ex)
command! -bar -range Execute silent <line1>,<line2>yank z | let @z = substitute(@z, '\n\s*\\', '', 'g') | @z

" [count]<Leader>e  Execute current [count] line(s) as ex commands, then
" {Visual}<Leader>e jump to the following line (to allow speedy sequential
"                   execution of multiple lines).
nnoremap <silent> <Leader>e :Execute<Bar>execute 'normal! ' . v:count1 . 'j'<CR>
xnoremap <silent> <Leader>e :Execute<Bar>execute 'normal! ' . v:count1 . 'j'<CR>
于 2013-01-17T19:03:21.723 回答
4

发布此消息后,我找到了解决方法。我可以使用 将文本复制到剪贴板"*y,然后使用鼠标中键将该文本放入命令缓冲区。这对我有用,但对于没有剪贴板支持、鼠标支持或只是厌恶将手从 Vim 位置移开的人来说,这并不是一个方便的解决方案。

于 2013-01-17T18:50:22.500 回答
2

接受的答案不处理延续部分。此外,令人惊讶的是,不需要该栏,换行符很好。这将起作用,首先将文本拉入寄存器 x:

vno <c-x> "xy:exe substitute(@x,"\n\\",'','g')<cr>

正如有人已经提到的,唯一的例外是“吃掉”换行符的命令。例如,在以下位置执行上述映射:

:sign define piet text=>> texthl=Search 
:exe ":sign place 2 line=23 name=piet file=" . expand("%:p")

将导致 vim 认为用户正在尝试将 textl 定义为 "Search\n:exe ":sign place... 等。

于 2013-06-18T19:55:03.860 回答
2

你也可以试试 :<C-R><C-L><CR>

根据 vim 文档,该组合会将当前行放入命令行。从那里,按回车键就可以了。我意识到这不能处理多行情况,但是它不需要 .vimrc,因此可以开箱即用。

于 2020-10-02T17:40:32.920 回答
1

我不想重新加载整个文件 (:so %),因为这会重置很多我正在试验的临时内容。我只想运行我目前正在处理的两条线。

如果你想执行一个命令,因为你想在将它提交到 _.vimrc 之前对其进行优化,那么你应该为 Ex 模式命令启动一个命令行窗口,使用q:.

启动时,命令行窗口会缓冲命令行历史记录的内容。它是一个普通的 Vim 窗口,其内容可以作为任何文本缓冲区进行编辑,除非在执行该行命令的任何行上按下。当您想稍微更改之前编写的长而复杂的命令并重新运行它时,它非常有用。

要为搜索字符串启动“命令行窗口”,请按q/

于 2013-06-15T07:05:09.877 回答
1

如果你正在做很多实验(我想尝试一下你可能想要添加到你的 vimrc 中的东西?)在一个像experimental.vim 这样的临时文件中这样做可能会有所帮助,这样你就不仅仅依赖于你的历史以了解您正在尝试什么。既然您拥有这些出色的映射,就可以轻松地从实验或 vimrc 重新运行东西,而无需获取整个文件。

另外(对不起,我似乎还不能评论答案),我尝试了彼得的这个映射:

vnoremap <Leader>es :<c-u>exec join(getline("'<","'>"),'<BAR>')<CR>

这在大多数情况下都有效,但它在函数定义上特别失败。

function! TestMe()
  echo "Yay!"
endfunction

此映射将这些行连接成一个字符串,由它们分隔<BAR>然后执行它们。

我不完全确定为什么,但是如果我尝试在正常模式下使用函数定义来做到这一点:

:exec 'function! TestMe()|  echo "Yay!"|endfunction'
-> E488: Trailing characters

经过一些测试,我发现它可以与换行符一起使用:

:exec "function! TestMe()\n  echo 'Yay!'\nendfunction"
:call TestMe()
-> Yay!

因此,我将映射更改为:

vnoremap <Leader>es :<c-u>exec join(getline("'<","'>"),"\n")<CR>

我想有一个 vim 或 ex 原因导致该<BAR>方法不适用于函数(甚至可能是我的某些设置?),如果有人知道,我很想知道它是什么。

于 2013-01-22T14:51:59.597 回答
0

!!(的简写)根据POSIX &:.!将当前行作为命令的输入执行。如果它是系统命令,您可能需要附加。 exvish

!!在空行上执行(并省略sh)是将 shell 命令直接读入缓冲区的快捷方式。它的本质是:.!覆盖当前行,同时:.r!在下面的行上插入。


ls -A | head -n +4
~
~
!sh

结果:

.sh_history
.sh_logout
.kshrc
corelist.txt
~
~
4 lines added; 1 line deleted`

这意味着无需将管道重定向到文件,然后检查数据以查看内容是否有效。vi直接执行命令,u如果出错则ndo。


或者,将行作为命名缓冲区拉出允许您将其作为ex命令执行,几乎就像宏一样。您仍然可以编辑和undo 该行以使其正确,而不是尝试:在命令模式下编辑该行。

这里推荐的功能都是POSIX并且已经支持了 40 多年,所以不需要特殊的vim或其他增强功能。

:%s/meep/pEEp/ | g/foo/ s//BAR

foo
grok
meep
~
~

ex命令(第 1 行,:%s...)拉到命名缓冲区/宏中。

我只是使用“宏”的标签m

"myy

或者

:1y m

现在在命令模式下执行命名的缓冲区/宏,使用@

@m

结果:

:%s/pEEp/pEEp/ | g/BAR / s//BAR

BAR
grok
pEEp
~
~
4 lines changed

但请记住,“多次撤消”不是POSIX。 undo 只是“历史上准确且合规” ex/vi实现中的撤消和重做之间的切换。
解决方法是在执行有问题的编辑之前保存到临时(或有效)文件名:

:w $$.tmp

然后只是:e!在需要时“重置并重新加载”。


您还可以在进行多项更改之前使用:pre(保留)制作特殊的临时备份文件。然后使用:reco! %(恢复这个!)恢复到那个点。意识到:preserve创建一个类似快照的文件,一旦它回滚就被删除。是否保存编辑并不重要。因此,编写您自己的文件 ( :w ...) 并使用恢复:e!可能仍然有价值,因为系统不会自动删除它。

:pre当您应该运行sudo vi ...或没有必要的权限时是完美的 - 但您只是在进行了几次更改后才意识到错误。vi /etc/sudoers代替sudo vi /etc/sudoers.
^^永远不要这样做!只是一个例子!改用sudo visudo

您可以获取现有恢复文件的列表,并根据需要vi -r直接使用恢复文件,也可以选择使用.vi -r filenamesudo vi -r filename

这里的区别在于,即使“ :preserved 文件”在内部有自己的“特殊”名称和路径,它也会在“ ed ==> :write时到达原始的预期位置,但请 务必使用,而不是像完成你的“恢复”,否则您仍然会丢失您尝试保存的编辑。:recover/etc/sudoers:wq!ZZ

顺便说一句,^R预计会根据 POSIX 重绘或重绘显示;vi在任何合规的实现中,它都不是“撤消” 。

于 2021-10-10T20:33:03.930 回答