Vim script: expand wildcards in a string - vim

There is a vim variable with the string value like this:
foo%:p:r:sbar
%:p:r:s is a vim wildcard.
How can I expand all wildcards in the string variable?
Unfortunately expand(my_variable) doesn't help.
Do I need to specify any additional argument or use other vim function?
Thanks.

Try :help expand()
This section of the docs seems especially relevant to you:
Modifiers:
:p expand to full path
:h head (last path component removed)
:t tail (last path component only)
:r root (one extension removed)
:e extension only
Example: >
:let &tags = expand("%:p:h") . "/tags"
Note that when expanding a string that starts with '%', '#' or
'<', any following text is ignored. This does NOT work: >
:let doesntwork = expand("%:h.bak")
Use this: >
:let doeswork = expand("%:h") . ".bak"
It looks like your trailing (and possibly leading) strings won't work with expand().
This does work though:
:echo "foo" . expand("%:p:r:s") . "bar"
Possibly you can rework your script so wildcards are expanded before they are combined with other strings. Alternatively you could try to split the concatenated string, expand the wildcards, then re-concatenate.

What about
join(map(split(mystring, '\ze[<%#]'), 'expand(v:val)'), '')
?

Related

vim mapping K to external command

I'd like to map vim's 'keywordprg' to Dash, namely, use K to do !open dash://word-unser-curse.
Currently, I'm doing this:
:let &keywordprg '!open dash://'
but it says E34: No previous command.
from :h E34:
Any '!' in {cmd} is replaced with the previous
external command (see also 'cpoptions'). But not when
there is a backslash before the '!', then that
backslash is removed. Example: ":!ls" followed by
":!echo ! \! \\!" executes "echo ls ! \!".
Thus you have to escape ! in order to have vim treat as it is, otherwise vim tries to replace it with the "previous command", resulting in the error.
Additionally, I don't think you need that ! in your keywordprg. Vim calls it as an external command anyway (the default value is man, not !man).

how to exclude files when using globpath() function

I want to obtain in Vim any file in a path that doesn't have a .tex or .bib extension.
I tried (in order to ignore tex files) the following command
:echo globpath({some path}, '*.[^tex]*')
but that will also ignore combinations of tex characters (for instance .toc files).
So how can I modify the pattern in order to match any file without .tex or .bib extension?
Edit: Vim' negative lookahead is done with \#!. I have a directory /test with the files foo.bib, foo.tex, foo.pdf, foo.aux and foo.toc. I tried doing
:echo globpath('C:/Users/Pedro/Desktop/test', '\w*\.\%\(tex\|bib\)\#!')
but that returns an empty string.
to use globpath() function, you don't need regex. it's a glob function. you can just set the wig option (wildignore) , then call the function .
set wig=*.bib,*.tex
then
:echo globpath('/your/path','*.*')
do a test:
kent$ pwd
/tmp/test
kent$ ls -1
bar.bib
bib.bar
f.txt
tex.foo
x.tex
in vim:
:set wig=*.bib,*.tex
:echo globpath('/tmp/test','*')
we got:
/tmp/test/bib.bar
/tmp/test/f.txt
/tmp/test/tex.foo
note that you can call it globpath('/path','*',0,1) to have returned value in a list, sometimes it is handy to use in script.

what does the number 1 in the shellescape function mean in vim?

