Skip to content

Vim: Znajdowanie plików w podkatalogach

by zergu on Marzec 26th, 2009 Blip Facebook Flaker Twitter Wykop

Jak wiadomo, Vim nie jest IDE. I w sumie dobrze. Jednak jest kilka funkcjonalności typowych dla IDE, które by się w nim przydały. Jedną z nich jest łatwe otwieranie plików w projekcie. Jako, że nie ma nic takiego wbudowanego, trzeba sobie poradzić samemu.

Jak mogło by takie wyszukiwanie i otwieranie plików działać? Otóż, w naszym przykładzie, po naciśnięciu ctrl+f i wpisaniu interesującej nas nazwy pliku (np. BasePlace) otrzymujemy taki wynik:

vim-find

Sposób na uruchomienie tego mechanizmu jest przedstawiony na stronie http://vim.wikia.com/wiki/Find_files_in_subdirectories. Jednakże, jest on dość chaotyczny, a efekt końcowy ma pewne wady. Dlatego przedstawiam sprawę po mojemu.

Cały kod podany poniżej trzeba wstawić do własnego .vimrc. Pierwsza część to funkcja do znajdowania, w niezmienionej postaci:

" Find file in current directory and edit it.
function! Find(name)
  let l:list=system("find . -name '".a:name."' | perl -ne 'print \"$.\\t$_\"'")
  let l:num=strlen(substitute(l:list, "[^\n]", "", "g"))
  if l:num < 1
    echo "'".a:name."' not found"
    return
  endif
  if l:num != 1
    echo l:list
    let l:input=input("Which ? (CR=nothing)\n")
    if strlen(l:input)==0
      return
    endif
    if strlen(substitute(l:input, "[0-9]", "", "g"))>0
      echo "Not a number"
      return
    endif
    if l:input<1 || l:input>l:num
      echo "Out of range"
      return
    endif
    let l:line=matchstr("\n".l:list, "\n".l:input."\t[^\n]*")
  else
    let l:line=l:list
  endif
  let l:line=substitute(l:line, "^[^\t]*\t./", "", "")
  execute ":e ".l:line
endfunction
command! -nargs=1 Find :call Find("<args>")

Następnie wstawiamy funkcję napisaną w Pythonie, również pochodząca ze wcześniej wspomnianej strony. Jest ona odpowiedzialna za sam proces wyszukiwania plików. Jednak tutaj zaszło klika zmian:

  • szukanie jest niewrażliwe na wielkość znaków,
  • szukanie ignoruje katalogi .svn
  • rozpoczynając szukanie, nie trzeba potwierdzić (ale też nie można zmienić) katalogu, w którym się szuka; domyślnie jest to katalog w którym otwarliśmy Vima.
python << EOL
import vim
 
def Finder(*args):
    start_dir = vim.eval('getcwd()')
    find_cmd = (r'find %s -iname "*%s*" ! -name "*.svn*" -type f -printf %%p:1:-\\n' % (start_dir, args[0]))
    vim.command("cgete system('%s')" % find_cmd)
    vim.command('botright copen')
EOL
command! -nargs=1 Find :py Finder("<args>")

I na koniec pozostało przypisanie sobie funkcji do skrótu ctrl-f:

map! <C-f> <Esc> :Find ;
map  <C-f> :Find ;

Po :Find jest spacja, aby nie trzeba było jej dopisywać za każdym razem. Teraz wystarczy wykonać :source ~/.vimrc lub zrestartować Vima, a następnie ctrl+f i voilà!

Podobne wpisy:

  1. Uprawnienia plików w repo SVN
  2. Krótko: Vim i powolna edycja plików PHP
  3. Ignorowanie plików w SVN

Autorzy zdjęć: kennymatic

From → Symfony, Vim

3 Comments
  1. Ja bym polecał raczej plugin do szybkiego otwierania plików typu Command-T albo FuzzyFinder – sam używam tego pierwszego.
    Ich działanie polega na tym, że wpisujesz kilka znaków ze ścieżki do pliku i dostajesz listę dopasowań, z której otwierasz plik, który Cię interesuje.

  2. A jak sobie radzi z dużym drzewem katalogów? Nie ma mulenia?

    BTW. Zergu jeszcze nie napisał o tym, ale stworzył ostatnio przydatny plugin do skakania po projekcie w symfony https://github.com/zergu/Vim-Project-Jumper – póki co tylko sf 1.4, ale planuje dopisać dla sf2 i railsów.

  3. Muli przy pierwszym użyciu (kilka-kilkanaście sekund przy projekcie na parę tys. plików), ale jak już zindeksuje, to działa normalnie. Czasem chwilę mu zajmie zanim zajarzy dodany niedawno plik – generalnie używam tego pluginu częściej niż NERDTree :)
    Do Railsów jest rails.vim, który z tego co się orientuję, umożliwia szybkie przeskakiwanie między modelem/kontrolerem/widokiem/helperem/testem, ale nie wiem dokładnie, mało w RoR piszę i pluginu nie testowałem.

Leave a Reply

Note: XHTML is allowed. Your email address will never be published.

Subscribe to this comment feed via RSS

Notify me of followup comments via e-mail. You can also subscribe without commenting.