I have a bash script that assembles some data, then pipes it through fzf for the user to choose, then manipulates the choice, then prints it to stdout.
This simulates the script:
#!/bin/sh
echo hello | fzf | sed 's/h/j/g'
This works great from the command line, but when running it from vim to include in the current buffer, the fzf TUI never displays, and I get ANSI escape sequences included in the result:
It doesn't matter how I run the command from vim. I've tried :read !{cmd}, :.!{cmd}, and even :let a=system('{cmd}').
For example, I would expect this to work:
:read !echo hello | fzf | sed 's/h/j/g'
fzf seems to be confusing stdout for a tty.
I know this isn't a limitation of vim, since if I substitute fzf for another interactive chooser with a tty, it works.
Is there an fzf or vim option to make this work?
Vim doesn't deal with interactive commands that easily. As you've seen, fzf outputs a lot of code to manipulate the display, and read is expecting a raw result.
You can do this with execute instead of using read directly.
Building off another answer ( Capture the output of an interactive script in vim ) but changing things up to work with fzf, I've modified #joshtch's solution to work with an arbitrary script, and checked that it works with fzf:
my-fzf-script.sh:
#!/bin/sh
ls | fzf
and the vim side of things:
function! <SID>InteractiveFZFCommand()
let tempfile=tempname()
execute '!./my-fzf-script.sh >' . shellescape(tempfile)
try
silent execute 'read' tempfile
finally
call delete(tempfile)
endtry
endfunction
command! -nargs=0 InteractiveFZFCommand call <SID>InteractiveFZFCommand()
Related
Rather than having vim print the output of the :make command, I want to read the output in a file (which gets updated automatically in vim); so that my compiled file can run right away without having to see the output of the :make command.
I'm using the following makefile
all: compile run
compile: file.cc
g++ -o file file.cc
run: file
./file
How does one redirect the output of the :make command in a way that it isn't also printed to the screen by vim?
First of all we have https://vi.stackexchange.com/ , you can get better answers about Vim in there.
Second, I'll argue that a Makefile is no place to run a program, the idea behind make is to catch compilation errors. But assuming you have your reasons (e.g. ./file opens a graphical display) there are a couple of ways to perform this in Vim:
For a start you can set makeprg to perform the redirection:
:set makeprg=make\ >/dev/null\ 2>&1
(You can change /dev/null to an actual file)
But that still leaves the line:
Press ENTER or type command to continue
And asks for confirmation, which may be annoying when you know that there is no output.
To get rid of the confirmation line you can use silent as follows:
set makeprg=make\ >/dev/null\ 2>&1
function! MyMake()
silent make
redraw!
endfunction
command Mm call MyMake()
And now you can do:
:Mm
To perform the make and go back to straight to Vim. (the redraw! is needed only in some terminals)
You can execute this command:
:silent exec "!make >Output" | :redraw!
The file Output contains the last output of the executed make command.
Use :silent to remove the output and "press enter" prompt. I suggest a nice mapping or command:
command! -nargs=* Smake silent make <args>
nnoremap <f5> :silent make<cr>
:make will populate the quickfix list with the results from :make. Use :copen to open the quickfix window.
For more help see:
:h :command
:h silent
:h :make
:h 'makeprg'
:h quickfix
I'd like to run a command from vim editor as follows.
:!mplayer %.mp3
The mp3 file contains spoken word related to the opened file.
When I run the command, it will close the vim window.
I'd like the vim window stay open and hear the mp3 file.
When you don't need to read the output of the external command, better use system() over :!, like this:
:call system('mplayer ' . expand('%') . '.mp3 &')
% won't be automatically expanded here, but that's no problem. The & is needed to avoid blocking Vim during playback. The call returns the output of mplayer, but you're apparently only interested in hearing the sound.
The following should do the trick:
:execute 'silent !mplayer %.mp3 &' | redraw!
Source
Maybe you want to run the command on the background? Then add &:
:!mplayer %.mp3&
I have this function to do inverse searches (from the pdf to Vim) when working with LaTeX documents in MS Windows:
function! ViewTex()
if has('win32') || has('win64')
let execstr = 'silent! !start SumatraPDF -reuse-instance '.
\ '-inverse-search "gvim --remote-silent +\%l \%f"'.
\ '%:p:r.pdf'
endif
exec execstr
endfunction
This works fine except that it will not open closed folds. So my question is: how to pass normal zv command to --remote-silent? I tried (without success) the following:
"gvim --remote-silent +\%l|normal\ zv \%f"
Back to your first attempt, in most situations the Windows cmd.exe shell doesn't use '\' to escape anything. So I think you need to surround your init commands in quotes instead of backslash-escaping the spaces. Also, according to :help --remote, the commands in the init must be able to have a following '|' to separate them, meaning normal will not work unless surrounded with an execute command. So in your case something like this will eventually need to execute in the shell:
gvim --remote-silent +"%l|exe 'normal! zv'" %f (with the quotes included)
But I'm not sure whether this allows expansion as desired of %1 and %f.
Edit:
Or, use foldopen! instead of exe 'normal! zv' to avoid the need for spaces or exe at all. But, note this actually opens more folds than just zv; maybe that's OK for you.
From your comments, it looks like whatever platform you're using requires backslash-escaping any '%' characters, so:
gvim --remote-silent +\%l|foldopen! \%f
Edit: The explanation below is slightly wrong but the method is sound. I missed that the --remote family takes an optional "init" command argument; it's part of the --remote-silent command not a new argument to gvim. The explanation below fits for if it was a new argument to gvim.
The problem is that the Vim which runs to send the remote file will also run the +... command, rather than the Vim which actually edits the file. Try using --remote-send or --remote-expr after the --remote-silent, to send the commands you need to run after loading the file.
I.e. something like:
gvim --remote-silent myfile
gvim --remote-send zv
etc.
I have python a code in vim, run it in vim command line, like this:
:!python %
Output is big enough for screen need scrolling to read it all, but vim only display the output with more command to page output, can I change this? use less command to page output.
I can run command with the less using pipe,
:!python % | less
but it seems not handy, have to quit twice to leave.
Try adding this to your .vimrc:
command! -nargs=* -complete=shellcmd R new | setlocal buftype=nofile bufhidden=hide noswapfile | r !<args>
Example usage:
:R python #
Explanation:
:R opens a new buffer and reads the output of the shell command into it. Because the shell command will be executed for THAT buffer and not the current buffer, we need to use # to refer to the current buffer.
I know that using VIM I can format C++ code just using
gg=G
Now I have to format 30 files, so doing it by hand becomes tedious. I had a look how to do it passing external commands to VIM, so I tried
vim -c gg=G -c wq file.cpp
but it does not work.
Can you give me a hint?
Thanks
Why not load all the files up in buffers and use bufdo to execute the command on all of them at one time?
:bufdo "execute normal gg=G"
Change -c gg=G to -c 'normal! gg=G'. -c switch accepts only ex mode commands, gg=G are two normal mode commands.
I prefer a slight change on the :bufdo answer. I prefer the arg list instead of the buffer list, so I don't need to worry about closing current buffers or opening up new vim session. For example:
:args ~/src/myproject/**/*.cpp | argdo execute "normal gg=G" | update
args sets the arglist, using wildcards (** will match the current directory as well as subdirectories)
| lets us run multiple commands on one line
argdo runs the following commands on each arg (it will swallow up the second |)
execute prevents normal from swallowing up the next pipe.
normal runs the following normal mode commands (what you were working with in the first place)
update is like :w, but only saves when the buffer is modified.
This :args ... | argdo ... | update pattern is very useful for any sort of project wide file manipulation (e.g. search and replace via '%s/foo/bar/ge' or setting uniform fileformat or fileencoding).