redirecting vim :make output to file - vim

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

Related

Can't run a script with fzf from vim

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()

Vim :make, :grep making shell fg first [duplicate]

I've been trying to experiment with using :make recently but I don't like that vim has to switch to showing the shell output first and require one enter keypress, then it shows me what I think is a list of the collected errors based on 'errorformat' which I also need to confirm by pressing enter. I would prefer to just have a short "OK" message that does not require confirmation by a keypress, or that vim would open the :cwindow if there were any errors.
I'm using next line just for exact purpose you wrote:
nnoremap <leader>m :silent make\|redraw!\|cc<CR>
cc in the end shows first error or No errors message if this is the case.
You can map for example F9 to use gcc for small C snippets that don't require libraries, linking, etc:
map <F9> :!gcc -o %< % <enter><CR><C-w>
This will produce for the file foo.c the binary foo. I know that's not exactly what you want, but this doesn't show any shell and is useful for small c snippet.
Try:
:silent make
To automatically open the quickfix window after you run make, you can put this into your .vimrc:
autocmd QuickFixCmdPost * :copen

display 'make' output in 'vim'

I want to :make and display output from it only if it fails.
I map to
:wa<cr>:make<cr><cr>
and only when it fails I want to see the results. Notice the
<cr><cr>
sequence, which closes the output because usually it's success and nothing to read. And it's much faster.
You want to use :silent to stop the output and use :cwindow to open the quickfix window when there is something to see.
:wa|silent make|cwindow<cr>
Note: you will want to use <bar> instead of | if this is inside a mapping. Example of a mapping below:
nnoremap <f9> :wa<bar>silent make<bar>cwindow<cr>
See the following for more information:
:h :silent
:h :cw

How do I automatically re-load a file that gets modified by a bang (!) commandin Vim?

