Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

with vim, if I use

:r!date

vim insert the date in the next line, similar with

:r!pwd

how I can insert the output command under cursor position and no in a new line ?

share|improve this question

2 Answers 2

up vote 5 down vote accepted

With ":read" Vim will always insert the output on a new line. The solution is unfortunately not simple.

You may insert the output of a command at the current cursor position when you are in insert mode by pressing ControlR then typing =system('command')Enter. Unfortunately, if the command's output has a trailing newline (as most will) that will also be inserted, so your line will be broken.

That can be fixed by adding a substitute() call to strip trailing newlines, but that makes the command more trouble than it is worth to type out by hand.

The ultimate solution is to create some sort of mapping, but that gets even more complex due to how Vim handles what it calls "type ahead"; while you can do something like:

:nmap \e i<c-r>=substitute(system('date'),'[\r\n]*$','','')<cr><esc>

Where the command is "hard wired" in the mapping, you cannot do something like:

:nmap \e i<c-r>=substitute(system(input('Command: ')),'[\r\n]*$','','')<cr><esc>

Where you try to prompt the user for the command to run, because Vim will just get confused, beep, and enter insert mode.

So you have to prompt for the command to run first, store it in a variable, and then insert the processed output. At this point a helper function is probably needed to keep the mapping itself from becoming unmanageably messy, so we end up with something like this:

function InlineCommand()
    let l:cmd = input('Command: ')
    let l:output = system(l:cmd)
    let l:output = substitute(l:output, '[\r\n]*$', '', '')
    execute 'normal i' . l:output
endfunction

nmap <silent> \e :call InlineCommand()<CR>

Note that nmap creates mappings that only execute when typed in normal mode.

Incidentally, if you only wanted to insert the date or the current working directory, the initial answer I gave is feasible. Just enter insert mode and type ControlR=strftime('%c')Enter or ControlR=getcwd()Enter.

share|improve this answer

If you want it in the current line you try just, but have in mind the old content of the line will be erased:

:.!date

If you want the exact cursor position you can:

:let a=system("date") | let b=substitute(a,"[\r\n]*$","","g") | exec 'normal i'.b

Long story short: you need to substitute cause you want to get rid of ^@ (null characters) which you can also can replace with .s/\%x00//g. This is a shorter version with less pipes:

:exec 'normal i'.substitute(system("date"),"[\n]*$","","")

And you can also set tags if you want to replace in various points at the same line:

Given this Line 1:

1 Date: <datehere> and also <datehere>

Execute:

:let a=system("date") | exec ".s/<datehere>/".a."/g" | .s/\%x00//g

After Replacement:

1 Date: jue ago 9 02:34:52 ART 2012 and also jue ago 9 02:34:52 ART 2012

Tested on Vim 7.2

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.