A vim command confuses me. I have read and re-read :help shellescape() several times. I still don't understand the meaning of the number 1 in shellescape(expand('%:p'), 1).
Here's the full command I'm trying to understand:
:nnoremap <F4> :exe ':silent !"c:\Program Files\Mozilla Firefox\firefox.exe"'shellescape(expand('%:p'), 1)<CR>
Let's break down this long command piece by piece.
the command is to map an exe command into F4 in the whole.
:exe is to execute some command.
:silent ! is to execute a shell command silently
"c:\Program Files\Mozilla Firefox\firefox.exe" can call my firefox program.
shellescape(), there are blanks to be escaped.
expand('%:p') can get current file name in full expression that is path + filename.
What does this excerpt from the help page mean?
With a |non-zero-arg| {special} and 'shell' containing "csh" in the tail it's
escaped a second time.
Is there some meaning such the same as 1 or 2 in s/(ha.*)(world)/\2\1/g?
please take a simple example in detail.
And i have two questions related to the topic.
1.In which way i can get how many type of shells in my gvim?
2.In which situation can i change 1 into 2 in shellescape()?
:nnoremap <F4> :exe ':silent !"c:\Program Files\Mozilla Firefox\firefox.exe"'shellescape(expand('%:p'), 2)<CR>
There are basically two different uses for shellescape(); one is the Vimscript system() function, the other the :! Ex command. While most escaping needs are identical in both uses (e.g. to deal with whitespace, arguments must be enclosed in quotes), the :! command requires some additional escaping, because on the command-line, Vim assigns special meaning to symbols like % (replacing it with the current file name). This does not happen for system().
Therefore, to tell shellescape() which escaping mode to use, it has the additional {special} argument; if you pass 1 (or any other value that evaluates to "true"), the additional characters are escaped, too.
TL;DR: Pass 1 for :! commands, 0 or omit the argument for use with system().
From the help for shellescape():
shellescape({string} [, {special}]) shellescape()
Escape {string} for use as a shell command argument.
On MS-Windows and MS-DOS, when 'shellslash' is not set, it
will enclose {string} in double quotes and double all double
quotes within {string}.
For other systems, it will enclose {string} in single quotes
and replace all "'" with "'\''".
When the {special} argument is present and it's a non-zero
Number or a non-empty String (non-zero-arg), then special
items such as "!", "%", "#" and "<cword>" will be preceded by
a backslash. This backslash will be removed again by the :!
command.
The 1 in your example simply tells shellescape() to escape special characters with a backslash. If you were to have (say) a ! in the path returned by expand(), it’d be replaced with \!.
shell is an option:
'shell' 'sh' E91
'shell' 'sh' string (default $SHELL or "sh",
MS-DOS and Win32: "command.com" or
"cmd.exe", OS/2: "cmd")
global
Name of the shell to use for ! and :! commands.
— :help 'shell'
“With a non-zero-arg {special} and 'shell' containing "csh" in the tail it's escaped a second time” means that if, as in your example, shellescape() is given a non-zero argument for special (your example has a 1), it will check shell for that "csh", and if it finds it (if your shell is set to something containing csh) it will double-escape it.
EDIT to specifically answer two questions added to (edited) original post:
You can get your shell setting (referred to in the shellescape() help quote) using :echo &shell.
2 is a Number and is non-zero. You should therefore be able to substitute 2 for the 1 in your example and get the same result.

please help to make it work of vimscript

why I can't set path success.
let s:WORKDIR = getcwd()
set path += ".," . s:WORKDIR . "/**"
echo &path
and the echo result is, my current directory is "/home/myname/example", my expected result is
".,/home/myname/example/**", but what i get is,
.,/usr/include,,
it seems this didn't work in my .vimrc script; please help, thanks.
Your syntax of the :set command is wrong; you should be getting errors, too. The += must not be surrounded by whitespace, and you cannot use an expression on the right-hand side. Better use the :let command; it can also modify Vim options (&optionname), not just variables:
let &path .= ",.," . s:WORKDIR . "/**"

Vim findfile function usage?

I'm looking for an example of how to use the findfile function in a vim script to search upwards recursively for a file, specifically using a wildcard.
Whenever I include a wildcard character as part of the first function parameter this doesn't seem to work.
For example, with the following directory structure:
~/MyProject/
Test.sln
src/
Test.cs
If I run the following function, while editing the file Test.cs with pwd set to ~/MyProject/src
function! Test()
let a = findfile("*.sln", ".;")
echo a
endfunction
findfile appears to return nothing. However, if I modify the function to remove the widcard as follows:
function! Test()
let a = findfile("Test.sln", ".;")
echo a
endfunction
It does what I would expect.
I've tested this on both ubuntu and windows and I see the same behavior on both. Am I doing something wrong here, or does findfile just not support wildcard characters? A lack of support for the wildcard character seems like a fairly strange omission. It seems like I must be doing something wrong here.
If you're using wildcards I think the glob() and/or globpath() functions are what you're looking for. See :h glob() and :h globpath().
One way to do it with external (fast) find
function! Test()
let l:list=system("find .. -maxdepth 1 -name \*.sln")
echo l:list
endfunction

Resources