Two years ago I was feeling some pain. I was trying to find a particular helper method in one of our applications, and full-text search across an entire project was not easy to do, by default. I was using TextMate at the time, which has a full-project search feature, but unless you took the time to actually configure your project just right, it would search everything (log files, Rails, etc) and that was painful. Furthermore, I was at the command-line a lot, and it wasn’t very fun to have to switch back to TextMate just to search the project.
What I typically did was just issue a suitably arcane Unix command via the command-line:
grep "def some_helper_function" app/helpers/*.rb
That’s not too bad, really, though it gets tedious when you do it often. What’s worse is when you want to find everywhere in your project that you reference that method:
find app lib -name '*.rb' \ -o -name '*.rhtml' \ -o -name '*.rjs' \ -o -name '*.rxml' | \ xargs grep some_helper_function
That’s where the pain begins to feel crippling.
So, about that time I created a utility script, called (unimaginatively) “find”, which essentially was a thin wrapper around find+xargs+grep. Instead of the above, it let me simply say:
script/find some_helper_function
However, I could scope the search, too, for narrower (and thus faster) searches:
script/find helper "def some_helper_function"
It turned out to be so handy that we’ve since copied it to nearly all of our projects. For two years I’ve relied on this script, to the point that when I started a new (personal) project this last week, I really felt the lack.
So I got permission from David to release it as a Rails plugin. I rewrote it a bit so it doesn’t rely on find, xargs, or grep (so it can be used on more than just Unix platforms), added some simple documentation, and posted it on GitHub.
Behold: the ProjectSearch plugin for Rails.
And if you happen to be a fellow Vimmer, you might find this vim script handy, which uses script/find to search in your project:
function! RailsScriptSearch(args)
let l:savegrepprg = &grepprg
let l:savegrepformat = &grepformat
try
set grepprg=script/find
set grepformat=%f:%l:%m
execute "grep " . a:args
finally
execute "set grepformat=" . l:savegrepformat
execute "set grepprg=" . l:savegrepprg
endtry
endfunction
" search with explicitly provided arguments
command! -n=? Rgrep :call RailsScriptSearch('<args>')
" search for the word under the cursor
map <leader>rg :silent call RailsScriptSearch(expand("<cword>"))<CR>:cc<CR>
" search for the method definition of the word under the cursor
map <leader>rd :silent call RailsScriptSearch(expand("'def .*<cword>'"))<CR>:cc<CR>
Enjoy!
Jonathan Weiss
on 09 Mar 09Have you seen `rak`?
$ gem install rak $ rak ‘def helper’ app
Jon Canady
on 09 Mar 09Are you familiar with Ack?
http://betterthangrep.com/
It’s absolutely a better tool than Grep, and it even has an existing TM plugin you might be interested in:
http://somethinglearned.com/articles/2008/06/03/ack-tmbundle-a-faster-find-in-project-for-textmate
Jamis
on 09 Mar 09@Jonathan, yeah, there are a few other pure-ruby grep replacements, too. The ProjectSearch plugin isn’t a general grep replacement, though, and is handier than one in a few instances: it has knowledge of Rails project structure, and common Rails file extensions, and will only search those. This lets you save a few key strokes in your searches.
leethal
on 09 Mar 09Some times, I wish XCode knew what Rails was. When you make Cocoa apps, it’s certainly handy to have direct access to APIs, auto completions of your own methods and so on.
Brandon Ferguson
on 09 Mar 09Another holler for Ack. It’s straight amazing whether it’s used using the TM Bundle or just from the command line. Blazingly fast. The only thing I feel is missing (and it could be that I didn’t RTFM) is global search and replace. And honestly that’s likely for the better.
Terje Sten Bjerkseth
on 09 Mar 09If you’re using Git, take a look at git grep.
Terje Sten Bjerkseth
on 09 Mar 09...and examples:
git grep -e ’#define\’—and \( -e MAX_PATH -e PATH_MAX \)
Looks for a line that has #define and either MAX_PATH or PATH_MAX.
git grep—all-match -e NODE -e Unexpected
Looks for a line that has NODE or Unexpected in files that have lines that match both.
boris
on 09 Mar 09Coming from the .NET world, I would be lying if I said I didn’t miss Visual Studio for this sort of thing. Thanks for sharing your solution, Jamis. Looking forward to giving it a whirl.
Adam Bachman
on 09 Mar 09I had to add a few lines to the vim script. Right after `try`
try
” get rails_root from current buffer (set by rails.vim)
let l:_buffer = bufnr(’%’)
let l:_rails_root = getbufvar(_buffer, ‘rails_root’)
exe ‘lcd ’ . l:_rails_root
set grepprg=script/find
...
I’ve setup vim to change directories based on the current buffer, which breaks the finder (can’t find script/find, can’t require from vendor/plugin, etc.). This patch interrogates the buffer for its rails_root value, which is normally set by rails.vim.
So far it seems to work for me.
Jamis
on 09 Mar 09@Terje, it’s cool that git gives you that, and I’m sure it’s useful, but are those examples really clearer than, say, “script/find ‘MAX_PATH’”? The point of this plugin isn’t to give you more power, it’s a compromise that gives you easier searching at the cost of less power. If you really need the power (and I don’t argue that there are times that you will), then you can use git grep or ack or rak or even just grep—but for the common case, script/find shines.
gilltots
on 09 Mar 09grep -lir “something” .
that’s all you need. it’s short to type, easy to remember, and fast.
Robin
on 09 Mar 09Netbeans seems to do this with its basic FIND function, and you can jump from the “found” item to the code where it was found.
Kenn Wilson
on 09 Mar 09@gilltots Except that it will also search your logs, your .svn directories, etc, which is exactly the point of this plugin: It knows about Rails and so knows which directories are relevant.
Good work. I just add it to a big project I’m on, where I’m constantly writing out long grep lines.
Mike Larkin
on 10 Mar 09Anybody make a textmate bundle for this yet, or planning to?
Douglas Greenshields
on 10 Mar 09A third holler for ack. I use it numerous times every day. Usage is as simple as “ack MAX_PATH”. It’ll just search likely code files, ignoring logs and hidden directories (and if there’s a type it’s skipping, you can quickly add it to .ackrc). So yes, it does the same thing as script/find! The output’s also quite pretty.
Rafa
on 10 Mar 09I write a little vim function to search a text in our project and definitions methods (using ack):
http://gist.github.com/77029
Kirill Maximov
on 11 Mar 09All these tricks are nice and useful, but for me they sound as old-days school. For Rails development, I use RubyMine. To go to helper declaration, I press shortcut meta-alt-shift-n and just start typing helper name. To find usages of the helper, alt-F7 on helper name (or on its usage). No need to switch to console to find anything.
Disclaimer: I work for JetBrains, creator of the RubyMine.
Mike Mondragon
on 11 Mar 09Is there any reason for Vim users that this script/find is better than just using ctags to index all the source code in the project?
François Montel
on 14 Mar 09Nice tool. I’ve found that the “Grep Method” command in the RubyAMP TM bundle works quite well for this. (Netbeans has a similar command.)
http://code.leadmediapartners.com/
This discussion is closed.