/tree-edit

🌲 Structural editing in Emacs for any™ language!

Primary LanguageEmacs LispGNU General Public License v3.0GPL-3.0

I’m looking for work! Check out my LinkedIn or email me at ethanleba5@gmail.com.

MELPA

âš  Tree-edit is very much a work-in-progress. Expect to run into bugs and breaking changes!

Every programming language has a formally defined structure, but most text editors are completely ignorant to it. As a result, editing can oftentimes devolve into a tedious exercise in character manipulation.

Tree-edit provides language-agnostic editing operations that map directly to the structure of the language, abstracting away the process of manually entering syntax. Leveraging the tree-sitter parser, tree-edit always has access to the precise state of the syntax tree – and directly wields the grammars of the languages under edit to power it’s editing capabilities.

Overview

The repository contains two co-existing packages (that will eventually be split).

tree-edit
The core library for structural editing. This library is intended to be used by other elispers who would like to implement their own structural editing or refactoring commands.
evil-tree-edit
An evil state for structural editing with preconfigured bindings and visualization, as seen in the GIF.

To get an overview of tree-edit’s capabilities, check out the EmacsConf talk!

How does it work?

Tree-edit relies heavily on the tree-sitter parser, leveraging the JSON intermediate representation that tree-sitter outputs to have a full understanding of what is valid for a given language with no language specific efforts on tree-edit’s part.

To learn more about how tree-edit works under the hood, see this high-level overview or check out this org doc with executable code examples demonstrating how the syntax generation works.

Supported languages

StatusLanguage
✅Python (issue)
🔨C (issue)
🔨Java (issue)

See links for grammar repository and issue tracker respectively.

✅Supported
🔨Under development

Tree-edit is designed to be as language-agnostic as possible. Currently the list of supported languages is not very impressive, but in theory it should be as simple as running a script to preprocess a grammar and adding a configuration file for the language. In practice the grammars usually also need modifications in order to make the grammar ergonomic for structural modification.

See here to learn the process for adding a new language.

Custom grammars

Tree-edit uses forked version of tree-sitter grammars to power it’s editing. They are intended to work as a drop-in replacement for the standard grammar, but with tweaks to better work with tree-edit. See below for how install the forked grammars.

The tree-sitter API and grammars were not designed with the structural editing usecase in mind, so most grammars are structured in a way that makes navigation and editing in tree-edit awkward or impossible without complex and fragile hackarounds. For more context, see this GH issue: tree-sitter/tree-sitter#1558

I hope that in the future more thought will be given to this usecase in terms of the tree-sitter API and grammar design so that the forks will eventually become unnecessary, but for now they’re needed.

Installing custom grammars

The function tree-edit-install-grammars-wizard can be used interactively to install grammars.

Contributing

Contributions are very much welcome! In particular, adding language files would be a great place to help. Otherwise, the issues are a good place to propose features or find ones to implement.

In addition, reporting bugs and providing feedback on the overall design and UX of the package is much appreciated! Providing a good UX for structural editing is crucial and will become increasingly important to this package as more of the fundamental shortcomings get ironed out.

The project is fairly complex and the documentation is still in progress, so feel free to open a discussion if you’re interested in helping out but you’re not sure where to start!

Running tests

The tests can be run with make test, while cached grammars can be cleaned out with make clean.

Related projects

symex
Structural navigation and editing with backends for lisp and tree-sitter
combobulate
Structural navigation and limited structural editing
grammatical-edit
Smartparens-like using tree-sitter (?)
evil-textobj-tree-sitter
Evil mode text objects using tree-sitter queries.
lispy
Lisp structural editing package – big inspiration for tree-edit!
smartparens
Multilingual package with structural editing limited to matching delimiters.