Vim insert mode file path completion - vim

I want to change where vim looks for file completion, but only in insert mode. For example:
I open gvim inside of the CG-Website directory.
This is my directory structure:
Then i go in to the css folder and open style.css
using :e src/static/css/style.css
Now i am inside of style.css and i want to complete a file name that is down one directory.
I want to be able to type ../ in INSERT mode and have all the files/folders that are inside of the static folder show up, instead of the www folder which is what it does right now.
However I don't want to change the actual directory, because I still want :e to work normally.

Insert mode filename completion is always done from the "current directory" or "working directory" which may or may not be the directory of the current file. Since you don't want to change directories, filename completion can't work like you want it to work.
Actually, the last sentence of :h compl-filename should give you a hint:
Search for the first file name that starts with the
same characters as before the cursor. The matching
file name is inserted in front of the cursor.
Alphabetic characters and characters in 'isfname'
are used to decide which characters are included in
the file name. Note: the 'path' option is not used
here (yet).
One solution to this problem is to set autochdir so that Vim always changes the working directory to the directory of the current file and use a plugin like CtrlP (there are others) for navigation. When configured properly, CtrlP lets you navigate your files from your project's home as defined by the presence of a .git or similar directory. This is really handy.
However, you can get around that limitation relatively easily with set autochdir (again, you need it for filename completion to work like you -- and I -- want it to work) and a bit of creativity:
nnoremap <F9> :e ~/path/to/project/
Consider this mapping as a quick shortcut to your project.

I think you are approaching this the wrong way. You want to filter results relative to your last opened dir without changing your current dir and that doesn't quite make sense.
My recommendation is to use a tool what will allow you to quickly filter through all of your files from the root folder of your project.
Take a look at Command-T: Fast file navigation for VIM
PS: you need vim with ruby support for that.

Related

Vim: How to open a file from current directory list without using arrow keys

Suppose I am editing a file using vim, and I go back to the file's current directory using :Ex, and I have a list of all the files I could open, I know arrow keys + Enter works, but is there a way to use : something to open a specific file? I tried :e filename but this goes directly back to the root of vim instead of the current directory.
Thanks.
The following is not a :-command, but it does the job and it can be in the muscle memory already:
You can move around the directory listing just like in a standard buffer. So you can /filename<Enter> to get to your file and <Enter> to open it. But typing whole filename can be rather cumbersome, so let's improve:
If there is something specific in the filename-baz, it will be enough to /baz<Enter><Enter>. And yet better, if you run vim with set incsearch and set hlsearch as many do, you'll see the search space narrow down to your filename, so you can easily get the prefix-search behavior of file commanders. Or even better, thanks to the coloring.
In case you can see the filename on the screen, then with EasyMotion, you can <Leader><Leader>w, then the usually two letters to get there and <Enter><Enter>.
tried :e filename but this goes directly back to the root of vim instead of the current directory.
This may happen because you are running vim from a different directory.
Suppose I run vim from my home directory, you will have to run :e /path/to/filename and :tabe /path/to/filename where the filepath is relative to the home directory.
you can open another file while vim is open with :tabe filename and to switch to the other file you type :tabn or :tabp for next and previous accordingly.
Maybe this link can help you

navigating filesystem in vim -> :find vs. :edit

When opening files in Vim I almost always do something like this:
:e subDir/**/file<ctrl-d>
But in the docs and basically every StackOverflow/blog post I have read it seems that people use "find" the way I use "edit".
What am I missing by using the edit command instead of the find command?
:edit is restricted by default to the working directory: if you need to edit a file that is not under your working directory you will have to provide its absolute path or a path relative to the working directory. Also, you need to provide the necessary globs.
:find is superficially very similar to :edit but the (big) difference is that it finds files in the directories specified in the path option. path is what makes :find a lot more interesting than :edit.
With set path=,, you essentially get the same behavior as :e foo.
With set path=** you essentially get the same behavior as :e **/foo except you don't have to use any glob.
With set path=.,** you also get access to files in the same directory as the current file.
With set path=.,**,/path/to/some/central/vendor/directory you also get access to files from that directory… and so on.

vim / file explorer: make browsing directory the current directory

