I want to talk about one of the more powerful tools in my toolbox - Ag. As a developer I’ll bet you spend a fair amount of time writing code, but I’d argue you spend even more time reading code. Having a solid understanding of your language’s standard library, or a framework’s core abstractions will no doubt come in handy, but if you’re working on anything larger than a Hello World program chances are you spend a lot of time digging through code - lots of code. This is where a code searching tool like Ag proves indespensible. Yes, Ag can do your basic keyword searches, but so can your favorite editor. I want to share some of the more advanced options I find myself using day-to-day to shine a light on just how powerful of a tool it can be.
All examples will use Flipper as an example codebase we can search through. Feel free to
git clone https://github.com/jnunemaker/flipper.git && cd flipper to follow along!
- fast…really fast (orders of magnitude faster than grep/ack)
- version control system awareness - ignores file patterns in your .gitignore
- ignores file patterns added to .ignore (eg .min.js)
brew install ag
ag [file-type] [options] PATTERN [PATH]
With one argument Ag recursively searches the current directory for the given pattern.
Pass it a second argument to recursively search a directory. This becomes especially useful when working in an opinionated framework like Rails where I know all of my controller code lives under app/controllers, specs under spec/controllers, etc.
ag Gate spec
Often we’re searching for a pattern that appears in many different contexts within our app. Usually this is a core domain concept like User, Property, or Gate. We only want to hit on cases where this pattern is a whole word - meaning not a subset of a larger word.
Gate is matched, but so is
Flipper::GateNotFound since it contains
ag -w Gate
ag --ruby User
ag --js console
To see all supported file-types:
Ag returns the filename and line matching PATTERN. Sometimes we just want to list the filenames.
ag Gate -l
ag Gate -l | sort - pro tip: who doesn’t prefer a sorted list?
Limit search to file names (including path) that contain a pattern:
ag User -G controllers
ag User -G /admin/
ag UserCreator --ignore-dir spec/
--ignore-dir can be used to search everywhere, except a given directory. Multiple directories can be ignored by repeating the option.
ag User --ignore-dir spec/ --ignore-dir config/.
Ag reads from Standard Input, allowing us to pipe results into the filter.
Usecase 1: searching rails routes
In rails we can get an overview of all defined routes by running the
rake routes task. With thousands of routes and not enough coffee left in my mug this would take way too long to search through by hand.
rake routes | ag sign_in
Usecase 2: filtering logs
Have you ever tried to figure out which controllers actions are handling requests on page load? Rails logs every request a controller processes. With Ag we can easily filter for these messages:
tail -f log/development.log
tail -f log/development.log | ag "Processing by"
Usecase 3: killing processes
Every once in a while I’ll try to shut down an irb session by sending a SIGINT via ctrl-c, only to have the process fail to terminate. When a process wants to play these kind of games there’s only one option - SIGTERM baby!
Get the PID by listing running processes with
Filter the results for any irb processes
ps -ax | ag irb
ag [file-type] [options] PATTERN [PATH]
We’ve mostly seen basic words as the PATTERN parameter. It turns out PATTERN supports Perl-style regular expressions making Ag’s searching capablities limitless.
Usecase: very specific searches
Let’s search for every reference to the
Feature class in files ending in adapter.rb or store.rb.
ag -w -G "(adapter|store).rb$"
man ag | ag -C case
Ag will display the line matching PATTERN, but sometimes we need some more context. For this we can pass the context (-C) flag to print the 2 lines above and below each match. Note the difference between the above command and the result of
man ag | ag case.
This really just scratches the surface of the powers of Ag. To learn more be sure to take a read through the man pages (
man ag) in your shell of choice.