Using Ack To Search Elixir Code
Tags: ack, elixir, tooling
Published: 2022-05-27 16:03:21

I've been a fan of [ack](https://beyondgrep.com) for quite some time.  Somehow (and I'm not quite sure how) once or twice it's found stuff in source code that VSCode simply misses (likely I was searching wrong with VSCode).  And there are a few things I've found that make it even more effective in searching Elixir code that I thought I'd share.

## How Do I Configure Ack?

First, how to get ack?  If you're on a Mac then simply use Homebrew to install it: `brew install ack`. For those on Windows there's a Chocolatey NuGet package [here](https://community.chocolatey.org/packages/ack). If neither of those are an option for you there are installation instructions on the homepage.

Secondly how should you configure ack for optimum use with Elixir?  I think the easiest way to set things up is to create an `.ackrc` file in your home directory.  So a `~/.ackrc file`.  This is mine:

`--type=elixir
--smart-case
--ignore-dir=deps
--pager=less -R -F
`

In order, this is what this `.ackrc` does:

1. It tells ack to assume I'm searching elixir files (`--type=elixir`).  Ack is smart enough to ignore .git directories and other temporary files when it's searching for text.  This tells ack that I want to search only through Elixir files by default.
2. Smart case tells ack to search case-insensitive unless I have an upper case letter in my search string. Obviously Elixir is case-sensitive so this is very helpful. 
3. Ignore directory (`--ignore-dir`) tells ack not to search in a given directory and below.  Since I don't usually want to see stuff that's brought in via Hex packages I ignore everything in any of the deps directory by default.
4. Use [less](https://en.wikipedia.org/wiki/Less_(Unix)) for the pager.  Less is a very neat tool that allows you to scroll forwards and backward through text output to the terminal one screenful at a time.  So by specifying less for my pager the ack output is sent out one page at a time and I can scroll forward and backward through it as I need to.

If you want to use ack without these settings (assuming you've added them to an `.ackrc` on your machine) you can simply pass the `--noenv` switch to ack on the command line and any settings in your `.ackrc` will be ignored.

## How Do I Actually Search?

Open a terminal and then change to the root directory of the source code you want to search (e. g. `~/git/myelixirapp`).  Then it's `ack stringtosearchfor` (e. g. `ack defmodule`).  If you want to search for a string containing spaces you need to enclose the string in double quotes (e. g. `ack "defmodule MyGreatModule do"`). 

One very interesting option for ack is to tell it to search within a given range of code.  For instance if I'm looking for a function called "reverse_string_and_json_encode" then I can use a few parameters to ack on the command line to help me quickly narrow my search.  By using this command line: `ack --range-start 'def reverse_string_and_json_encode do' --range-end 'end'` I can find the exact definition of the function whereever it's defined.  Two important details about range-start and range-end:

1. Range-start and range-end both support regular expressions.  For example, if I weren't quite sure of the name of the function I could also pass `--range-start 'def reverse\w+'` and `--range-end 'end'`
2. You use single quotes (not double quotes) around the strings you use with range-start and range-end.

## Are There Other Options?

If you don't care to use ack (or you have some sort of aversion to it), ack actually lists several good alternatives on their home page (under More Tools → Other grep-like tools). I won't bother to repeat them here. 

## What Else?

If you spot something I've got wrong, please let me know!  One reason I even bother to write this up is that I know of no method faster to find something I've gotten wrong than to share it with nerds.