Vim: Can't set 'path' correctly to make 'gf' work - vim

I'm trying to get gf working with paths that look like this:
foo/bar.js
The file is located here: /Users/dimal/dev/project/src/foo/bar.js
So I set my path like this:
set path+=/Users/dimal/dev/project/src
It seems like gf should find the file but it doesn't.
E447: Can't find file "foo/bar.js" in path
Why?
I've tried other variations:
/Users/dimal/dev/project/src/**
/Users/dimal/dev/project/src/**/*

gf commands searches for files in the paths include via :set path.
set path command accepts wildcards like *. (* means any character) So, if you wanted to include all files under subdirectories of a directory, you can give
:set path+=directory/**
For a depth of three levels under a directory, that is , to include files under any subdirectory of subdirectory of subdirectory of current directory, you can specify like directory/**3
Maximum depth allowed is 100.
A command like
:set path+=/Users/dimal/dev/project/src/**3
will allow you to search for file named bar.js in src/subdirectory/subdirectory/subdirectory as well, not just in src/.

Related

Why is both ./tags and tags present in the Vim 'tags' option?

If I execute :set tags? in Vim, I get the following output.
tags=./tags,./TAGS,tags,TAGS
If I execute the :help 'tags' in Vim, I get the following documentation.
*'tags'* *'tag'* *E433*
'tags' 'tag' string (default "./tags,tags", when compiled with
|+emacs_tags|: "./tags,./TAGS,tags,TAGS")
global or local to buffer |global-local|
Filenames for the tag command, separated by spaces or commas. To
include a space or comma in a file name, precede it with a backslash
(see |option-backslash| about including spaces and backslashes).
When a file name starts with "./", the '.' is replaced with the path
of the current file. But only when the 'd' flag is not included in
'cpoptions'. Environment variables are expanded |:set_env|. Also see
|tags-option|.
"*", "**" and other wildcards can be used to search for tags files in
a directory tree. See |file-searching|. {not available when compiled
without the |+path_extra| feature}
The |tagfiles()| function can be used to get a list of the file names
actually used.
If Vim was compiled with the |+emacs_tags| feature, Emacs-style tag
files are also supported. They are automatically recognized. The
default value becomes "./tags,./TAGS,tags,TAGS", unless case
differences are ignored (MS-Windows). |emacs-tags|
The use of |:set+=| and |:set-=| is preferred when adding or removing
file names from the list. This avoids problems when a future version
uses another default.
{Vi: default is "tags /usr/lib/tags"}
I want to know why both ./tags and 'tags` are present in this option?
The documentation says, When a file name starts with "./", the '.' is replaced with the path of the current file. So ./tags seem to behave similar to tags, or am I mistaken?
What is the difference between ./tags and tags in this option?
The path of the current file is not necessarily the same as the current working directory. With tags the latter directory is used, with ./tags, the former. The difference is explained in :h tags-option:
When a tag file name starts with "./", the '.' is replaced with the path of
the current file. This makes it possible to use a tags file in the directory
where the current file is (no matter what the current directory is). The idea
of using "./" is that you can define which tag file is searched first: In the
current directory ("tags,./tags") or in the directory of the current file
("./tags,tags").
For example:
:set tags=./tags,tags,/home/user/commontags
In this example the tag will first be searched for in the file "tags" in the
directory where the current file is. Next the "tags" file in the current
directory. If it is not found there, then the file "/home/user/commontags"
will be searched for the tag.
For example, consider the following directory tree:
.
├── project2
│   └── tags
└── project1
   └── tags
And you do:
cd project1; vim ../project2/foo.c
Then project2/tags will be used first, and then project1/tags (assuming you don't have autochdir set, or similar shenanigans aren't at work).

How do I set Vim's 'path' if a file's parent path tree is cookbooks/foo/recipes?

I'm using MacVim to edit Chef cookbooks and I'd really like the gf (Go to file) command to open other Chef recipes in the same cookbook.
Super extra bonus points if your solution can open recipes in other Chef cookbooks as well.
So given a directory structure like this:
1. cookbooks/mycookbook/recipes/default.rb
2. cookbooks/mycookbook/recipes/foo.rb
3. cookbooks/mycookbook/recipes/bar.rb
4. cookbooks/apache2/recipes/default.rb
5. cookbooks/apache2/recipes/mod-ssl.rb
And mycookbook/recipes/default.rb contains this:
include_recipe 'mycookbook::foo'
include_recipe 'mycookbook::bar'
include_recipe 'apache2'
include_recipe 'apache2::mod_ssl'
I'd like Vim's gf command to be able to open the recipes listed above.
Approach:
Basically, I'm thinking about using setlocal for Ruby files to set the path variable if the current Ruby file's parent directory structure is like cookbooks/<cookbook name>/recipes/, but I'm not sure how to do it.
For the easy solution, you could just add the current file's parent directory (recipes) to the path if the current file's parent path was cookbooks/<cookbook name>/recipes/.
For the more comprehensive solution, you would also need to add cookbooks/<all cookbooks>/recipes/ to the path variable.
So after several hours of reading Vim docs and Googling, I came up with this autocmd (broken into two lines for readability:
" Make gf work on Chef include_recipe lines
" Add all cookbooks/*/recipe dirs to Vim's path variable
autocmd BufRead,BufNewFile */cookbooks/*/recipes/*.rb
\ setlocal path+=recipes;/cookbooks/**1
Wouldn't it be cool if you could do the same thing for templates? For example:
template "/etc/sudoers" do
source "sudoers.erb"
end
gf on sudoers.erb and it will pull up the sudoers template, and if more than one exists pull them up in a split window!

Find command in vim gets incomplete path

In vim when I'm using :find to open another file, it misses the first component of the relative path.
For example, if I'm looking for a file that's in:
./foo/bar/file.txt
I'll type
:find **/file.txt
It finds the file but then tries to open
bar/file.txt
It works correctly if I type
./**/file.txt
But I'm lazy and don't want to type that much. Is there some config I'm missing that will correctly locate and open this path?
My Solution
I simply appended the main source code dir to my path
exec "set path^=src/**"
Is your 'path' set? That (IMO) is a pretty handy way to keep from even typing the **/ bit.
In my setup, there's an environment variable that defines which project I'm currently in so I use that and construct a path with that as the root. In a nutshell:
let s:rootdir = $PROJECT_DIR
let s:path = 'src/**;' . s:rootdir . ',scripts/**;' . s:rootdir
execute "set path=" . s:path
Then I can just :find a_file.txt and it searches my src hierarchy then my scripts hierarchy for the file.

