I know nothing about compiling but if I understand you correctly, you want a vim command that can be used without argument to execute a shell command.
And if the same vim command is used with arguments, it should execute a different shell command on them.
I've come up with a template that maybe you could adapt to your specific needs and that seems to do what you want :
function! CompileFiles(...)
if a:0 == 0
!echo "Compile without argument"
else
execute "!cat " . join(a:000)
endif
endfunction
command! -nargs=* Com call CompileFiles(<f-args>)
In this template, the Com
command is defined at the end and calls the CompileFiles()
function that is defined just above.
The command passes the arguments it receives to the function.
Inside the latter you can test the number of arguments with a:0
and access the list of arguments with a:000
.
The function tests the number of arguments it has received :
- if it's 0 it executes the shell command
echo "Compile without
argument"
- if it's more, all the arguments are concatenated (with the built-in
join()
function) into a string which in turn is concatenated at the end of "!cat "
.
The content of the resulting string is then executed.
For example, if you type :Com foo bar
, the function should execute !cat foo bar
.
What you want is different.
You want to write the current file (w
) and then (|
) execute the shell (!
) command gcc -Wall %:p -o %:p:r
if no argument follows the command, or execute gcc -Wall <args> -o compiled
if there are arguments.
I think the previous code could be modified like this :
function! CompileFiles(...)
if a:0 == 0
write
!gcc -Wall %:p -o %:p:r
else
write
execute "!gcc -Wall " . join(a:000) . " -o compiled"
endif
endfunction
command! -nargs=* Com call CompileFiles(<f-args>)
Not sure it will work though.
One last thing, before passing some arguments to the shell it's often recommended to escape them. There's a built-in function that does it : shellescape()
I know how to use it on a specific argument :
shellescape(a:foo)
will escape the argument whose name is foo,
shellescape(a:1)
will escape the first argument of the optional group (the one that is symbolized by ...
in the previous code), etc.
but I don't know how to escape a list of arguments whose size is unknown.
Edit : I've tried to modify the code a little bit to escape the arguments in case they contain special characters :
function! CompileFiles(...)
let mylist=[]
let c = 0
while c < a:0
let myarg = shellescape(a:000[c])
call add(mylist, myarg)
let c += 1
endwhile
if a:0 == 0
write
!gcc -Wall %:p -o %:p:r
else
write
execute "!gcc -Wall " . join(mylist) . " -o compiled"
endif
endfunction
command! -nargs=* Com call CompileFiles(<f-args>)
The only thing that changes is the creation of a mylist
variable and a while
loop that executes the shellescape()
function on each argument received by the main function.
I didn't test it as I don't have anything to compile.
ComC
andComM
, for "compile current" and "compile many". Still, it's an interesting question, even if the answer is just "It can't be done".Makefile
(that has as targets either the whole binary, or just a single object - so it would solve both of your problems)? You will then just have to run:make
from Vim AND you get any errors in the quickfix window.