0.02
The project is in a healthy, maintained state
Ruby bindings for Tree-Sitter
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

 Project Readme

Ruby tree-sitter bindings

ci valgrind asan/ubsan

Ruby bindings for tree-sitter.

The official bindings are very old, unmaintained, and don't work with modern tree-sitter APIs.

Usage

TreeSitter API

The TreeSitter API is a low-level Ruby binding for tree-sitter.

require 'tree_sitter'

parser = TreeSitter::Parser.new
language = TreeSitter::Language.load('javascript', 'path/to/libtree-sitter-javascript.{so,dylib}')

src = "[1, null]"

parser.language = language

tree = parser.parse_string(nil, src)
root = tree.root_node

root.each do |child|
  # ...
end

The main philosophy behind the TreeSitter bindings is to do a 1:1 mapping between tree-sitter's C API and Ruby, which makes it easier to experiment and port ideas from different languages/bindings.

But it feels like writing some managed C with Ruby, and that's why we provide a high-level API (TreeStand) as well.

TreeStand API

The TreeStand API is a high-level Ruby wrapper for the TreeSitter bindings. It makes it easier to configure the parsers, and work with the underlying syntax tree.

require 'tree_stand'

TreeStand.configure do
  config.parser_path = "path/to/parser/folder/"
end

sql_parser = TreeStand::Parser.new("sql")
ruby_parser = TreeStand::Parser.new("ruby")

TreeStand provides an idiomatic Ruby interface to work with tree-sitter parsers.

Dependencies

This gem is a binding for tree-sitter. It doesn't have a version of tree-sitter baked in it by default.

You must install tree-sitter and make sure that their dynamic library is accessible from $PATH, or build the gem with --disable-sys-libs, which will download the latest tagged tree-sitter and build against it (see Build from source .)

You can either install tree-sitter from source or through your go-to package manager.

Linux

ubuntu >= 22.04

sudo apt install libtree-sitter-dev

arch

sudo pacman -S tree-sitter

MacOS

sudo port install tree-sitter

or

brew install tree-sitter

Install

From rubygems, in your Gemfile:

gem 'ruby_tree_sitter', '~> 1.0'

Or manually:

gem install ruby_tree_sitter

Or from git sources, which will compile on installation:

gem 'ruby_tree_sitter', git: 'https://github.com/Faveod/ruby-tree-sitter'

Disable system libraries

To install with --disable-sys-lib, you can either:

gem install ruby_tree_sitter -- --disable-sys-libs

Or via bundle:

bundle config set build.ruby_tree_sitter --disable-sys-libs

No compilation

If you don't want to install from rubygems, git, or if you don't want to compile on install, then download a native gem from this repository's releases, or you can compile it yourself (see Build from source .)

In that case, you'd have to point your Gemfile to the gem as such:

gem 'tree_sitter', path: 'path/to/native/tree_sitter.gem'

⚠️ We're currently missing a lot of platforms and architectures. Cross-build will come back in the near future.

Parsers

You will have to install parsers yourself, either by:

  1. Downloading and building from source.
  2. Downloading from your package manager, if available.
  3. Downloading a pre-built binary from Faveod/tree-sitter-parsers which supports numerous architectures.

A note on static vs dynamic linking

This extension will statically link against a downloaded version of tree-sitter when you use the --disable-sys-lib. So any installed version of tree-sitter will not be loaded.

The native gems are also statically linked.

All other methods will dynamically link against the installed tree-sitter.

Examples

See examples directory.

Development

See docs/README.md.

🚧 👷‍♀️ Notes 👷 🚧

Since we're doing a 1:1 mapping between the tree-sitter API and the bindings, you need to be extra-careful when playing with the provided objects. Some of them have their underlying C data-structure automatically freed, so you might get yourself in undesirable situations if you don't pay attention to what you're doing.

We're only talking about Tree, TreeCursor, Query, and QueryCursor. Just don't copy them left and right, and then expect them to work without SEGFAULTing and creating a black-hole in your living-room. Assume that you have to work locally with them. If you get a SEGFAULT, you can debug the native C code using gdb. You can read more on SEGFAULTs here, and debugging here.

That said, we do aim at providing an idiomatic Ruby interface. It should also provide a safer interface, where you don't have to worry about when and how resources are freed.

To See a full list of the ruby-specific APIs, see here.

Sponsors