How to source all vim files in directory

I have split my .vimrc into several files and placed them into ~/vimfiles/vimrc.d/.
Currently I source each file in that directory using exact name:
source ~/vimfiles/vimrc.d/file1.vim
source ~/vimfiles/vimrc.d/file2.vim
etc.
How to make a loop thourgh all files in that directory so i could only have to do such loop in my .vimrc:
for file in ~/vimfiles/vimrc.d/*.vim
source file
enfor
As mb14 has already said, if you put them in ~/.vim/plugin they will be sourced automatically. For information, however, if you want to source all of the files in your vimrc.d directory, you could do this (requires a relatively recent Vim):
for f in split(glob('~/vimfiles/vimrc.d/*.vim'), '\n')
exe 'source' f
endfor
You may also be interested in the autoload mechanism, described in :help 41.15: if you're defining a lot of functions, this can make start-up a bit quicker as the functions are only loaded the first time they're used.
You can just put your files in the plugins directory (~/.vim/plugin). They will be automatically loaded.
mb14 gave you the best answer. You want something automatically executed? Then use the standard organization: here the plugin/ subdirectory.
Otherwise, :runtime would have been your friend:
:runtime! vimrc.d/*.vim
:source barks when its parameter doesn't exist while :runtime silently source nothing.
:source can source only one file while :runtime! can source any number of files.
:source takes an absolute pathname, or a pathname relative to the current directory while :runtime takes a pathname relative to the 'runtimepath' option, which shouldn't be a problem as long as you respect vim conventions.
The example from DrAl did not work for me, this is how I achieved it:
for fpath in split(globpath('~/.vimrc.d/', '*.vim'), '\n')
exe 'source' fpath
endfor
The following snip is what I use within my ~/.vimrc file to source scripts within the ~/.vimrc.d/ directory and sub-directories...
for f in glob('$HOME/.vimrc.d/**/*.vim', 0, 1)
execute 'source' f
endfor
Check vim -c ':help glob' for details about additional glob arguments.
TLDR
glob({expr} [, {nosuf} [, {list} [, {alllinks}]]]) *glob()*
{nosuf} set to False allows 'suffixes' and 'wildignore' options to apply
{list} set to True causes glob to return a list that respects new-lines within file names

Vim problem with gf command

I am using Vim and I have set the path (set path+= c:/work/etc/etc) to my project directory (for C#), but still using command 'gf' give me error:
E:447 Can't find file.
Is there anything I am doing wrong over here?
G'day,
To get a bit more detail on your current path settings you can see what's being included and the files vim can't find by entering the command:
:checkpath
and you'll get a dump of the files not found, e.g.
--- Included files not found in path ---
<io.h>
vim.h -->
<functions.h>
<clib/exec_protos.h>
Or you can get a listing of all included files, both found and not found, by entering
:checkpath!
Enter
:help path
to get more info on the path syntax.
Edit: Don't forget that using the syntax
set path=/work
will completely reset your path variable to what you've just declared. I'd suggest using
set path+=/work
instead. This won't clobber the current path and will just add your /work directory instead.
HTH
I also found out that
:set path+=./foo/bar
adds a search location relative to the directory of the current file, just like '.' does.
My vim didn't want to search for such include
#include <common/util/string.h>
So what I needed to do was
:set path+=foo/bar
instead of
:set path+=./foo/bar
The former adds a search path relative to current working directory. Hopefully it helps someone.
First can you open the file using :find file.name ? (:help find for more info). If this does not work then your path is wrong. If :find does locate your file then do the following:
Insure that you are not in Visual/Insert mode
Place cursor on the first letter of the filename and press gf
I know this is an old question, but I also had some troubles with this for another reason and it took me some time to find out why. I hope this might be helpful to someone.
When a directory is matched with wildignore, gf does not work for files in it, nor does :find.
This is obvious if you read wildignore's documentation, but I forgot I ever changed this variable, and what it was for exactly. Also I used a glob, and it was not immediately apparent to me that the directory I was using gf in, was also matched with this glob.
Make sure there is no leading character to the file name if you press gf, i.e. using gf when the cursor is on help.txt will not work here:
file=help.txt
If you are talking about the gf tool wri††en by tomnomnom then here's how to set-up:
Setting PATH for GO (if you have not setup yet).
export GOROOT=$HOME/go
export PATH=$PATH:$GOROOT/bin
Step 1: Download tool from github
Step 2: cp -r path/to/tomnomnom/gf/examples ~/.gf
Step 3: source ~/tools/gf/gf-completion.bash
Now gf should work along with auto-completion from anywhere.
Source: Original sources are present at his repo.

Resources