/ruby-tree-sitter

Ruby bindings for tree-sitter

Primary LanguageRubyMIT LicenseMIT

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

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

About

The main philosophy behind these bindings is to do a 1:1 mapping between tree-sitter's C API and Ruby.

It doesn't mean that we're going to yield the best perormance, but this design allows us to better experiment, and easily port ideas from other projects.

Versioning

This gem follows the tree-sitter versioning scheme, and appends its own version at the end.

For instance, tree-sitter is now at version 0.20.8, so this gem's version will be 0.20.8.x where x is incremented with every notable batch of bugfixes or some ruby-only additions.

Dependencies

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

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', '~> 0.20.8.1'

Or manually:

gem install ruby_tree_sitter

Or from git sources, which will compile on installation:

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

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'

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.

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