sponsor Vim development Vim logo Vim Book Ad

basic Tip #1432: File search similar to cmd-t in TextMate

 tip karma   Rating 9/5, Viewed by 640 

created:   December 4, 2006 3:37      complexity:   basic
author:   Samuel Hughes      as of Vim:   5.7

This adds similar capabilities as the cmd-t file search feature in TextMate. I put the "Find" function below into my .vimrc since it's relatively small. I found a similar function a while ago, but I can't trace the author in order to credit them. Anyway, I modified it a bit in order to make it more like TextMate.

It will search recursively whatever directory you are in.

So for example, I am in "~/alumni" directory and I am looking for a file named "admin_controller.rb" somewhere beneath "~/alumni", I could type:

:Fi adm trol

where "adm" and "trol" are excerpts of "admin_controller.rb", and the result will be:

1       ./app/controllers/admin_controller.rb                                                                            
2       ./test/functional/admin_controller_test.rb
Which ? (<enter>=nothing)

Then you type the number next to the file you're searching for and hit enter.

In other words, it's searching with this as its input, "*adm*trol*", the asterisk's being wildcards. The wildcards replace the spaces from your original search and are also added to the beginning and end of your search keywords.

I also mapped it to:
map ,f :Fi

which seems to be quicker.

And the function is:

function! Find(name)
  let l:_name = substitute(a:name, "\\s", "*", "g")
  let l:list=system("find . -iname '*".l:_name."*' -not -name \"*.class\" -and -not -name \"*.swp\" | 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 ? (<enter>=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>")

 rate this tip  Life Changing Helpful Unfulfilling 

<<manage a tasklist of TODO code snippets (e.g. //TODO) | Use of vim to convert files mangled by Palm OS memo conduit >>

Additional Notes

[email protected], December 5, 2006 2:37
Hi, nice thing.
How about making it a script?
Setting a list of serchable directories (something like 'tags' variable?)
[email protected], December 6, 2006 0:00
Hi, this is really nice :) This tip has number 1432 . If you go to tip number 1234 (vimtip #1234), you'll find my original post ;) While reading throught comments to my post, I promised to make script out of the tip, which never happened ... And also please notice that there is a fix in comments, look for "try-catch".

Happy vimming !

--
Vladimir
[email protected], December 7, 2006 17:59
Vladimir,

I'm glad you found your way to this tip so you can get some credit. What do you think of my textmate modification? The search capability was always my biggest argument for ever using textmate, but adding this little change to your Find script makes vim work just as well. And your script alone is obviously good too.

Sam
If you have questions or remarks about this site, visit the vimonline development pages. Please use this site responsibly.
Questions about Vim should go to [email protected] after searching the archive. Help Bram help Uganda.
    stats
Sponsored by Web Concept Group Inc. SourceForge.net Logo