Vim open file determined by external script - vim

I have a line in one of my functions
silent! exec "r!sh myScript '" . a.1 "'
this prints the output of myScript to the current buffer.
myScript outputs a single filename. Instead of printing the filename to the buffer I'd like to open that file.
I've tried things like
silent! exec "open!sh myScript '" . a.1 "'
silent! exec "new!sh myScript '" . a.1 "'
let l:file = silent! exec "sh myScript '" . a.1 "'
new l:file
but none seem to work.
Am I missing something obvious?

I would suggest using the system() function in this way:
let path=system("myScript ... ")
let path=substitute(path,"\n","","g")
exec "edit" path
Note that the intermediate substitute command may be necessary to remove erroneous newline characters. If it isn't necessary, don't worry about it. Of course, instead of edit you can use split or vsplit etc to suit your needs.

Related

How to replace selected text in vimscript

I have some specific parts of files with unformated xml code. I need to write a vimscript function that selects the text and calls xmllint over it.
I know I can do this on the command line :'<,'>!xmllint --format -
But I really need to do the same in a vimscript function and I don't know how to make something like normal! call for visual.
I tried this but it does not work correctly :
function! MyFormat()
... stuff done here
let startl = line("'<")
let endl = line("'>")
let line = getline(startl, endl)
let r = system('echo "' . join(line, "") . '" | xmllint --format -')
call setline('.', r)
endfunction
Every line in a Vim script is an Ex command. Since you already have a working Ex command, you might as well use it.
function! MyFormat()
" ... stuff done here
'<,'>!xmllint --format -
" ... more stuff done here
endfunction
But, again, data is missing so this might work… or not, be sufficient… or not, etc.

pipe string to bash command in a function

I have a string (as a result of another function, but for now let's store it in s for sake of simplicity) and I want to write it out, through a pipe to a bash command. (It has to be a pipe, the command does not accept this kind of input as an argument.)
So the question is, how should I invoke mycommand, that is, what goes to ...?
function! MyFunc()
let s = "my string"
execute ... !mycommand --flag
endfunction
Via here string:
:let s = "my string"
:set shell=/bin/bash
:exe "!cat <<< " . shellescape(s)
Output
my string
Via pipe:
:exe "!echo " . shellescape(s) . " | cat "
Could you try this
:execute "!\"".s."\" | mycommand"

Write a simple Vim script to compile java code, and found expand() function return weird path name in Vim script

I try to write a simple Vim script to compile java code in Vim.
function! CompileJava()
let path = expand("%")
exec ":!javac " . path
let className = expand("%:p:r")
exec ":!java " . className
endfunction
I got error when I run following line
exec ":!java " . className
className is '.home.javacode.test' instead of '/home/javacode/test'
Does anyone know why all the slashes in className are replaced with dot?

Vim. set command line from a function

I'm trying to write a function that replaces text in all buffers. So I call Ack to search all the matches and next step I want to set into Quickfix command line this code
:QuickFixDoAll %s/foo/boo/gc
Seems like I can only call 'exec' function which runs this command immediately and there is no ablility to edit it or cancel at all
I also tried "input" function to read user input but got this error at runtime
not an editor command
Any ideas?
.vimrc:
function! ReplaceInFiles(o, n)
exec "Ack '" . a:o . "'"
exec "QuickFixDoAll %s/" . a:o . "/" . a:n . "/gc"
endfunction
" QuickFixDoAll
function! QuickFixDoAll(command)
if empty(getqflist())
return
endif
let s:prev_val = ""
for d in getqflist()
let s:curr_val = bufname(d.bufnr)
if (s:curr_val != s:prev_val)
exec "edit " . s:curr_val
exec a:command
endif
let s:prev_val = s:curr_val
endfor
exec "quit"
endfunction
command! -nargs=+ QuickFixDoAll call QuickFixDoAll(<f-args>)
Using input()
This queries both values interactively:
function! ReplaceInFiles()
let l:o = input('search? ')
let l:n = input('replace? ')
exec "Ack '" . l:o . "'"
exec "QuickFixDoAll %s/" . l:o . "/" . l:n . "/gc"
endfunction
nnoremap <Leader>r :call ReplaceInFiles()<CR>
Incomplete mapping
nnoremap <Leader>r :let o = ''<Bar>exec "Ack '" . o . "'"<Bar>exec "QuickFixDoAll %s/" . o . "//gc"<Home><Right><Right><Right><Right><Right><Right><Right><Right><Right>
This one puts the cursor on the right spot for the search. As this value is used twice (Ack and QuickFixDoAll), it is assigned to a variable. After that, move to the end of the command and fill in the replacement in between the //gc.
Custom parsing
The most comfortable option would be a custom command :AckAndSubstAll/search/replacement/. For that, you'd need to parse the two parts in the custom command (like :s does). You could do that with matchstr(), or use ingo#cmdargs#substitute#Parse() from my ingo-library plugin.
First use vim-qargs to copy all files from the quickfix window into Vim's arglist by calling :Qargs.
Then run your replace on all arguments in the arglist by doing :argdo %s/search/replace/gc

vim function system invalid argument

I'm trying to use the following vim function to run my sas on windows, but I always got error message saying the argument for system is invalid.
Could some vim expert help me out?
myy sas is installed in:
C:\Program Files\SAS\SAS\9.1\sas.exe
function! RunSASonCurrentFile()
" Make sure this is a SAS program file (ends with .sas) so that
" we don't run SAS on a log file or similar.
:let checkSASpgm=match(expand("%"),"\.sas")
" If we did not match .sas in the file name, end this function with
" a warning msg
if checkSASpgm==-1
:echo "*** Current file is not a SAS program. SAS run has been canceled."
:return
endif
" Ask user if we want to run SAS so we don't accidentally run it.
:let l:answer = input("Run SAS? Y/N ")
:if (l:answer == "Y" || l:answer == "y")
" If file has been modified, save it before running
if exists(&modified)
:echo "*** Saving modified file before SAS run..."
:w
endif
" Run SAS on path/file name (modify to your location of sas)
:echo "*** Running SAS..."
"let returntxt = system("/usr/local/bin/sas -nodms " . shellescape(expand("%:p")))
" The following may work for your Windows system. Comment the line above and uncomment
" the two lines below and make them one long line.
let returntxt = system("\"" . shellescape("C:\\Program\ Files\\SAS\\SAS\9.1\\sas.exe")
". "\ -nosplash" . "\ -sysin" . "\ " . shellescape(expand("%:p")) . "\"")
" Shows the return messages from the SAS commandline (may be useful
" if no log produced)
:echo "*** SAS commandline: " . returntxt
:call LoadSASLogList()
:else
:echo "SAS Run cancelled."
" endif for the Run SAS? check
:endif
endfunction
Vim patch 7.3.443 changed the behavior of the shell escaping (which continues to be a trouble spot, due to the arcane Windows shell escaping rules). Whereas beforehand, one had to enclose the entire command line in double quotes if it contained a (itself quoted) executable with spaces in it, these now have to be removed. Try the following:
let returntxt = system(shellescape('C:\Program Files\SAS\SAS\9.1\sas.exe') . ' -nosplash -sysin ' . shellescape(expand('%:p')))
This also avoids some additional escaping by using single quoted strings.
If that's the exact text of your function, I think you're missing a second \ between SAS and 9.1 in the line let returntxt = system("\"" . shellescape("C:\\Program\ Files\\SAS\\SAS\9.1\\sas.exe").

Resources