Введение: Markdown встречает Tree-sitter

Если вы давно работаете в Emacs и пишете Markdown — будь то документация, README, статьи или заметки — вы наверняка сталкивались с markdown-mode из MELPA. Это добротный, зрелый инструмент. Но Emacs 31 меняет правила игры.

Emacs 31 поставляется с markdown-ts-mode прямо из коробки — и этот режим появился из предложения разработчика Рахула М. Хулиато, который отправил идею и первую версию кода в список emacs-devel ещё в начале 2025 года. Это не сольный проект: Стефан Маркс присоединился позже и стал соавтором режима, отвечая за большую часть того, что делает его удобным сегодня.

Среди ключевых нововведений Emacs 31 — упрощённая настройка tree-sitter с автоматической установкой грамматик, новый встроенный markdown-ts-mode с живой подсветкой синтаксиса внутри блоков кода и рендерингом инлайн-изображений, а также рендеринг LSP-документации через markdown-ts-mode в Eglot.

В этом руководстве мы разберём всё по порядку: что такое markdown-ts-mode, как его настроить, что он умеет и где у него пока есть шероховатости.


Что такое markdown-ts-mode и зачем он нужен

Tree-sitter — это инкрементальная библиотека парсинга, позволяющая редактору строить точное синтаксическое дерево файла в реальном времени. Это принципиально отличается от старого подхода с регулярными выражениями.

Раньше использование tree-sitter требовало ручной конфигурации: нужно было настраивать treesit-language-source-alist, скачивать грамматики, компилировать их и переключать режимы на ts-варианты. В Emacs 31 большая часть этой боли ушла.

Этот релиз продолжает тренд, при котором ядро Emacs поглощает функциональность, ранее требовавшую внешних пакетов, постепенно снижая сложность конфигурации как для новых, так и для опытных пользователей.

markdown-ts-mode — это мажорный режим для редактирования Markdown, построенный поверх tree-sitter. В отличие от старого markdown-mode, он использует два парсера одновременно:

Markdown использует две грамматики: основную и отдельную для инлайн-парсинга. Это позволяет точно разбирать как структуру документа (заголовки, списки, блоки кода), так и инлайн-разметку (жирный, курсив, ссылки) — независимо друг от друга.

ℹ Что такое tree-sitter?
Tree-sitter — C-библиотека инкрементального парсинга. Emacs интегрировал её начиная с версии 29. В отличие от regex-font-lock, дерево пересчитывается только в изменённых частях файла, что даёт стабильную подсветку даже в больших документах.

Сравнение: markdown-mode vs markdown-ts-mode

Характеристикаmarkdown-mode (MELPA)markdown-ts-mode (встроен)
ИсточникMELPA (внешний пакет)GNU Emacs 31 (встроен)
ПарсингРегулярные выраженияTree-sitter
Подсветка блоков кодаЧастичнаяЖивая, в языке блока
Инлайн-изображенияНетДа
LSP через EglotОграниченноНативно
Поддержка тем (modus-themes)ЕстьДобавляется
Статус в Emacs 31Устарел для новых функцийРекомендован

Новый markdown-ts-mode — это не замена с паритетом функций, а другой фундамент. Он берёт лучшее из tree-sitter и делает Markdown первоклассным гражданином Emacs.


Установка и первый запуск

Главное правило, которое нужно усвоить сразу:

Нет никакой необходимости скачивать или добавлять этот пакет в менеджер пакетов. Старый MELPA-репозиторий откажется устанавливаться начиная с Emacs 31 и очень беден по функциям — если вы его используете, вы не используете новый встроенный markdown-ts-mode.

Шаг 1: Проверка tree-sitter

Прежде всего убедитесь, что ваш Emacs собран с поддержкой tree-sitter:

