• Stars
    star
    298
  • Rank 139,663 (Top 3 %)
  • Language
    Rust
  • License
    Other
  • Created over 3 years ago
  • Updated about 1 month ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Like grep, but uses tree-sitter grammars to search

tree-grepper

Works like grep, but uses tree-sitter to search for structure instead of strings. Here's a longer introduction to the tool as a blog post.

Installing

Use nix to install:

  1. if you have cachix installed, cachix use tree-grepper.
  2. nix-env -if https://github.com/BrianHicks/tree-grepper/archive/refs/heads/main.tar.gz

Usage

Use it like grep (or really, more like ack/ag/pt/rg.)

$ tree-grepper -q javascript '(call_expression)'
./tests/cmd/hello-world.js:1:1:query:console.log("Hello, World!")

By default, 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 #eq? and #match?): if you name a pattern starting with an underscore, it will not be returned in the output. This is primarily useful for filtering out matches you don't really care about. For example, to match JavaScript calls to 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.

Tree View

You can discover the node names your language uses by using --show-tree languagename path/to/file. When you do this, tree-grepper will parse the file and print out an indented tree view.

For a file like this:

console.log("Hello, World!");

You'll get a tree like this:

$ tree-grepper --show-tree javascript tests/cmd/hello-world.js
program 1:1
  expression_statement 1:1
    call_expression 1:1
      member_expression 1:1
        identifier 1:1: console
        . 1:8: .
        property_identifier 1:9: log
      arguments 1:12
        ( 1:12: (
        string 1:13
          " 1:13: "
          string_fragment 1:14: Hello, World!
          " 1:27: "
        ) 1:28: )
    ; 1:29: ;

Each line takes the format {node name} {location} {source, if present}. Source is only shown for the leaf-most nodes on the tree to avoid printing a huge block. However, tree-grepper can extract text from any of these nodes.

You can use the node names in queries. For example:

  • tree-grepper -q elm (exposed_value) would have matches on average and percentOf.
  • tree-grepper -q elm (module_declaration) would match on the whole declaration, module Math exposing (average, percentOf)

Supported Languages

You can find all the languages in your installed version of tree-grepper by running tree-grepper --languages. The output is the literal language strings you can use in queries or --show-tree. For example, here's the list for the current version of tree-grepper:

$ tree-grepper --languages
c
cpp
elixir
elm
go
haskell
java
javascript
markdown
nix
php
python
ruby
rust
typescript

Don't see 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!

Note: when you're adding grammars, please keep things in alphabetical order.

  1. Add your grammar as an input in flakes.nix, following the template of the ones already there. You'll need to add an entry in inputs and another in the updateVendor script.
  2. Run direnv reload to make sure you have the latest changes, then update-vendor to get your grammar in the right place. Make sure the repo content under vendor/YOUR-GRAMMAR looks how you expect.
  3. Set up compilation in build.rs by following the pattern there.
  4. Set up a new target in src/language.rs by following the patterns there.
  5. Add the language to the list of supported languages in this readme.

License

See LICENSE in the source.

More Repositories

1

nix-script

write scripts in compiled languages that run in the nix ecosystem, with no separate build step
Rust
180
star
2

elm-benchmark

Benchmarking for Elm
Elm
47
star
3

emit

Build graphs to process streams. Now with Celery!
Python
39
star
4

elm-particle

Simple particle system for web apps. Designed for visual flourishes like confetti.
Elm
37
star
5

elm-csv

Decode CSV in the most boring way possible.
Elm
31
star
6

elm-string-graphemes

Do string operations based on graphemes instead of codepoints or bytes.
Elm
24
star
7

Markov-Generator

a simple gibberish / random text generator using a markov chain.
JavaScript
20
star
8

spacemacs-rocks

A tip blog!
CSS
20
star
9

elm-duet

Rust
19
star
10

candy-and-allowances

Candy and Allowances Code
Elm
17
star
11

