Force fzf :Tags to use a specific file with vim - 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.

Related

vimrc how to invoke unix find?

i want to set the tags variable to the set of all gotags files i generated in specific folder(s) using exuberant Ctags. (gotags is nothing but the tags file renamed).
i put following lines in my .vimrc file.
set tags+=/usr/local/go/src/gotags
set tags+=`find /home/vimal/gowork/src -name gotags`
but it doesnt work and i get the following error
$ vi ~/.vimrc
Error detected while processing /home/vimal/.vimrc:
line 157:
E518: Unknown option: /home/vimal/gowork/src
Press ENTER or type command to continue
how can i fix the error and set the tags variable with the value: list of all the gotags files under one directory tree.
Inventing new syntax tends not to work that well in practice. Use system() to run external commands from Vim, not backticks. Also set in Vim is weird, it doesn't evaluate RHS the way you expect. Most of the time it's a lot simpler to use let &option = ... instead of set option=....
Anyway, to answer your question, you don't need to run find(1) for that, plain Vim functions are enough for what you want:
let &tags = join(extend([&tags, '/usr/local/go/src/gotags'],
\ findfile('gotags', '/home/vimal/gowork/src', -1)), ',')

Open a file based on the name/dir of the currently opened file

I would like to either find a vim plugin or write a vimscript function to open
a file in (or under) the same directory as my present file. The file should
match one of a list of regex files that is defined in a list.
I have a project that looks something like this:
src
|- controllers
| ...
|- util
| ...
|- widgets
| - widgetA
| | - widgetA.js
| | - widgetA.template.html
| -widgetB
| | - widgetB.js
| | - widgetB.template.html
| -widgetC
| | - widgetC.js
| | - widgetC.template.html
| | - someHelpers.js
Sample usecase (in the command line):
cd src
vim widgets/widgetA/widgetA.js
Inside vim:
press F4 while in command mode
Result:
widgetA.template.html is opened in vertical split mode with widgetA.js
Template files will either be in one of the following:
Named the same as the presently opened file but with this regex run on it: s/js$/tempate.html/
Named the same as the presently opened file but with this regex run on it: s/js$/html/
In a subdirectory named templates named as above
I am presently using nerdtree and ctrl-p to speed up file opening, but this is a workflow that
I use so frequently that I thought it could make sense to try to speed it up. Any suggestion?
It feels like you are looking for something along the lines of projectionist or fswitch.
projectionist
With projectionist you could in theory then just execute :A/:SA to switch to the alternate file.
So in your .projections.json (not tested) file would look something like this:
{
"widgets/*.js": {
"alternate": "widgets/{}.template.html",
"type": "widget"
},
"widgets/*.template.js": {
"alternate": "widgets/{}.js",
"type": "template"
}
You can also use :Ewidget and :Etemplate commands to find a widget/template. These commands will also take fuzzy filenames. e.g. :Ewidget wta. You can also open the files in split, vertical splits and tabs via :Swidget, :Vwidget, and :Twidget respectively. Please see :h projectionist for more information.
fswitch
Another option is to use something like fswitch which is a C/C++ .h/.c switcher. Please see :h fswitch-setup for more information.
There are a few other plugins that do similar things: altr and a.vim to name a few.
vanilla
If plugins are not your thing then you can use % tricks. e.g. :sp %<.template.html
Or maybe a quick and dirty mapping:
nnoremap <f4> %:p:s,\.js$,.X123X,:s,\.template\.html$,\.js,:s,\.X123X$,\.template\.html,<CR>
For more information see the following vim wiki page: Easily switch between source and header file
conclusion
I personally use projectionist and find it meets my needs, especially for navigating a structured project which I find more useful than just a simple switcher like fswitch. Projectionist will also be easier than the vanilla approach to when your needs become wilder.
What you want is easy to do in the shell:
$ cd src
$ vim -O w*/*A/*
but I'm not exactly sure how you see that working in Vim itself. Do you want that to happen in a new tab? Do you want the new pair of files to replace the current pair of files?
Dropping this into the your vimrc and relaunch vim will work.
Presently only working for files ending in .template.html that are in the same directory but easy to see how it could work for multiple other cases. When it can't find the template it opens nerdTree to the current directory.
map <F4> :call OpenTemplate()<cr>
function! OpenTemplate()
" Get the Current directory
let l:jake = expand('%')
" Replace .js with .template.html
let l:jake = substitute(l:jake, ".js$", ".template.html", "")
" Verify that the file exists and it it does open in using vs (see :help vs)
" if the file can't be found, open nerdTree
if filereadable(l:jake)
execute 'vs ' . l:jake
else
echo 'Cant find template'
:NERDTreeFind
endif
endfunction

Creating ctags extension for markdown

I edit quite a few markdown files using Vim these days. One thing I'm missing is a map of the file like function list in C based on ctags. So I came up with the following .ctags file
--langdef=markdown
--langmap=markdown:.md
--regex-markdown=/^# ([a-zA-Z0-9]+)/\1/
It runs OK but generates no valid tags for my .md file. With verbose mode turned on I get the following:
Considering option file /home/wenliang/.ctags: reading...
Option: --langdef=markdown
Option: --langmap=markdown:.md
Setting markdown language map: .md
Option: --regex-markdown=/^# ([a-zA-Z0-9]+)/\1/
Considering option file ./.ctags: not found
What's wrong with what I did?
Your definition looks OK.
What command did you use to generate your tags file? $ ctags . won't index anything but $ ctags -R . will.
FWIW, here is a slightly modified version of your definition that provides meaningful tag names and kind informations:
--langdef=markdown
--langmap=markdown:.md
--regex-markdown=/^#[ \t](.*$)/\1/h,heading,headings/
As an alternative, you might be interested in these cheaper, built-in, solutions…
using the define option and :dlist:
:setlocal define=^#\\s*
:dli /<CR>
using :ilist and no setup:
:il /#<CR>
which both produce the same list, ready for you to type :126<CR>:
See :help :ilist, :help :dlist, :help 'define'.

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!

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