Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ethan-leba/tree-edit

🌲 Structural editing in Emacs for anyβ„’ language!
https://github.com/ethan-leba/tree-edit

emacs evil-mode tree-sitter

Last synced: about 1 month ago
JSON representation

🌲 Structural editing in Emacs for anyβ„’ language!

Awesome Lists containing this project

README

        

#+HTML:

I'm looking for work! Check out my LinkedIn or email me at [email protected].

#+HTML:

MELPA

#+HTML:

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


#+HTML:

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 [[#supported-languages][language-agnostic]] editing operations that map directly to
the structure of the language*, abstracting away the process of manually
entering syntax. Leveraging the [[https://github.com/tree-sitter/tree-sitter][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).

- [[file:doc/using-tree-edit.org][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.
- [[file:doc/evil-tree-edit.org][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 [[https://emacsconf.org/2021/talks/structural/][EmacsConf talk]]!

* How does it work?

#+HTML:

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 [[file:doc/implementation.org][this high-level
overview]] or check out this [[file:doc/parser-examples.org][org doc with executable code examples]] demonstrating
how the syntax generation works.

* Supported languages

| Status | Language |
|--------+----------------|
| βœ… | [[https://github.com/tree-edit/tree-sitter-python][Python]] ([[https://github.com/ethan-leba/tree-edit/issues/33][issue]]) |
| πŸ”¨ | [[https://github.com/tree-edit/tree-sitter-c][C]] ([[https://github.com/ethan-leba/tree-edit/issues/54][issue]]) |
| πŸ”¨ | [[https://github.com/tree-edit/tree-sitter-java][Java]] ([[https://github.com/ethan-leba/tree-edit/issues/34][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 [[https://github.com/ethan-leba/tree-edit/blob/main/doc/using-tree-edit.org#adding-new-languages-to-tree-edit][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:
https://github.com/tree-sitter/tree-sitter/issues/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
- [[https://github.com/drym-org/symex.el][symex]] :: Structural navigation and editing with backends for lisp and tree-sitter
- [[https://github.com/mickeynp/combobulate][combobulate]] :: Structural navigation and limited structural editing
- [[https://github.com/manateelazycat/grammatical-edit][grammatical-edit]] :: Smartparens-like using tree-sitter (?)
- [[https://github.com/meain/evil-textobj-tree-sitter][evil-textobj-tree-sitter]] :: Evil mode text objects using tree-sitter queries.
- [[https://github.com/abo-abo/lispy][lispy]] :: Lisp structural editing package -- big inspiration for tree-edit!
- [[https://github.com/Fuco1/smartparens][smartparens]] :: Multilingual package with structural editing limited to matching delimiters.