如何在Vim中的文本中插入命令的结果?


42

例如,:echo strftime(%c)将在底部显示当前时间,但是如何将此时间字符串插入文本(光标之后)?


1
我相信OP的意思是“如何在文本中插入Vim表达式的结果?”
Alastair Irvine

另外值得一提的是,这是一样的问题写了vim的函数来插入静态文本块,但一些问题的答案仍然适用。
Alastair Irvine

您的示例实际上是我的用例,因此我向您致敬。

参见重定向到寄存器:stackoverflow.com/questions/2573021/...
NeilG

Answers:


49

可以使用表达式寄存器,"=p(或P在正常模式下或<C-R>在插入模式:

在正常模式下:
<C-M>在这里意味着Control+ M,或者只是按Enter/ Return

"=strftime('%c')<C-M>p

在插入模式:
<C-M>具有相同的含义如上,<C-R>装置Control+ R

<C-R>=strftime('%c')<C-M>

如果要多次插入同一表达式的结果,则可能需要将它们映射到您的.vimrc:上的键上
(此处,<C-M>and <C-R>应该按字面值键入(五个可打印字符的序列,Vim会在内部对其进行翻译))

:nmap <F2> "=strftime('%c')<C-M>p
:imap <F2> <C-R>=strftime('%c')<C-M>

2
+1偏离路线!该"=寄存器。:-/
Eelvex

2
获取vim变量的值(例如,sessionoptions):<C-R>=&sessionoptions-它甚至可以执行通配符制表符!
贾斯汀·凯斯

2
:put = strftime('%c')<CM>
brunch875

在插入模式下,使用<c-r>=命令的速度很慢,该命令可能会有很多输出,并且还可能破坏缩进,因此输出文本不可读。例如,<c-r>=execute('nmap')输出将逐行写入,这非常慢。
jdhao

22

:r!date +\%c

看到 :help :r!


1
date是一个外部命令,!在OP询问vim命令时调用外部命令。
Eelvex 2011年

@eelvex不,他没有。和!是vim和vi命令。这是规范方法。同样适用于许多其他事情。
基思

5
@Keith:是的!是调用外部命令的vi(m)命令。您可能是对的,OP不希望仅输出vim命令,但是如果不输出,!则不会。
Eelvex

11

这些命令将strftime("%c")在光标所在的位置插入right 的输出:

:exe ":normal i" . strftime("%c")

:call feedkeys("i". strftime("%c"))

还有其他方法可以做您想要的事情(例如,关于Mikel的答案)。

编辑:更好,就地插入,使用克里斯·约翰森描述=寄存器


10

如果要插入vim 命令的输出(而不是函数调用返回值),则必须捕获它。这是通过:redir命令完成的,它使您可以将vim的标准输出重定向到变量,文件,寄存器或其他目标。

:redir使用起来有点痛苦不便;我会写一个函数以更方便的方式封装其功能,例如

funct! Exec(command)
    redir =>output
    silent exec a:command
    redir END
    return output
endfunct!

声明了此类函数后,就可以使用表达式寄存器(如Chris Johnsen所述)将命令的输出插入光标位置。因此,在普通模式下,点击i^R=Exec('ls')插入vim当前缓冲区的列表。

请注意,该命令将在函数名称空间中执行,因此,如果您使用全局变量,则必须在其前面加上前缀来显式命名该名称空间g:。还要注意Exec(),如上文所述,即使在一行输出中,也会添加一个终止换行符。您可能希望将调用添加substitute()到函数中以避免发生这种情况。

另请参阅https://stackoverflow.com/questions/2573021/vim-how-to-redirect-ex-command-output-into-current-buffer-or-file/2573054#2573054,以获取更多有关的信息redir以及指向的链接相关命令。


2
这很好。我set paste在返回输出之前和set nopaste之后添加了一条命令,以避免行以空格开头时阶梯缩进。实际上,我想保存当前粘贴选项的值并返回它,但我无法这样做。
胡安·拉努斯

1
@JuanLanus在set nopaste之后不应该工作return output,因为return语句是函数的退出点。我已将此问题的解决方案作为单独的答案放在此页面上。
Evgeni Sergeev

4
:call append(line('.'), strftime("%c"))

将其放在下一行,然后可以按JShift+ J)将其加入到当前位置。

或者,如果您只需要一个命令就可以完成所有操作

:call setline(line('.'), getline(line('.')) . strftime("%c"))

要么

:call setline(line('.'), getline(line('.')) . " " . strftime("%c"))

取决于您是否要在日期之前插入空格。


4

改进@intuited答案以避免领先的空格和缩进的问题:

"Examples:
":call Exec('buffers')
"This will include the output of :buffers into the current buffer.
"
"Also try:
":call Exec('ls')
":call Exec('autocmd')
"
funct! Exec(command)
    redir =>output
    silent exec a:command
    redir END
    let @o = output
    execute "put o"
    return ''
endfunct!

:call Exec('command')普通模式下,这只会插入文件的当前位置。如评论中所述,可以使用来部分地纠正原始的(插入模式)Ctrl + R =Exec('command')方法(Exec(..)返回字符串)set paste,但不能提供放置set nopaste任何位置的机会。

let @o = output语法设置寄存器o到变量的内容output,如下解释:https://stackoverflow.com/a/22738310/1143274

return ''行是为了确保0不会将默认返回值插入到缓冲区中。


2

这就是我的方法。由于使用,因此将其放在光标之后p

" save previous yank
let reg_save = @@

" save your text to the '@' register
let @@ = strftime('%c')
" paste it after the cursor
exec "normal! p"

" restore previous yank
let @@ = reg_save
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.