I'm starting to use vim's native explorer (:E). My doubt: when I press c to "make browsing directory the current directory" nothing happens.. When I used nerdTree and did the same operation (:NERDTreeCWD), that directory was placed at the top of the exporer and the directories upper were "hidden".
It just seems pressing c is not doing anything..
NOTE: Im using the tree view on explorer, instead of the default one. I pressed i to change the view.
Im using 7.4.52
The netrw command works different than NERDTree's. It doesn't apply to the directory under the cursor, but to the one currently being browsed. So if you want to make a subdir the current one, first go into it (via <Enter>), then press c.
To expand on Ingo's answer. If you always want netrw to make the current browsing directory the current vim directory, you can set the option let g:netrw_keepdir=0 in your .vimrc.
This allows you to use netrw to browse directories and use vim to operate in that directory. For example, you can use vim's command :e <filename> to create a new file instead of netrw's command % <filename>.
To learn more about netrw I recommend reading the help pages :help netrw-quickhelp

GVim - How to handle multiple files

Sorry to ask such a novice question but I am looking for a way to handle multiple files. I dont want to type huge file paths to open every file using :tabnew and :e commands
Fuzzy Finder is a handy plugin to quickly find and open files.
Basically you have to only type a few letters like test and you'll get a pop-up menu to open in your current path :
footest.c
bartest.h
footest.h
...
It is a bit slow when used on NFS but it is useful if you don't want to type long path and file names.
Alternatively if you don't want to use any plugin, by default gvim/vim includes a file browser called netrw.
To start it, just type :e . you'll get the content of your current directory, you can then navigate through the directory structure quite easily. (There is even commands to delete, rename, etc like a standard file explorer)
:help netrwfor more information.
A couple of tips that you might be interested in:
You can configure Vim so that the
current directory "follows" the
directory of the file you are
currently editing. That way you can
edit another file from the same
directory without having to type the
full path. This can be achieved by
putting either set autochdir or
autocmd BufEnter * lcd %:p:h in
your .vimrc
You can use wildcards with tab
completion. e.g. to edit
a_file_with_a_long_name.txt you could
do :e a*long and then press
Tab followed by
Return.
Usually, vim supports buffers for that. Use :badd to add buffer, :bdelete to remove it and :ls (or :buffers) to list all opened buffers. I believe, GVim supports these features too.
For example, if you wanna edit all .rb files in your app/controllers/pages dir (in the case of Rails project), you type vim app/controllers/pages/*.rb in your terminal and then edit the first file (buffer) in the vim window. When you've done with all changes, save changes as usual with :w (note: do not use q! option - this will close all your buffers you've opened) and then use :bn<tab> (or fully, :bnext) or :bprevious to switch to the next file (buffer). When you run :bnext on the last buffer, you'll be dropped to the first one.
You can open a directory in Vim, search for the file o directory you are looking for with '/' and type [enter] to open it.

How to navigate in large project in VIM

How do you manage big projects (hundreds of files) using only VIM?
I personally start having problems in any larger than small project.
is there any way to quickly 'go to file', preferably with name completition?
same for 'go to class definition', when it is in another file
I kinda know all the VIM basics, so I don't have problem using it for writing scripts or quick editing some source code. But it gets really messy for me when I have to navigate between files.
VIM has excellent support for tags. Once you have created a tags file for your project, you can jump to a definition or declaration of a method, class, etc., including jumping across files, all inside the same editing session.
Try
:help tags
To generate a tags file for C/C++, go to your shell prompt (I'm assuming your system is *nix/Cygwin) and type
info ctags
or
ctags --help
I like simple solutions, my favorite way to navigate at the moment is:
Add to ~/.vimrc.local
set path=$PWD/**
Then type this in the editor to find the file anywhere in the current working directory (pwd)
:find user_spec.rb
You can use tab-completion on the filenames to find multiple choices as well, making this TextMate convert very happy.
I use a combination of NERDTree (directory sidebar), FuzzyFinder Textmate (go-to-file like TextMate's CMD+T), and Sessions (:h sessions) to help me deal with large projects.
I would suggest using some sessions helper plugin. I would mention what I use, but I'm not satisfied with it yet. Just Google "vim sessions".
One thing to note with getting FuzzyFinder Textmate to work is that it depends on an old version the FuzzyFinder plugin, specifically v2.16. Anything higher and you'll get errors. But it's definitely worth the trouble. While it doesn't have name completion, its search is smart so if I search for fro/time/actionsphp it will pull up the file apps/(fro)ntend/modules/(time)_tracking/actions/(actions).class.(php) (parenthesis denote what it's matching). It makes it very easy to pick out files that are only unique by their folder name.
As well as the invaluable ctags and the various associated commands. I also couldn't live without the project plugin, which allows you to have the files of interest associated with a project in a separate pane. I can't remember how much of my setup is customised, but if I want to open a source file called Debug.c, I hit:
<F12> " Opens the project pane
/De " Searches for "De", which is likely to be enough to find Debug.c or possibly Debug.h
<ENTER> " Opens the selected file and closes the project pane
I often then do:
:vsp " Vertically split the window
<F12> " Reopen project pane
# " Search back to find previous entry with the same name (to find
Debug.h if I was on Debug.c: my headers are in Headers/ and
my source is in Source/, so the headers come earlier in the list
than the source). I use * to go the other way, obviously.
<ENTER> " Open the header file in the other window and close the project window.
With this relatively short sequence, I can open any file and it's header in a vertical split. Since the project plugin window is just a text file, completion is achieved by using Vim's searching capability.
Starting in Vim 7.3, the :find command has tab-completion of filenames.
So if you set your 'path' option to contain your entire project (probably using the ** wildcard to allow recursively searching subdirectories), then you can use the :find, :sfind, :tabfind, etc. commands with completion to get to any file in your project. This also allows jumping to files directly with gf and friends if the file name is in your text, for example in an include directive.
With this method, no external tools or plugins are needed for navigating to specific files. Although, it may admittedly not be as fast or easy to use, and doesn't address the need for jumping to definitions. For definitions, I use ctags as other answers suggest.
If you are using ctags as other posters have recommended, then make sure you look at the taglist plugin.
Make sure you take the time to read the docs and learn the key bindings. Here are a few to get you started (from the TList window):
o - open file in new window
t - open file in new tab
[[ or backspace - previous file in list
]] or tab - next file in list
Exuberant ctags.
Use Ctrl-] to jump to the tag under the cursor.
Opening vim from root of your source file and extending path option to include all sub-directories therein.
For example set path+=/usr/include/c++/** for C++ headers and set path+=** for your source directory.
This ,then, opens a plethora of following possibilities.
1) Opening file by name or parts of it
:find file_name
You can use auto-completion and wildcard expansion with :find reliably. You type the name, it will locate the name. This works language agnostic.I am sure you will like it.
2) Navigating to files under cusror:
if you want to go a file path like #include "project/path/classA.h.
gf or gF - go to file under cursor.
Ctrl-6 - to come back to last cursor position after gf or gF
3) API lookup and navigating to the API location
[i or [I can be used to look up your function signature for word under cursor without leaving your workspace. [<Tab> to actually go to declaration. Use Ctrl-6 to come back to last location.
Without extending path, you can start navigating files by :Ex command and navigate and open your file. I prefer NerdTree over this though.
I use FindFile. If you open vim at the root of your project and run :FC . the plugin will cache all the filenames beneath your cwd. You can then do :FF to open a completion menu and type the name of the file you want (or rather, the first few letters).
Although I'm kinda hoping someone will point out a better solution so I can learn something, NERDTree has been good to me for getting to specific files with name completion as long as I have the tree expanded. The command when I need to get to a file is something like:
,d/foo.pyo (where foo.py is a file name)
,d to open the tree, / to enter search mode, the name (or partial name, or regex, or whatever) of the file, and then o to open.
Of course you may have to hit 'n' a few times if you didn't type enough of the filename or there are duplicates.
I admit it feels like a bit of a hack using NERDTree like this although it has gotten so far into my muscle memory by now that I don't even think about it.
Of course I use ctags too but those are only useful when you have a function near the cursor and need to get to its definition in another file or something. A lot of times I say "OK, I need to work on feature x now" and need to navigate to another file without any references nearby that ctags would really help with.
I'm using two plugins of mine:
searchInRuntime that completes filenames on command line. It is somehow similar to fuzzyfinder and lookupfile,
lh-tags which is completely experimental and undocumented. It offers two features: automatic and quick update of the tagfile on file save(ing?), and a tag selector plugged to <c-w><m-down> by default. You may want to check the renowned taglist plugin instead.
Both require my viml library lh-vim-lib.
Try SourceCodeObedinece. This one I developed to handle C++ 1Gb source files project.
I use it in pair with 0scan.
These two plugins are wrappers around the most popular Vim browsing tools: ctags and cscope.

Resources