M-: (featurep 'treesit) RET

Должно вернуть t. Также убедитесь, что у вас есть инструменты для компиляции грамматик — make, gcc и другие. Tree-sitter требует пакета tree-sitter-cli в вашем дистрибутиве, его можно проверить командой tree-sitter --version.

Шаг 2: Базовая конфигурация init.el

Добавьте в ваш init.el:

(autoload 'markdown-ts-mode "markdown-ts-mode" nil t)
(dolist (re '("\\.md\\'" "\\.mdx\\'" "\\.markdown\\'"))
  (add-to-list 'auto-mode-alist (cons re 'markdown-ts-mode)))
(with-eval-after-load 'markdown-ts-mode
  (require 'markdown-ts-mode-x))

После этого оба файла — основной режим и библиотека markdown-ts-mode-x с дополнительными возможностями — будут загружены, и вы сможете открывать Markdown-файлы в новом режиме.

Шаг 3: Тестирование без изменения конфигурации

Если хотите попробовать, не трогая рабочий конфиг:

Сохраните конфигурацию выше в файл, например testing.el, и запустите Emacs командой emacs -Q --load 'testing.el'. Вы получите чистую сессию Emacs с настроенным тестовым окружением.

Шаг 4: Установка грамматик

При первом открытии .md-файла Emacs может сообщить, что грамматика не найдена.

Это означает, что Emacs не нашёл грамматику для markdown в системе (по умолчанию — в ~/.emacs.d/tree-sitter/). Emacs предложит установить её, то есть скачать и скомпилировать из репозитория, уже указанного в исходном коде markdown-ts-mode. Нужно согласиться — Emacs клонирует репозиторий грамматики, скомпилирует её и перейдёт к второй грамматике.

💡 Автоустановка грамматик

В Emacs 31 появилась переменная treesit-auto-install-grammar. Установите её в 'always, чтобы грамматики ставились автоматически без запроса:

(setq treesit-auto-install-grammar 'always)

Для корректной работы markdown-ts-mode протестирован со следующими версиями грамматик: tree-sitter-markdown v0.4.1 и tree-sitter-markdown-inline v0.4.1.


flowchart TD
    A[Открываем .md файл] --> B{Грамматика установлена?}
    B -- Нет --> C[Emacs предлагает установить]
    C --> D[Клонирование + компиляция grammars]
    D --> E[Установка markdown-inline]
    E --> F[markdown-ts-mode активен]
    B -- Да --> F
    F --> G[Подсветка синтаксиса]
    F --> H[Инлайн-изображения]
    F --> I[Подсветка внутри блоков кода]


Возможности markdown-ts-mode

Подсветка синтаксиса через tree-sitter

Основа режима — точная синтаксическая подсветка, основанная на реальном дереве разбора, а не на регулярных выражениях. Это означает корректное поведение даже в сложных и вложенных конструкциях.

Режимы языков для блоков кода определяются из таблицы markdown-ts-code-block-modes и эвристики, добавляющей -ts-mode и -mode к имени языка. Если режим вашего языка не распознаётся корректно, добавьте его в markdown-ts-code-block-modes. Мажорный режим каждого языка активируется один раз на буфер markdown-ts-mode во временном буфере для извлечения настроек font-lock и tree-sitter.

То есть блок ```python в вашем Markdown будет подсвечиваться как настоящий Python — со всеми правилами подсветки этого языка.

Поддержка инлайн-изображений

Это одна из самых заметных новинок. Изображения, указанные в Markdown-синтаксисе (![alt](url)), теперь могут отображаться прямо в буфере — без дополнительных плагинов.

Интеграция с Eglot (LSP)

Eglot теперь рендерит LSP-документацию через markdown-ts-mode — это значит, что всплывающие подсказки и документация к функциям, приходящие с языкового сервера в формате Markdown, будут корректно подсвечены и отформатированы.

Работа с блоками кода

Блоки кода с указанием языка должны подсвечиваться в режиме этого языка; отступы внутри блока кода должны работать согласно правилам этого режима; то же касается и заполнения текста (fill) внутри блока кода.

📝 Пример: блок Python в Markdown

В файле .md с таким содержимым:

```python
def hello():
    print("Hello, world!")
```

markdown-ts-mode применит подсветку Python-синтаксиса прямо внутри блока — включая ключевые слова, строки и функции.

Поддержка тем (Modus Themes)

Разрабатывается поддержка markdown-ts-mode faces в темах — в первую очередь в modus-themes. Emacs 31 поставляется с восемью доступными цветовыми схемами, включая варианты для людей с дейтеранопией и тританопией.


Известные ограничения и подводные камни

Ни один инструмент не идеален, особенно в первом релизе. Важно понимать текущие ограничения.

Отсутствие LSP «из коробки»

Eglot не поможет вам подготовить систему к LSP-работе — он воспользуется тем, что уже есть. Автоопределения и автоконфигурации нет. Нет никаких подсказок пользователю, поэтому нужно читать документацию, чтобы знать об этом.

Грамматики не идут в комплекте

Поддержка tree-sitter не включает грамматики. Они, как правило, отсутствуют в репозиториях дистрибутива, поэтому пользователям приходится самостоятельно находить грамматику и компилировать её. Emacs даже не даёт хорошей рекомендации, где их взять.

В Emacs 31 эта ситуация улучшена за счёт авто-предложения установки при первом запуске режима — но базовые инструменты (gcc, make) всё равно должны быть на машине.

Требования к версии libtree-sitter

Старые рантаймы дистрибутивов, например версия 0.22, не поддерживаются, поскольку некорректно обрабатывают несмежные диапазоны парсера. Поддерживаемые комбинации: Emacs 29/30 с libtree-sitter 0.25.x, и Emacs 31 со снимками разработки с libtree-sitter 0.25.x или 0.26.x.

Двунаправленный текст

Текст с разметкой может потребовать дополнительного переноса строки перед двунаправленным текстом для корректного отображения. Это ограничение движка отображения Emacs.

⚠ MELPA-пакет устарел
Если вы устанавливали markdown-ts-mode из MELPA раньше — удалите его. Нет никакой необходимости скачивать или добавлять этот пакет в менеджер пакетов. Старый (уже заархивированный) репозиторий MELPA откажется устанавливаться на Emacs 31 и выше и очень беден по функциям.

Альтернатива: md-ts-mode для Emacs 29+

Если вы ещё не перешли на Emacs 31, но хотите попробовать схожую функциональность:

Пакет md-ts-mode основан на markdown-ts-mode из GNU Emacs 31, изначально написанном Рахулом Мартимом Хулиато. Это мажорный режим для редактирования Markdown на основе tree-sitter, совместимый с Emacs 29, 30 и 31.

Установка грамматик для него:

M-x treesit-install-language-grammar RET markdown RET
M-x treesit-install-language-grammar RET markdown-inline RET

На Emacs 31 он также отдаёт предпочтение md-ts-mode над встроенным markdown-ts-mode.


Заключение

markdown-ts-mode в Emacs 31 — это не просто ещё один режим для Markdown. Это сигнал о направлении развития редактора: tree-sitter становится стандартом, а не экспериментом. От улучшенной поддержки языков до повышения удобства использования и производительности — tree-sitter в Emacs продолжает развиваться впечатляющими темпами.

Что мы имеем в итоге:

  • Встроен — не нужно ничего ставить из MELPA
  • Точная подсветка — синтаксическое дерево вместо regex
  • Подсветка внутри блоков кода — Python как Python, Rust как Rust
  • Инлайн-изображения — прямо в буфере
  • LSP-документация — через Eglot, красиво
  • Активное развитие — сообщество продолжает улучшать режим

Если вы присматривались к Emacs, но откладывали из-за сложности настройки, Emacs 31 движется в правильном направлении. Больше функций работает из коробки, а улучшения в системе завершения делают ванильный Emacs более современным без необходимости использовать фреймворки вроде Doom или Spacemacs.

💡 С чего начать прямо сейчас
  1. Установите Emacs 31 (или проверьте снапшот)
  2. Убедитесь, что есть gcc, make, tree-sitter-cli
  3. Добавьте конфигурацию markdown-ts-mode в init.el
  4. Откройте любой .md файл и согласитесь с установкой грамматик
  5. Наслаждайтесь живой подсветкой Python/Rust/JS прямо в блоках кода