#grep #search #regex #outline #indentation

app ogrep

Tool for searching in indentation-structured texts

4 releases (2 breaking)

Uses old Rust 2015

0.4.0 Sep 24, 2019
0.2.1 Mar 16, 2018
0.2.0 Mar 16, 2018
0.1.0 Mar 8, 2018

#599 in Text processing

MIT license


Outline grep

Featureful tool for searching in indentation-structured text files.

Inspired by ogrep by Matt Brubeck. That ogrep is compact and beautiful, but not featureful.

See also ogrep — port of this tool written in Python (to be truly, it was first).


ogrep is much like grep, both can search for matches and display their context. But context in grep is “N lines before/after match”, and in ogrep it is “lines above matched one with lower indentation”.

Let me explain. I use this tool mostly when working with GN build files, so I'll use some large BUILD.gn file as an example. Usual task is to search for source file name and understand which target includes this file and under which conditions.

Let's find mentions of “arena.cc” file:

# grep arena.cc BUILD.gn

Ok, now we now that our file is here, but don't know target. Let's ask for some context:

# grep -C2 arena.cc BUILD.gn

Nope, not that useful. Let's try ogrep:

ogrep arena.cc BUILD.gn
 102: component("net") {
 385:   if (!is_nacl) {
 386:     sources += [
 409:       "base/arena.cc",

Now that's useful! We immediately know that file in included into “net“ target under “!is_nacl” condition.

It is even better, because ogrep can use colors, here is a picture:


Using Cargo (any platform)

Install Rust and Cargo, if you haven't yet, then

cargo install ogrep-rs


Install Homebrew, then

brew install kriomant/ogrep-rs/ogrep-rs

Other platforms

Sorry, not yet, but I'm working on it. Use Cargo for now.


There are plently of available options, run with --help to list them.

Tool is useful not only for strict indentation-based files (like Python source) or GN build files, but for wide range of text files, because even not-indentation based ones are usually formatted for convenience.

There are even some C-related hacks built-in.

Here is brief feature list:

  • Pattern is fixed text by default, but you may use arbitrary regular expression with -e.

  • Usual -w (match whole words) and -i (case-insensitive search) are available.

  • Tool preserve some blank lines between matches, because it helps to visually separate groups of related matches, you can turn it off with --no-breaks.

  • Sometimes it is useful to see whether there were other lines between matched ones. Use --ellipsis for that.

  • If you integrate otool with external tools, --print-filename options may be useful, it tells to print filename if any match found.

  • By default “if-else” branches are treated specially: if-branches are preserved so you know conditions even when match is found in “else” branch:

  • Traditional context (displaying N leading and/or trailing lines around matched one) is also supported with --context/-C, --before-context/-B and --after-context/-A options.

# ./ogrep filename_util_icu BUILD.gn
 102: component("net") {
2106:   if (!is_nacl) {
2210:     if (use_platform_icu_alternatives) {
2222:     } else {
2228:       sources += [
2229:         "base/filename_util_icu.cc",

This can be turned off with --no-smart-branches.

  • Preprocessor instructions in C files are often written without any indentation (or indentation is inserted after “#”). So tool ignores preprocessor instructions by default until --no-ignore-preprocessor is given.

More intelligent handling of preprocessor instructions (parallel context) is planned.

Searching in directory

Integration with external tools

otool in intended to search in single file only. And it is not so fast to be used for searching through many files. But you can integrate it with other search tools like this:

grep -l cache_used -r . --include='*.cc' | xargs -n1 ogrep --print-filename cache_used

Builtin git grep support

ogrep has builtin integration with git grep: when -g option is given, second argument is passed to git grep as path specification. All relevant options (-w, -i, etc.) are also passed to git grep automatically, --print-filename is forced.

ogrep -g cache_used '*.cc'


~83K SLoC