File name expansion in vim when using set option=value - vim

I'm trying to add an autocmd to vim that will execute whenever I open a file in a certain subdirectory and that sets the search path. Unfortunately path name expansion doesn't seem to work inside a set command.
Specifically I'd like to have a line like this in my vimrc:
setlocal path+=**;%:p:h
But this will just give me the literal value. Just calling expand() doesn't work either. Is there a way to get variable expansion to work here?

What about:
execute 'setlocal path +=**;' . fnameescape(expand('%:p:h'))

There's no need for the expansion of the current file's directory; just adding . to path will do. From the help:
To search relative to the directory of the current file, use:
:set path=.

Use
let &l:path.=(empty(&l:path)?(''):(',')).'**;'.escape(expand('%:p:h'), ',\*; ')
. This is much cleaner then using :execute 'setlocal path', especially knowing that fnameescape() was designed to escape paths for commands, not for options and I can say it is not really safe to use it here: it definitely is not going to escape comma and semicolon and add additional escape for space (one for escaping for :set, one for the option itself). (empty(&l:path)?(''):(',')) is here to imitate the behavior of set+=.

Related

Can you use wildcards with Vim's open file under cursor feature?

I move a lot between files from within Vim by highlighting a path and pressing the keys gf. I'm creating a makeshift Vim wiki for note-taking purposes, and I wanted to write only the beginning of a filename to be used as a link, because the way I have it, each filename begins with a unique identifier and so there would be no other matches, like so:
/notes/20190712*
I'm wondering if a simple asterisk wildcard could suffice for Vim to properly follow the incomplete filename, like how it autocompletes when :edit,:find or similar commands.
Vim's help alludes to some sort of expansion that takes place if it can't find a file, using something called includeexpr:
...used for the gf command if an unmodified file name can't be found.
Allows doing "gf" on the name after an 'include' statement.
Any help is appreciated. Thank you.

Make VIM to consider current folder the root

I already know how to quit Vim, now I'm wondering is it possible anyhow to force Vim search '/somedir/file.js' in current directory when you press gf, as if it were './somedir/file.js'?
UPD: There's question how to set path in general, but it doesn't help to make /myfolder/ pointed to some certain folder I want. /myfolder/ is always absolute path to the root of current volume.
Vim counts filenames beginning with / as file system root always, as
you observed. If that wasn't the case, of if 'isf' (the option that
controls what is considered file name) accepted a regex, this would be
easier to solve. But if you remove / from 'isf' then no slashes are
considered part of a file name anymore.
The only solution to this I can think of is using the visual mode for
gf. As you may know, if you have text selected visually and use gf
then the visual selection will be considered, instead of the 'isf'
match. Then all we need to do is to visually select the file name under
cursor excluding a possible leading /. This can be solved in a map, if
you don't mind messing your previous search:
nnoremap <silent> gf :let #/ = substitute(expand('<cfile>'), '^/', '', '')
\ <bar>normal gngf<cr>
This overwrites your gf to set the search to the filename under cursor
(expand()), minus leading slash if any (substitute()) and then run
the normal commands gn which selects the match and finally the
original gf.
If you want to save your previous search and restore, you can easily
create a function to wrap this all. Note that I also wrote this is two
lines just because I'm a declared enemy of long lines. But if you just
want to test it remove the \ and write in a single line.
Now your gf will interpret /file as file. Thus if you're on the
correcty directory this will work. If you need to search in a different
directory, the option you're looking for is 'path', or 'pa' for
short. You can give a list of directories to search. Much like Unix
shell's $PATH. Separated by commas. From the help (be sure to read the
rest yourself, with :h 'pa):
This is a list of directories which will be searched when using the
gf, [f, ]f, ^Wf, :find, :sfind, :tabfind and other
commands, provided that the file being searched for has a relative
path (not starting with "/", "./" or "../"). The directories in the
'path' option may be relative or absolute.
In conclusion, to use this in your project, set your 'path' if needed
as you wish and enable this map. Or run it all automatically in a
:autocmd or something similar. You aren't changing the root of the
project as you initially suggested, but you're kind of emulating this by
including the desired directory in 'path' and then forcing gf to
ignore the leading /.

How to create a macro with vim commands?

I am trying to create a macro to use it globaly. I have inserted this command to my .vimrc file
let #c='<esc>:r c.c'
or
let #c=':r c.c'
but in both cases when I use "#c" on any file it only prints 'c>:r c.c' on the the file
Try adding a '^M' at the end of your macro, then "#c" should work. Else ':#c' should work as mentioned by ebenezer. You should use Ctrl+VEnter to insert '^M'.
let #c=':r c.c^M'
Best way would be to record the macro first and then save it to the .vimrc.
If these doesn't work, you can check the content of your register c using "cp and see if there is something missing.
This is described in another answer. Try something like this:
let #c = ':r c.c'
and then, in your file, use
:#c
to execute it.
If you want to include special characters in your macro (like Escape or Enter) then use a non-literal string (double quotes, not single quotes) and the correct syntax. See :help expr-string. You could use raw special characters, as #Amit suggests, but this will make your vimrc file hard to read.
Assuming that you are starting in Normal mode and want to type #c, there is no need to start off with an Escape.
For testing purposes, I tried
:let #c = ":echo 'foo'\<CR>"
and it worked as expected. I even added this line (without the leading :) to my vimrc file just to make sure, and tested it that way. This should work:
:let #c = ":r c.c\<CR>"

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 replace a variable with its value in ~/.vimrc

I would like something similar too this in my .vimrc.
let dir=“/home/user/Downloads/”
set path=$dir
nnoremap gr :grep '\b<cword>\b' $dir/*<CR>
The code above is wrong of course, but maybe you can understand what I am trying to do. I would like to set path to the value of dir to /home/user/Downloads/, and replace the word dir in the third line with the value of dir. I tried and failed, can anyone tell help me out, any help appreciated!
First of all, there are fancy quotes; you need to use plain (") ones. Other than that, the :let is okay.
let dir = "/home/user/Downloads/"
You could use :execute to evaluate the defined variable with :set, but it's easier to use :let, because it can change Vim options, too, with the special notation &{optionname}:
let &path = dir
For the mapping, if dir doesn't change during runtime, it's easiest to use :execute. Note how the quoted backslashes must be escaped (i.e. doubled):
execute "nnoremap gr :grep '\\b<cword>\\b' " . dir . "/*<CR>"
All that information is part of :help eval. Learn how the excellent and comprehensive help is structured; all the information is in there (you just need to know how to find it)!
You must use this notation:
let variable_name = "value"
and use straight quotes.
To set path:
set path=/home/user/Downloads/
or to append a directory to path.
set path+=/home/user/Downloads/
Path is an Vim variable which does not seem very appropriate to use if you are going to only use it for this one remapping. It would be better to declare you own variable, as path can also have many directories within it which will not work with grep.
let g:search_path="/path/to/your/dir"
nnoremap gr :grep '\<<cword>\>' <C-R>=eval("g:search_path")<CR>
Ctrl+R lets us insert a register here, when then use that to call the expression register, which we use to evaluate g:search_path.
Check out :help expr-register for more on that!
This will evaluate your g:search_path variable on every execution of the mapping, allowing you to change the path and not have to remap gr each time.

Resources