Vitaly Kushner
Vitaly Kushner

Reputation: 9455

How to show the output from the last shell command run in vim? (e.g., from ":!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

Upvotes: 58

Views: 34675

Answers (9)

RayLuo
RayLuo

Reputation: 19290

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:

  1. Assuming you first run :!make foo bar baz tons of parameters and see its output, later come back to vim.
  2. 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.
  3. 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.
  4. 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).

Upvotes: 16

MaikoID
MaikoID

Reputation: 5007

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;

Upvotes: 4

user1703082
user1703082

Reputation: 714

just type :! or you could try SingleCompile

Upvotes: 69

chibicode
chibicode

Reputation: 4419

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.

enter image description here

The buffer is filled with the output.

enter image description here

Now, after hitting ENTER, you can scroll up to see the previous output.

enter image description here

Upvotes: 2

Wolf7176
Wolf7176

Reputation: 317

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

Upvotes: 2

sidyll
sidyll

Reputation: 59297

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.

Upvotes: 29

idbrii
idbrii

Reputation: 11946

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.

Upvotes: 0

holygeek
holygeek

Reputation: 16185

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

Upvotes: 39

Sedrik
Sedrik

Reputation: 2221

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.

Upvotes: 8

Related Questions