How to autocomplete file paths in Vim, just like in zsh? - vim

In Zsh, I can use filename completion with slashes to target a file deep in my source tree. For instance if I type:
vim s/w/t/u/f >TAB<
zsh replaces the pattern with:
vim src/wp-contents/themes/us/functions.php
What I'd like is to be able to target files the same way at the Vim command line, so that typing
:vi s/w/t/u/f >TAB<
will autocomplete to:
:vi src/wp-contents/themes/us/functions.php
I'm trying to parse the Vim docs for wildmode, but I don't see what settings would give me this. It's doing autocompletion for individual filenames, but not file paths. Does Vim support this natively? Or how can I customize the autocomplete algorithm for files?
Thanks for any advice!
-mykle-

I couldn't find a plugin to do this, so I wrote one. It's called vim-zsh-path-completion. It does what you're looking for, although via <C-s> rather than <Tab>. You can use it with <Tab> for even more control over what matches, though.
It's got bugs, but for basic paths without spaces/special characters, it should work. I think it's useful enough in its current state to be helpful. I hope to iron out the bugs and clean up the code, but I figured I'd start soliciting feedback now.
Thanks for the idea!
Original (wrong) answer, but with some useful information about Vim's wildmode.
Put the following in your .vimrc:
set wildmenu
set wildmode=list:longest
That will complete to the longest unique match on <Tab>, including appending a / and descending into directories where appropriate. If there are multiple matches, it will show a list of matches for what you've entered so far. Then you can type more characters and <Tab> again to complete.
I prefer the following setting, which completes to the first unique match on <Tab>, and then pops up a menu if you hit <Tab> again, which you can navigate with the arrow keys and hit enter to select from:
set wildmode=list:longest,list:full
Check out :help wildmenu and :help wildmode. You might also want to set wildignore to a list of patterns to ignore when completing. I have mine as:
set wildignore=.git,*.swp,*/tmp/*

Vim doesn't have such a feature by default. The closest buil-in feature is the wildmenu/wildmode combo but it's still very different.
A quick look at the script section of vim.org didn't return anything but I didn't look too far: you should dig further. Maybe it's there, somewhere.
Did you try Command-T, LustyExplorer, FuzzyFinder, CtrlP or one of the many similar plugins?
I use CtrlP and fuzzy matching can be done on filepath or filename. When done on filepath, I can use the keysequence below to open src/wp-contents/themes/us/functions.php (assuming functions.php is the only file under us that starts with a f):
,f " my custom mapping for the :CtrlP command
swtuf<CR>
edit
In thinking about a possible solution I'm afraid I was a little myopic. I was focused on your exact requirements but Vim has cool tricks when it comes to opening files!
The :e[dit] command accepts two types of wildcards: * is like the * you would use in your shell and ** means "any subdirectory".
So it's entirely possible to do:
:e s*/w*/t*/u*/f*<Tab>
or something like:
:e **/us/f<Tab>
or even:
:e **/fun<Tab>
Combined with the wildmode settings in Jim's answer, I think you have got a pretty powerful file navigation tool, here.

Related

Vim command to introspectively list available commands

