在Vim中同时保存并运行的方法

54

我经常使用Python进行快速模拟,需要不断地保存(:w),然后运行(:!!)。有没有一种方法可以将这两个操作组合起来?

也许可以使用“保存并运行”命令。


你能看一下我的回复吗?我认为它正确地回答了你的问题。 - Douglas Mayle
12个回答

86

好的,最简单的方法是使用管道命令。它允许您在同一行上运行多个命令行命令。在您的情况下,这两个命令是写入 `w` 和执行当前文件 `!%:p`。如果您有一个特定的命令用于运行当前文件,则第二个命令变为,例如`!python %:p`。因此,对于您的问题,最简单的答案如下:

:w | ! %:p
 ^ ^ ^
 | | |--Execute current file
 | |--Chain two commands
 |--Save current file

最后需要注意的一点是,并非所有命令都可以被链接在一起。根据Vim文档所述,某些命令接受一个管道作为参数,因此会中断链式操作...


3
一条命令搞定。这就是我想要的答案,不需要脚本或映射。我之前不知道 | 用于链接命令。谢谢! - dwerner

31

选项1:

编写一个类似于这个函数的函数,并将其放置在启动设置中:

function myex()
   execute ':w'
   execute ':!!'
endfunction

你甚至可以将一个键组合映射到它上面--查看文档。


选项2(更好):

查看重新映射按键的文档 - 你可能可以通过简单的按键重映射来实现它。以下代码有效,但硬编码了“filename.py”。或许你可以深入挖掘并找出如何用当前文件替换它?

:map <F2> <Esc>:w<CR>:!filename.py<CR>

映射完毕后,您只需在命令模式下按下F2

imap、vmap等是不同模式下的映射。上述内容仅适用于命令模式。以下内容也适用于插入模式:

:imap <F2> <Esc>:w<CR>:!filename.py<CR>a

Vim手册的40.1节非常有用。


1
请查看 expand 选项以获取文件名。我认为 expand("%:p") 可以获得文件名。 - Caleb Huitt - cjhuitt
7
刚刚测试过,效果很好。请将“map <F5> <Esc>:w<CR>:!%:p<CR>”(不含引号)添加到您的vimrc文件中。 - mechanical_meat

18

使用autowrite选项:

:set autowrite

如果文件已被修改,在每个 :next、:rewind、:last、:first、:previous、:stop、:suspend、:tag、:!、:make、CTRL-] 和 CTRL-^ 命令中,将文件的内容写入。


这太棒了! - Amir Shabani

7

Here you go:

:nmap <F1> :w<cr>:!%<cr>

保存并运行(您必须处于n模式中 - 只需添加esc和一个for i模式)。


对于设置了x位并且第一行为#!/bin/bash/env python的Python脚本,在$HOME/.vimrc中使用map <F1> <Esc> :w<CR> :!./%<CR>可以正常工作(map或nmap,F1或其他键)。 - lllluuukke

5

命令组合似乎可以通过 | 字符实现,因此可以将类似于 :w|!your-command-here 的别名绑定到一个独特的按键组合上。


4

另外一种可能性:

au BufWriteCmd *.py write | !!

尽管这会在每次保存时运行,但这可能并不是您想要的。

4
在Vim中,您可以简单地将当前缓冲区的任何范围重定向到外部命令(无论是Bash、Python解释器还是您自己的Python脚本)。
# Redirect whole buffer to 'python'
:%w !python

假设您当前的缓冲区包含以下两行内容,
import numpy as np
print np.arange(12).reshape(3, 4)

然后,:%w !python 将运行它,无论是否保存。并在终端上打印类似下面的内容,
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

当然,您可以使一些键映射(keymaps)持久化。
nnoremap <F8> :.w !python<CR>
vnoremap <F8> :w !python<CR>

第一个是运行当前行。第二个是通过Python解释器运行可视化选择。
#!! Be careful, in Vim ':w!python' and ':.w !python' are very different. The
first write (create or overwrite) a file named 'python' with contents of
current buffer, and the second redirects the selected cmdline range (here dot .,
which mean current line) to external command (here 'python').

命令行范围,请参见

:h cmdline-ranges

不是下面这个,它涉及普通命令,而不是cmdline命令。
:h command-range

这是受到从Vim中执行当前行的Bash命令启发而来的。


实际上,这个答案更像是IDE的答案。现代IDE在“运行”之前不会保存文件。我点赞这个答案。 - minion

2

这是我放在我的.vimrc文件中的代码,可以完美地工作:

nnoremap <leader>r :w<CR>:!!<CR>

当然,在执行此命令之前,您需要运行一次您的shell命令,以便它知道要执行哪个命令。
例如:
:!node ./test.js

1
我从Vim技巧维基上得到了以下内容:
command! -complete=file -nargs=+ shell call s:runshellcommand(<q-args>)
function! s:runshellcommand(cmdline)
  botright vnew
  setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
  call setline(1,a:cmdline)
  call setline(2,substitute(a:cmdline,'.','=','g'))
  execute 'silent $read !'.escape(a:cmdline,'%#')
  setlocal nomodifiable
  1
endfunction

但是我在第三行将new改为vnew,然后对于Python,我有以下内容:
map <F9> :w:Shell python %<cr><c-w>

按下 F9 保存、运行并将输出转储到一个新的垂直分割的临时缓冲区,以便轻松地复制、保存等。它还会按下 c-w,这样我只需要按 h/c 关闭它并回到我的代码即可。

0

尝试在Bash中完成它。

对于名为t.c的C文件,这非常方便:

vi t.c &&  cc t.c -o t && ./t

符号(&&)确保一个错误消息会中断命令链。

对于Python来说,这可能更容易:

vi t.py && python t.py

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接