I have set up a line of vimscript in my .vimrc file to pretty print JavaScript files:
nnoremap <leader>p :!js-beautify -r -j %<cr>
I want to just automatically reload the file instead of being prompted when vim comes back from the shell, is that possible? Thanks.
:! can be used a) to execute arbitrary shell commands or b) as a filter.
You are using it to run js-beautify against the file associated with the current buffer with the following consequences:
You are forced to exit Vim.
The file is modified outside of Vim so you get a prompt asking you if you want to reload or not.
Hence the many seemingly pointless <CR>.
What you actually want is to run js-beautify as a filter against the current buffer, which doesn't require you to exit Vim or press <CR>:
nnoremap <leader>p :%!js-beautify -f - -j<cr>
the special range % represents the whole buffer, it's the range on which we want to apply our filter
-f - passes the content of the buffer via stdin
That's it: no <CR>, no prompt, no mess.
As a bonus, here is a custom command from my config (I didn't want a mapping for that):
command! -buffer -range=% Format execute <line1> . "," . <line2> . "!js-beautify -f - -j -B -s " . &shiftwidth
edit
You can use context marks to return the cursor to its initial position:
nnoremap <leader>p m`:%!js-beautify -f - -j<CR>``
As the help for :! notes:
Vim redraws the screen after the command is finished,
because it may have printed any text. This requires a
hit-enter prompt, so that you can read any messages.
To avoid this use:
:silent !{cmd}
The screen is not redrawn then, thus you have to use
CTRL-L or ":redraw!" if the command did display
something.
So if you wanted to use the :redraw! approach, for example, you could do this using something like
nnoremap <leader>p :silent !js-beautify -r -j %<cr>:e!<cr>:redraw!<cr>

How to show the output from the last shell command run in vim? (e.g., :!echo foo)

When I run a shell command it asks to type ENTER at the end and once you do the output is hidden. Is there a way to see it again w/o running the command again?
Also some internal commands like make also run external commands, and those do not even stop for ENTER so if I have an error in my 'compiler' settings the command flashes on the screen too fast to see it. How do I see the command and its output? (quickfix is empty)
UPDATE
The output is DEFINITELY still there. at least on the terminal vim. if I type
:!cat
the output of the previous command is still there. the problem is a) it seems too much like a hack, I'm looking for a proper vim way b) it doesn't work in gui vim
just type :!
or you could try SingleCompile
Putting vim into the background normally works for me (hit Ctrl+Z).
This will show you the shell you started vim from and in my case I can see the output of all the commands that I ran in vim via ":!somecommand".
This is assuming that you ran vim from a shell, not the gui one (gvim).
Before executing a command, you can redirect output to a file, register, selection, clipboard or variable. For me, redirecting to a register is the most practical solution.
To start redirecting to register a, use
:redir #a
Then you run your commands, say
:!ls -l
And end redirecting with
:redir END
That's all, register a now contains the output from the redirected commands. You can view it with :reg a or put into a buffer with "ap, as you would do normally with a register.
Read the help for :redir to know more about the various ways of redirecting.
After months, I found a help file that you may be interested in taking a look: messages.txt.
Though incomplete, it helps a lot. There is a command (new to me) called g< that displays the last message given, but apparently only the Vim messages, like [No write since last change].
First, I suggest you to take a look in your settings for 'shm', and try to make your commands output more persistent (the "Hit ENTER" appearing more often). Then, check if this help file helps :-) I couldn't make it work 100%, but was a great advance.
Why I do not use :! anymore, and what is the alternative
I learn the :! from the currently chosen answer (and I upvoted it). It works, in a sense that it does show the previous screen.
However, the other day I learn another tip of using :!! to re-run the last command (which, by the way, is very useful when you are in a edit-test-edit-test-... cycle). And then I realize that, using :! somehow has a side effect of forgetting the last command, so that future :!! won't work. That is not cool.
I don't understand this, until I take a deep dive into vim's documentation.
:!{cmd} Execute {cmd} with the shell.
Any '!' in {cmd} is replaced with the previous
external command
Suddenly, everything starts to make sense. Let's examine it in this sequence:
Assuming you first run :!make foo bar baz tons of parameters and see its output, later come back to vim.
Now you can run :!!, the second ! will be replaced with the previous external command, so you will run make foo bar baz tons of parameters one more time.
Now if you run :!, vim will still treat it as "start a (new) external command", it is just that the command turns out to be EMPTY. So this is equivalent to you type an empty command (i.e. hitting ENTER once inside a normal shell). By switching the screen into shell, you happen to get a chance to see the previous screen output. That's it.
Now if you run :!!, vim will repeat the previous command, but this time, the previous command is an empty command. That's why your vim loses the memory for make foo bar baz tons of parameters so that next time you wanna make, you will have to type them again.
So, the next question will be, is there any other "pure vim command" to only show the previous shell output without messing up the last command memory? I don't know. But now I settle for using CTRL+Z to bring vim to background, therefore shows the shell console with the previous command output, and then I type fg and ENTER to switch back to vim. FWIW, the CTRL+Z solution actually needs one less key stroke than the :! solution (which requires shift+; shift+1 ENTER to show command screen, and a ENTER to come back).
I usually exit to the shell using :sh and that will show you the output from all commands that has been executed and did not have it's output redirected.
Simply close the shell and you will be back inside of vim.
Found this script -- which will open up a new tab
function! s:ExecuteInShell(command)
let command = join(map(split(a:command), 'expand(v:val)'))
let winnr = bufwinnr('^' . command . '$')
silent! execute winnr < 0 ? 'botright new ' . fnameescape(command) : winnr . 'wincmd w'
setlocal buftype=nowrite bufhidden=wipe nobuflisted noswapfile nowrap number
echo 'Execute ' . command . '...'
silent! execute 'silent %!'. command
silent! execute 'resize ' . line('$')
silent! redraw
silent! execute 'au BufUnload <buffer> execute bufwinnr(' . bufnr('#') . ') . ''wincmd w'''
silent! execute 'nnoremap <silent> <buffer> <LocalLeader>r :call <SID>ExecuteInShell(''' . command . ''')<CR>'
echo 'Shell command ' . command . ' executed.'
endfunction
command! -complete=shellcmd -nargs=+ Shell call s:ExecuteInShell(<q-args>)
Paste it in your .vimrc
It works on gui vim too..
Example Usage -- :Shell make
Scroll up (tested on iTerm 2). Note: this might not work depending on your vim configuration..
Example: I'm about to run !rspec --color % from my vim.
The buffer is filled with the output.
Now, after hitting ENTER, you can scroll up to see the previous output.
maybe the guys are forgetting about the :r
r !ls ~/
Put this where my cursor is:
bug_72440.html
bug_72440.vim
Desktop
dmtools
Docear
docear.sh
Documents
Downloads
examples.desktop
index.html
linux_home
Music
Pictures
Public
Templates
A simple u could get rid of the new text after I yank it or whatever;
Commands like make save their output to /tmp/vsoMething. The errorfile setting seems to be set to the file backing the quickfix/location list. If you want the output to be somewhere specific, see makeef. You can open the current errorfile like this:
:edit <C-r>=&errorfile<CR>
(Unfortunately, this doesn't seem to work for :grep.)
redir doesn't have to be tedious. See this plugin for simplifying it. (I have ftdetect and ftplugin scripts to make the output buffer not backed by a file.)
You see the output on the terminal when you type :!cat because of your terminal, not vim. You'd see the same thing if you used Ctrl-z which suspends vim so vim isn't actively doing anything.

Resources