Dequoting a vim argument - vim

I want to remove the quotes around a vim argument [<f-args>][0].
The problem I'm having is that when I define a new command and call it with an argument say: MyCommand Blah, this gets called like :MyCommand "Blah". The thing is, I want the argument Blah to be dequoted because I have an enviroment variable that I want to prefix the argument with $ so that the full command actually reads something like :MyCommand $Blah.
How do I dequote the argument?

<f-args> is for passing custom command arguments to a Vimscript function; there, you need quoting to pass those arguments as strings.
If you want to pass arguments to another (built-in or custom) command, just use <args>, which passes the arguments as-is.
If you need to pick apart the arguments, pass some to command X and others to command Y, this again is best done not inline in the :command definition, but in a function, so the <f-args> approach would work just fine.
Example
command! -nargs=* Test call TestFunc(<f-args>)
function! TestFunc( ... )
echomsg 'argument 1 is' a:1
echomsg 'arguments 2, 3 are' join(a:000[1:2])
endfunction

Related

Vim - writing to filename in vimscript variable

I'm doing something like
:let foo="bar"
:echom foo
bar
:w foo
"foo" [New File] 0 lines, 0 characters written
I am expecting/hoping to write a file named "bar", not a file named "foo". Assuming that I have a string stored in a variable "foo", how can I write the current buffer to a file with the name being that string?
As an aside, can someone explain what :w foo and :echom foo are doing different with regards to foo?
Vimscript evaluation rules
Vimscript is evaluated exactly like the Ex commands typed in the : command-line. There were no variables in ex, so there's no way to specify them. When typing a command interactively, you'd probably use <C-R>= to insert variable contents:
:sleep <C-R>=timetowait<CR>m<CR>
... but in a script, :execute must be used. All the literal parts of the Ex command must be quoted (single or double quotes), and then concatenated with the variables:
execute 'sleep' timetowait . 'm'
Like :execute above, the :echo[msg command is particular in that it takes a variable argument, whereas most commands (like :write) do not, and treat the argument(s) literally.
Your particular problem
As above, your issue is best resolved via execute:
:execute 'write' foo
However, note that if foo contains any regular filename, it still needs to be escaped for the :write function, which understands some special notation (e.g. % stands for the current buffer name), and likes to have spaces escaped:
:execute 'write' fnameescape(foo)
Only
:execute 'write ' . foo<CR>
and
:write <C-r>=foo<CR><CR>
do what you want.
Variables can be used in a concatenation, case 1, or in an expression, case 2.

Calling another user command inside the user defined command

Is it not possible to call another user defined command in a user defined command?
I tried the following two lines but neither of them worked:
command! GetRapidLinks FindRapidLinks|MatchesOnly
command! GetRapidLinks :FindRapidLinks|:MatchesOnly
The Vim help reads:
You cannot use ":X", ":Next" and ":Print"
The context of this restriction is not clear. I guess one cannot use those in a user defined command, right?
This is probably because you didn't define the :FindRapidLinks command with -bar; without it, the command "eats" the entire remaining arguments (cp. :help command-bar). So, either redefine:
:command! -bar FindRapidLinks ...
:command! GetRapidLinks FindRapidLinks|MatchesOnly
or work around this (for cases when you cannot redefine the other command) via :execute:
:command! GetRapidLinks execute 'FindRapidLinks'|MatchesOnly
As a general rule, use -bar unless your custom command needs to be passed arguments that contain special characters like |.
Actually, what the help means is, you can't call a user command :Next or :X, because those are the few builtin commands, that start with a capital letter. I am not sure, why your vim actually says, you can't define a :Print command, as it is possible to define your own custom :Print command (since the builtin command is only an alias for :print anyhow)
I am not sure, what exactly you are trying to achieve here, so I can't answer the first part of your question. You can however in a function or in a custom command call another custom command.
Perhaps try backticks ` (not to be mistaken with quotes ' or ")
for e.g.
command! GetRapidLinks `FindRapidLinks` | MatchesOnly
or
command! GetRapidLinks $(FindRapidLinks) | MatchesOnly

Pass a variable to sleep in vimscript

I've been using vim for too many years to count, but I never have really learned vimscript very well. I'm trying now.
Anyway, I would like to pass a variable amount of time to the sleep function. I also want to manipulate that value before I pass it along. Here's a simple example.
function! wait(mil)
let timetowait = mil . "m"
sleep timetowait
endfunction
Even if I try prefixing timetowait with l: it says, "Invalid argument: l:timetowait".
What's the right way of passing the value of a variable to sleep?
There are a couple of problems:
Your method should start with a capitalized name
You need to access your argument with a:
You have to have a space between the time to sleep and m
You have to execute the sleep indirectly using execute
Here's an example on how one could do this:
function! Wait(mil)
let timetowait = a:mil . " m"
exe 'sleep '.timetowait
endfunction
Daan's answer is correct; here's some more background info:
Vimscript is evaluated exactly like the Ex commands typed in the : command-line. There were no variables in ex, so there's no way to specify them. When typing a command interactively, you'd probably use <C-R>= to insert variable contents:
:sleep <C-R>=timetowait<CR>m<CR>
... but in a script, :execute must be used. All the literal parts of the Ex command must be quoted (single or double quotes), and then concatenated with the variables:
execute 'sleep' timetowait . 'm'

How to expand function arguments in Vim command line?

Vim's Utl plugin offers a convenient way for doing web queries from within the editor. When called directly from the command line, a dictionary lookup can be done like this:
:Utl ol http://dict.leo.org/?search=my+search+term
What's the correct way for defining a custom command with the same purpose (my+search+term being user input)? I can't seem to get <f-args> right with this one:
command -nargs=1 SearchLeo :exe ":Utl ol http://dict.leo.org/?search=" . expand("<f-args>")
What's the correct way of defining function arguments here? Or should I turn this into a more complete function? Thanks!
You probably don't need expand() here; it's just for expanding globs (like *.txt) or the special variables like % for the current file.
You're quoting the argument twice, once through <f-args> (<q-args> would be slightly more correct, though it only matters with a variable number of arguments), once literally.
Use this:
command -nargs=1 SearchLeo :exe ":Utl ol http://dict.leo.org/?search=" . <q-args>

VIM: how to put result of a colon command into a variable?

In VIM script, i want to check if VIM was started with command-line arguments or wthout. For this, i want to check a result of :args command that prints arguments. But how to put a result of :args inside an if() or a variable. Following wll not work:
let s:MyArgs = execute( "args" )
You need to play with :redir. I have encapsulated this operation in a function there.
BTW, argc() should also answer your original need in a simpler way. (:h argc())

Resources