Home InternationalBuilding Emacs Major Modes with Tree-sitter: Lesso...
International⭐ Featured

Building Emacs Major Modes with Tree-sitter: Lessons Learned

Over the past year I’ve been spending a lot of time building Tree-sitter-powered major modes for Emacs – clojure-ts-mode (as co-maintainer), neocaml (from scratch), and asciidoc-mode (also from scratch). Between the three projects I’ve accumulated enough knowledge (and battle scars) to write about the experience. This post distills the key lessons for anyone thinking about writing a Tree-sitter-based major mode, or curious about what it’s actually like.

6 April 2026 at 07:49 pm
1 views
Building Emacs Major Modes with Tree-sitter: Lessons Learned

Over the past year, I’ve been immersed in the process of building Tree-sitter-powered major modes for Emacs. This journey has involved contributions to clojure-ts-mode as a co-maintainer, as well as creating neocaml and asciidoc-mode from scratch. Through these projects, I’ve gained a wealth of knowledge and encountered various challenges that have shaped my understanding of developing Tree-sitter-based major modes. This article aims to distill the key lessons learned, offering insights for anyone considering embarking on a similar endeavor or simply curious about the process.

My first major mode, clojure-ts-mode, was a collaborative effort with the existing maintainers. This project provided an excellent opportunity to learn the ropes of integrating Tree-sitter with Emacs. Tree-sitter is a language server that offers robust parsing capabilities, enabling advanced syntax highlighting and code navigation. Emacs, with its powerful extensibility, is an ideal host for such tools. The initial challenge was understanding how to properly configure Tree-sitter within Emacs, ensuring that the language server communicates effectively with the editor.

One of the most important lessons I learned was the importance of a solid Tree-sitter grammar. The grammar forms the foundation of the language server’s understanding of the syntax, which directly impacts the quality of features like auto-completion, error highlighting, and code navigation. For clojure-ts-mode, the existing grammar was a great starting point, but I soon discovered that it required fine-tuning to match Clojure’s nuanced syntax. This involved working closely with the Tree-sitter maintainers to ensure that the grammar accurately captured the language’s intricacies.

When I moved on to developing neocaml from scratch, I faced the daunting task of creating a Tree-sitter grammar for a language I was not entirely familiar with. Neocaml, a dialect of Caml, posed unique challenges due to its specific syntax and features. I spent considerable time studying the language’s specification and existing parsers to build an accurate grammar. This process was slow and meticulous, but it was essential to ensure that the major mode provided accurate parsing and useful features.

Another critical aspect of developing major modes is integrating with Emacs’ existing infrastructure. Emacs has a rich set of conventions and APIs that must be respected to create a seamless user experience. For instance, the major mode must properly define syntax tables, faces, and hooks to integrate with features like flycheck for linting or company-mode for auto-completion. Additionally, ensuring compatibility with other popular packages, such as magit for Git integration, is crucial for a well-rounded experience.

The process of building asciidoc-mode further solidified my understanding of these challenges. AsciiDoc is a lightweight markup language, and its grammar is somewhat simpler than Clojure or Neocaml. However, the project still required careful attention to detail. One particularly tricky aspect was handling AsciiDoc’s extensive set of options and attributes, which needed to be reflected in the syntax highlighting and code navigation features.

Throughout these projects, I also encountered issues related to performance and resource management. Tree-sitter can be resource-intensive, especially for large files or complex grammars. Ensuring that the major mode did not negatively impact Emacs’ performance was a priority. This involved optimizing the grammar, leveraging Tree-sitter’s caching mechanisms, and carefully managing the language server’s lifecycle within Emacs.

In addition to technical challenges, I learned the importance of community engagement and documentation. Maintaining a major mode requires ongoing support and updates, particularly as the underlying language or Tree-sitter evolves. Engaging with the community—whether through forums, mailing lists, or issue trackers—proved invaluable for addressing user feedback and identifying potential improvements.

Documentation is another critical component. Clear and concise documentation helps users understand how to use the major mode effectively and encourages contributions from the community. For each project, I made a point to provide comprehensive README files, examples, and tutorials to guide new users and contributors.

Reflecting on these experiences, I realize that developing Tree-sitter-powered major modes is both rewarding and challenging. The process demands a deep understanding of both the target language and the intricacies of Emacs’ extensibility model. However, the end result—a powerful, feature-rich editing experience—is well worth the effort. For anyone considering embarking on a similar journey, I encourage you to start with a well-defined grammar, engage with the community, and prioritize performance and compatibility. By addressing these key aspects, you can create a major mode that not only meets the needs of users but also contributes to the broader ecosystem.

Source: OCaml Planet
📰 Related News
Ollama 0.2.6 Released with Native Gemma 4 Support and Enhanced Performance
Ollama 0.2.6 Released with Native Gemma 4 Support and Enhanced Performance
Ollama 0.2.6 is now live, featuring native support for Google's Gemma 4 models and improved local inference performance for Windows, macOS, and Linux.
14 Apr
Weekly news roundup: Shortages spread to MLCCs; SK Hynix reportedly in talks with Microsoft and Google
Weekly news roundup: Shortages spread to MLCCs; SK Hynix reportedly in talks with Microsoft and Google
Below are the most-read DIGITIMES Asia stories from the week of April 6-April 13, 2026:
14 Apr
cutile-stencil 0.2.0
cutile-stencil 0.2.0
An xDSL-based stencil compiler that generates optimized GPU kernels via NVIDIA cuTile
14 Apr
merlin-llm added to PyPI
merlin-llm added to PyPI
Merlin — a fast local LLM for agentic coding on Apple Silicon
14 Apr
Fluent Cut - Craft and compose videos programmatically in PHP with an elegant fluent API
Fluent Cut - Craft and compose videos programmatically in PHP with an elegant fluent API
Craft and compose videos programmatically in PHP with an elegant fluent API - b7s/fluentcut
14 Apr
Crypto Investor at Center of Trump Corruption Allegations Now Sees Himself as ‘Victim’
Crypto Investor at Center of Trump Corruption Allegations Now Sees Himself as ‘Victim’
Justin Sun has accused Trump-affiliated World Liberty Financial of misconduct and a general lack of transparency.
14 Apr
nvidia-nat-weave 1.7.0a20260413
nvidia-nat-weave 1.7.0a20260413
Subpackage for Weave integration in NeMo Agent Toolkit
14 Apr
nvidia-nat-s3 1.7.0a20260413
nvidia-nat-s3 1.7.0a20260413
Subpackage for S3-compatible integration in NeMo Agent Toolkit
14 Apr
Social Security Trust Fund to Run Dry in 2032: Just 6 Years From Now
Social Security Trust Fund to Run Dry in 2032: Just 6 Years From Now
Six years. That is how much time separates retirees from a Social Security system that, by its own projections, runs out of money. If you are 56 years old...
14 Apr
cane-gpu-perf added to PyPI
cane-gpu-perf added to PyPI
GPU inference benchmarking with opinionated diagnostics
13 Apr