dotfiles.nix

Nix
16
star
12

django-plop

Django plop middleware
Python
13
star
13

finch

A task manager which implements the Final Version algorithm by Mark Forster
Go
7
star
14

frankenblog

Hugo for SEO + bake-in, Elm for rendering everything else
Elm
6
star
15

elm-trend

generate trend lines for two-dimensional data
Elm
6
star
16

elm-scientists

Code for Duplicating Scientists in Elm: Stop Sharing State blog post
Elm
6
star
17

elm-cli

Creating CLI tools with Elm !!EXPERIMENTAL!!
Elm
6
star
18

elm-json-dynamic-keys

Pies and Cake!
Elm
4
star
19

koalas

Python
4
star
20

elm-commonmark

An Elm implementation of the CommonMark spec
Elm
3
star
21

BrianHicksBlog

Django Blog
Python
3
star
22

spacemin

a ground-up .emacs.d with stolen Spacemacs stuff I like, developed at my own pace, and customized for me.
Emacs Lisp
3
star
23

lwt-docker

Docker image for lwt.sf.net
Shell
2
star
24

elm-guardian

pre-build server for Elm packages
Elixir
2
star
25

tree-db

Rust
2
star
26

bytes.zone

Elm
2
star
27

elm-subreddit-theme

Source for the Elm Subreddit theme
Makefile
2
star
28

probe

Probe lets you ship personal metrics (feelings, energy level, productivity) to external services for analysis.
Python
2
star
29

brianhicks.github.com

JavaScript
2
star
30

similar-sort

Rust
2
star
31

learnhaskell

I'm working through some books learning haskell. This here is a repo for me to document that process.
Haskell
2
star
32

xbar-review-request-status

Format GitHub review requests for use in an xbar script
Rust
2
star
33

erudite

Tail files, and do things with them.
Python
2
star
34

promtop

a quick and dirty `top` for prometheus services
Shell
1
star
35

omnifocus-scripts

JavaScript
1
star
36

minielixir

Miniature Elixir Docker Container
1
star
37

nowjs-multichat-example-coffeescript-haml

NowJS multichat example with coffeescript and haml
CoffeeScript
1
star
38

Portfolio

Brian Hicks' portfolio
Ruby
1
star
39

pt-to-things

export PivotalTracker items to Things
Python
1
star
40

lingo

Prototype language-learning tool
CSS
1
star
41

drinks

1
star
42

elm-edit-playground

Elm
1
star
43

path

Such Elm. So filesystem. Wow.
Elm
1
star
44

autoauth

Automatic Authentication for Django
Python
1
star
45

buildTemplate

a simple javascript string template
JavaScript
1
star
46

property-testing-presentation

Elm
1
star
47

aaron

Syntactic sugar for function composition
1
star
48

uatu

The watcher
Python
1
star
49

elm-infra

Upcoming Elm infrastructure
HCL
1
star
50

ListenUP

Ruby
1
star
51

elm-forbid-import

Rust
1
star
52

tinyobj

a tiny dict -> object mapper
Python
1
star
53

promtree

a quick and dirty `tree` for prometheus services
Shell
1
star
54

should

Should is a todo management program on the command line. It stores todos in plain text. Put it in your dropbox!
Python
1
star
55

funding

Python
1
star
56

elm-json-parser-toy

Elm
1
star
57

this-is-not-my-resume

This is not my ResumΓ©.
1
star
58

nur-packages

Nix packages I'm using which aren't upstream for whatever reason
Nix
1
star
59

elm-list-randori

Randori Output of the St. Louis Elm Group, 2016-11-07
Elm
1
star
60

elm-avl-exploration

AVL trees for Set and Dict in Elm - optimized for reads
Elm
1
star
61

montage

Rust
1
star
62

habitifocus

Sync OmniFocus tasks to Habitica
Go
1
star
63

graft

graft files together. Probably do stuff with 'em too. Who knows.
Haskell
1
star