Reputation: 4505
I'm trying to make a key mapping in vim that (a) saves current file (b) performs a git action, using shell (c) quits current vim editor.
I've tried the following methods but still can't figure it out.
Method 1 - in Vim command line
:w | !git commit -am "auto" | q
Method 2 - in .vimrc
map :W :w \| !git commit -am "auto"
map :L :Wq
Problem
The problem is that the pipe |
can only be used to append shell commands. How do I do 'a Vim command' + 'a shell command' + 'a Vim command'
? How to pipe a vim command after a shell command?
Upvotes: 7
Views: 3691
Reputation: 29332
There are 3 scenarios I see here:
If you want to add a new vim command, so that typing :W
would write the buffer, do git commit and quit vim, you'll need to follow JonnyRaa's answer. Namely, define a function, and then define a command that executes that function:
function! WriteCommitAndQuit()
w
silent !git commit -am "auto"
q
endfunction
command! W call WriteCommitAndQuit()
Notes:
:
to go into command line mode.silent
to avoid getting the "Press ENTER or type command to continue" prompt.write
and quit
instead of w
and q
, for nicer-looking code. (Conversely, silent
can be shortened to sil
if you're in a hurry...)If you want to just be able to hit a single key to run these commands, you'll need to add a mapping, and the trick for putting a shell command in the middle is to use <CR>
to simulate hitting ENTER:
map <F10> :w<CR>:silent !git commit -am "auto"<CR>:q<CR>
Notes:
:
and typing it directly.silent
, you can just add an extra <CR>
after the shell command.Sometimes there's a sequence of commands you want to run repeatedly, but they're not worth bothering to persist into vimrc, since they are ad-hoc and won't be useful in the future. In this case, I just execute the line and then rely on the up arrow to bring the line again from history and execute it. In this case, the trick is to add an escaped LF character in the middle of the command, using Ctrl-V, Ctrl-J:
:w | silent !git commit -am "auto" ^@ q
Notes:
^@
in the command is what gets shown when I hit Ctrl-V, Ctrl-J. It won't work if you hit Shift-6, Shift-2. However, it does seem to work if I hit Ctrl-Shift-2.]
is the 27th letter of the ABC.Upvotes: 1
Reputation: 322
:echo expand('ls') | echomsg 'test'
:!ls | echomsg 'test'
Upvotes: 0
Reputation: 8038
This feels related as I ended up here!
So if you want to bind this in a command you won't be able to use <cr>
and pipe also won't work.
In that case the right thing to do is use a function and just call the function from that command.
In this example I had a shell script to grep some log files for errors and output the result into .errors, which then gets opened in the quickfix. The redraw is because silent messes your screen up with external commands!
function! ReadErrors()
silent !read-errors
redraw!
cfile .errors
endfunction
command! ReadErrors call ReadErrors()
Upvotes: 1
Reputation: 885
i use this command to copy current file path to system clipboard.
map <silent> <leader>vv :echo expand('%:p') \| !syscopy.sh <cr>
Upvotes: 0
Reputation: 353
Have you tried vim-fugitive?
You can git commit -am using that plugin and then add your git command.
So you would write something like:
Gcommit -am "auto"
I tested it briefly. I've put this into my .vimrc:
function! CommitAndQuit()
execute "Gcommit -am 'auto'"
execute "q"
endfunction
Then type :call CommitAndQuit()
and it will do what you want.
Upvotes: 1
Reputation: 196476
You need to execute those three commands separately. This is what <CR>
is for:
nnoremap <key> :w<CR>:!git commit -am "auto"<CR>:qa<CR>
Upvotes: 4