It would help me a lot to be able to view a list of Vim commands, and related metadata (eg. a description of each command, if it has aliases, etc.).
I understand that, through Vim plugins, the list of commands can be extended, and also depending on what options Vim was compiled with, can change the list of available commands.
I've done extensive searches online, for things like "vim command to list commands," but have come up empty-handed. The only command lists I can find are static documentation, that don't take into account the version of Vim you're running (including Neovim), what plugins you have installed / enabled, and what options Vim was compiled with.
Question: Is there a Vim command that introspectively lists all of the available commands in Vim?
In searchInRuntime I've the following function that list all commands starting with a leading text (that could be empty). This is an old trick to get what vim would expand through command line completion -- :h c_CTRL-A.
" s:MatchingCommands(ArgLead) {{{3
" return the list of custom commands starting by {FirstLetters}
function! s:MatchingCommands(ArgLead)
silent! exe "norm! :".a:ArgLead."\<c-a>\"\<home>let\ cmds=\"\<cr>"
let cmds = substitute(cmds, '\s\+', '\n', 'g')
" for your purpose, split is probably more fit
return cmds
endfunction
Note that it can't know what the commands are meant for. At best, you can fetch the definition of user commands thanks execute('verbose command '.cmdname) (execute() is a very recent function).
Note by the way that unlike execute('command'), this solution also list standard commands, not just user defined commands.
Regarding other actions available in vim (in case you weren't just looking for vim commands), while we can list user defined mappings (even may be even know that they do when they rely on well named plug-mappings), there is no way to list any other actions like dd, J...
Learn how to look up commands and navigate the built-in :help (there's automatic completion, listing of all candidates with Ctrl + A, and so on); it is comprehensive and also offers many tips. Most (good) plugins also provide their own help pages, so I think that answers your question best.
Don't try to implement some sort of introspection (as one commenter remarked to "shoot yourself in the foot"); rather, use the existing facilities of Vim. You can even write your own documentation pages (under ~/.vim/doc/*.txt); that's what I do: Collect tips, and short clips from other help locations. And it offers a place to document some older plugins that don't have their own help page.

Using the 'f' command in vim to search more than just the current line

I know that philosophically the f/F command is used to search through the current line. However, other than [LINE]G f, what would be the best way to jump to somewhere else in the file in the style of the f command?
Add this line to you ~/.vimrc
set incsearch
to activate incremental search and use /foo<CR> to search forward or ?bar<CR> to search backward.
Note that, like fFtT, /? can also be very useful as motions for dcsv.
If you don't mind using a plugin, there are a bunch of them designed around the idea of multi-dimensional fFtT like this one. Take a look around vim.org.
You may want to use the vim plugin EasyMotion,
github repo
vim online
<Leader>f<char> will search forward from current line to the end of current window.
<Leader>F<char> will search backward from current line to the start of current window.
for all usage :help easymotion.txt
Christian Brabandt's ft_improved plugin extends the built-in f / t commands to search in following lines, too.

Configure tab to show list of variants instead of cycling through in VIM

When opening new buffer it VIM, I type:
new /path/to/fi
If I hit "tab" at this point it cycles through files. How to configure VIM to show list of variants instead of going for the first one?
set wildmenu
Is all you need to add to your .vimrc. Read :help wildmenu.
Set your wildmode setting to something different, for example
set wildmode=list:longest
If I misunderstood the question completely, yell ... :)
(This is not a direct answer to your question, but I think it's even better :)
You should check out the Command-T plugin, inspired by TextMate's 'Go To File'. It filters out possible combinations very intelligently, just type a few characters of each subdirectory enough to distinguish it and it 'gets' it, the characters don't have to be at the beginning and can don't have to be sequential. It also shows you a list of options left.
I realize this is a terrible explanation so check out this video to see how it works.
The downside is it requires Vim to be compiled with Ruby support.
Control-P (ctrlp.vim) is a replacement for Command-T written in VimScript, so it doesn't require Ruby.

Is vim able to detect the natural language of a file, then load the correct dictionary?

I am using several languages, and currently I am obliged to indicate to vim with which of these the spell check must be done. Is there a way to set up vim so that it automatically detects the correct one? I vaguely remember that in a previous version of vim, when the spell check was not integrated, the vimspell script made this possible.
It would be even better if this could apply not only to a file but also to a portion of a file, since I frequently mix several languages in a single file. Of course, I would like to avoid to load several dictionaries simultaneously.
I don't know if there is a way to autodetect it, but if you put vim:spell:spelllang=foo,bar,baz at the bottom of the file, vim will set the spellchecking languages to foo, bar, and baz when the file is opened. Note that you must put at least one space before that text, or vim will think it's part of the file.
Since vim is missing this feature, I found it useful to define shortcuts like these in .vimrc:
command! Nb :set spelllang=nb
command! En :set spelllang=en

Opening files in Vim using Fuzzy Search

I'm looking for a way to make Vim have the ability to open a file by fuzzy-searching its name.
Basically, I want to be able to define a project once, and then have a shortcut which will give me a place to type a file name, and will match if any letters match up.
This kind of functionality exists in most editors I've seen, but for the life of me I can't understand how to get Vim to do this.
Note that I'm looking for something that won't require me to have any idea where in my directory tree a file is. I just want to be able to open it by the filename, regardless of what directory it's in.
Thanks
There are two great vim plugins for this.
ctrlp:
Written in pure VimL
Works pretty much everywhere
Supports custom finders for improved performance
Most popular fuzzy search plugin for Vim
Command-T:
Written in C, VimL and Ruby
Fast out of the box
Requires +ruby support in Vim
Recommends Vim version >= 7.3
EDIT:
I use CtrlP with ag as my custom finder and it's incredibly quick (even on massive projects) and very portable.
An example of using ag with CtrlP:
if executable('ag')
" Use Ag over Grep
set grepprg=ag\ --nogroup\ --nocolor
" Use ag in CtrlP for listing files. Lightning fast and respects .gitignore
let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""'
endif
CommandT for Vim is very much the comparable feature as in TextMate. My work flow is now
1) open up MacVim
2) :cd ~/my_project
3) (I have this mapped as described in the installation help)
4) C-v the file to open the file in a vertical split, or CR to open a new horizontal split.
5) to close the split, use :bd (buffer delete)
6) to switch to another buffer, I have BufferExplorer installed, so just \be and select
This workflow is comparable to TextMate, it takes a while to get used to, and I'm still learning.
Basic solution
Simply add this to your .vimrc
nnoremap <C-p> :find ./**/*
Pressing Ctrl+p will now allow you to fuzzyfind files in your current working directory and sub-directories thereof. Use the tab key to cycle through options.
Related solution
For those who want to keep it basic i.e. no plugins, this entertaining video shows another way to achieve fuzzy file find in vim.
They actually use
set path+=**
set wildmenu
in their .vimrc to find files in current sub-directories.
For example, with :find *Murph followd by tab, I would find the files KilianMurphy2012Why.R and KilianMurphy2014ROLE.R in subdir code which I can cycle through with the tab key. The first solution above has the advantage that the relative path is also shown.
Note that your current working directory will matter and that other files on your path (:set path?) will also be found with the this type of solution. The wildmenu option adds visual information and is not essential.
For a keyboard shortcut, add
nnoremap <C-p> :find *
to your .vimrc. Now you will be able to quickly search for files inside your project/current dir with Ctrl+p in normal mode.
What about http://www.vim.org/scripts/script.php?script_id=1984 Then there is http://github.com/jamis/fuzzy_file_finder .
Also see these blog posts: http://weblog.jamisbuck.org/2008/10/10/coming-home-to-vim and http://weblog.jamisbuck.org/2009/1/28/the-future-of-fuzzyfinder-textmate
HTH

Resources