ethan-leba / tree-edit

🌲 Structural editing in Emacs for anyβ„’ language!
GNU General Public License v3.0
390 stars 16 forks source link
emacs evil-mode tree-sitter

+HTML:

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

+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.

To get an overview of tree-edit's capabilities, check out the [[https://emacsconf.org/2021/talks/structural/][EmacsConf talk]]!

+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.

| 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.

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.

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=.