grep, but uses
tree-sitter to search for structure instead of strings.
This isn't available packaged anywhere. That's fine, use
nix-env -if https://github.com/BrianHicks/tree-grepper/archive/refs/heads/main.tar.gz
If you have a Rust toolchain set up, you can also clone this repo and run
Use it like
grep (or really, more like
$ tree-grepper -q elm '(import_clause (import) (upper_case_qid)@name)' ./src/Main.elm:4:7:name:Browser ./src/Main.elm:6:7:name:Html ./src/Main.elm:8:7:name:Html.Events ...
tree-grepper will output one match per (newline-delimited) line. The columns here are filename, row, column, match name, and match text.
Note, however, that if your query includes a match with newlines in the text they will be included in the output! If this causes problems for your use case, try asking for JSON output (
-f json) instead.
tree-grepper uses Tree-sitter's s-expressions to find matches. See the tree-sitter docs on queries for what all you can do there.
We add one important thing on top of the standard query stuff (including
require but not other functions, you could do this:
(call_expression (identifier)@_fn (arguments . (string)@import .) (#eq? @_fn require))
In addition to text output, we support JSON output for scripting: just specify
-f json. You also get more info (the match's end location and node kind) by asking for JSON output. This is handy for discovery: if you want to see the node names for your target language, try something like
tree-grepper -q rust '(_)' -f json, replacing
rust with the language of your choice.
... and your favorite? We're open to PRs for adding whatever language you'd like!
For development, there's a nix-shell setup that'll get you everything you need. Set up nix (just Nix, not NixOS) and then run
nix-shell in the root of this repository.
After that, you just need to add a tree-sitter grammar to the project. The tree-sitter project keeps an up-to-date list, so you may not even need to write your own!
- Add your grammar as a subtree to this repo:
git subtree add --squash --prefix vendor/tree-sitter-LANGUAGE https://github.com/ORG/tree-sitter-LANG BRANCH(where
BRANCHis whatever main branch the project uses) Add the update command to
- Set up compilation in
build.rsby following the pattern there.
- Set up a new target in
src/language.rsby following the patterns there.
- Add a test like
- Try to run with insta:
cargo insta testand then
cargo insta review. If the output looks right, open a PR!
See LICENSE in the source.