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

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!

Related

Force fzf :Tags to use a specific file with vim

I'm using fzf for a few weeks now and it really changed my workflow. I'm working on a big project with multiple things interconnected.
I'd like to use :Tags command to have an overview of all existing tags in the whole project (not to have multiple tags files) in the folder /home/ctags/ (ctags bin being here).
My command in the vimrc is
let g:fzf_tags_command='/home/ctags/bin/ctags -R --extra=+qf --excmd=pattern --exclude=Makefile -f /home/ctags/tags /home/work/project/'
Because of something I don't understand, while I use :Tags, tags file is generated where I want to, but the error "Failed to create tags" occurs..
The question becomes more simple : how to force fzf to use a specific tag file ?
Bonus
I added
set tags=./tags;
set tags+=/usr/include
To also include import tags, but it doesn't seem to work. Any idea ?
EDIT
Found the solution !
This has to be added on top of .vimrc file
set autochdir
set tags=/home/work/tags,tags;
And the command for :Tags is
let g:fzf_tags_command='/home/ctags/bin/ctags -R -f /home/work/tags --extra=+qf --excmd=pattern --exclude=Makefile /home/work/project/'
This way, only one tag file will be generated and it will be updated each time you invoke fzf.

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

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/.

Removing a character from 'iskeyword' in vim

In my vimrc, I have included a script (say, otherscript.vim, which I need to include for work reasons) that says:
autocmd FileType php setlocal iskeyword+=$
and I don't want this behaviour. So, sometime later in the vimrc, I say:
autocmd FileType php setlocal iskeyword-=$
(I also tried using set instead of setlocal.) But, when I open a php file, iskeyword still contains the $ symbol in it. I am using vim 7.2. The output of ':verbose set iskeyword' is
iskeyword=#,48-57,_,192-255,$
Last set from /path/to/otherscript.vim
The output of ':scriptnames' is:
...
7: /usr/share/vim/vim72/ftplugin.vim
8: /home/yogeshwer/.vimrc
...
74: /path/to/otherscript.vim
...
Can somebody help me how I can revert the changes to 'iskeyword' made by the other script? Thanks a bunch.
I like to avoid autocmds when I can and use the after directory structure.
$ mkdir -p ~/.vim/after/{ftplugin,syntax,indent}
$ echo 'setlocal iskeyword-=$' >> ~/.vim/after/ftplugin/php.vim
This sets up a basic after directory in your user-specific vim config folder. Whereas ~/.vim/ftplugin/$FILETYPE.vim would be used in lieu of vim's standard $FILETYPE.vim file, files in an after directory get executed after, allowing you to override or change the behavior of your ftplugins, syntax definitions, and indent commands.
As an additional example to show you how these work, I'll include part of my local after/syntax/python.vim file here. I like all the "structural punctuation" of my code to stand out when I read it, so I do this:
syn match pythonParen /[()]/
syn match pythonBrack /[][]/
syn match pythonCurly /[{}]/
hi def link pythonParen Paren
hi def link pythonBrack Brack
hi def link pythonCurly Curly
I've also got an after/indent/php.vim file that was supposed to fix some of the annoying indent issues I ran into with the indent behavior when switching in and out of <?php ?> regions in a template file, but the code is a mess and never really worked in the first place, so I won't reproduce it here. I mention it only to give you an example of what can be done with the after hooks.

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