From 364f61b03d601d2cb3aeb1687da2d1b2a232474c Mon Sep 17 00:00:00 2001 From: Rahul Martim Juliato Date: Fri, 19 Apr 2024 23:21:20 -0300 Subject: [PATCH] feat: add markdown-ts-mode --- etc/NEWS | 5 ++ lisp/progmodes/markdown-ts-mode.el | 106 +++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 lisp/progmodes/markdown-ts-mode.el diff --git a/etc/NEWS b/etc/NEWS index 8ad1e78ca60..ea0640337fb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1688,6 +1688,11 @@ A major mode based on the tree-sitter library for editing Elixir files. *** New major mode 'lua-ts-mode'. A major mode based on the tree-sitter library for editing Lua files. +--- +*** New major mode 'markdown-ts-mode'. +A major mode based on the tree-sitter library for editing Markdown files. + + ** Minibuffer and Completions +++ diff --git a/lisp/progmodes/markdown-ts-mode.el b/lisp/progmodes/markdown-ts-mode.el new file mode 100644 index 00000000000..a20d754f83e --- /dev/null +++ b/lisp/progmodes/markdown-ts-mode.el @@ -0,0 +1,106 @@ +;;; markdown-ts-mode.el --- tree sitter support for Markdown -*- lexical-binding: t; -*- + +;; Copyright (C) 2024 Free Software Foundation, Inc. + +;; Author : Rahul Martim Juliato +;; Maintainer : Rahul Martim Juliato +;; Created : April 2024 +;; Keywords : markdown md languages tree-sitter + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Commentary: +;; + +;;; Code: + +(require 'treesit) +(require 'subr-x) + +(declare-function treesit-node-parent "treesit.c") +(declare-function treesit-node-type "treesit.c") +(declare-function treesit-parser-create "treesit.c") + +(defvar markdown-ts--treesit-settings + (treesit-font-lock-rules + :language 'markdown + :override t + :feature 'delimiter + '([ "[" "]" "(" ")" ] @shadow) + + :language 'markdown + :feature 'paragraph + '([((atx_heading) @font-lock-keyword-face) + ((block_quote_marker) @font-lock-string-face) + ((code_span) @font-lock-string-face) + ((emphasis) @underline) + ((image_description) @link) + ((indented_code_block) @font-lock-string-face) + ((link_destination) @font-lock-string-face) + ((setext_heading) @font-lock-keyword-face) + ((strong_emphasis) @bold) + ((thematic_break) @shadow) + (block_quote (block_quote_marker) @font-lock-string-face) + (block_quote (paragraph) @font-lock-string-face) + (fenced_code_block (code_fence_content) @font-lock-string-face) + (fenced_code_block (fenced_code_block_delimiter) @font-lock-doc-face) + (inline_link (link_destination) @font-lock-string-face) + (inline_link (link_text) @link) + (list_item (list_marker_dot) @font-lock-keyword-face) + (list_item (list_marker_minus) @font-lock-keyword-face) + (list_item (list_marker_plus) @font-lock-keyword-face) + (list_item (list_marker_star) @font-lock-keyword-face) + (shortcut_link (link_text) @link) + ]))) + +(defun markdown-ts-imenu-node-p (node) + "Check if NODE is a valid entry to imenu." + (equal (treesit-node-type (treesit-node-parent node)) + "atx_heading")) + +(defun markdown-ts-imenu-name-function (node) + "Return an imenu entry if NODE is a valid header." + (let ((name (treesit-node-text node))) + (if (markdown-ts-imenu-node-p node) + (thread-first (treesit-node-parent node)(treesit-node-text)) + name))) + +(defun markdown-ts-setup () + "Setup treesit for `markdown-ts-mode'." + (setq-local treesit-font-lock-settings markdown-ts--treesit-settings) + (treesit-major-mode-setup)) + +;;;###autoload +(define-derived-mode markdown-ts-mode fundamental-mode "markdown[ts]" + "Major mode for editing Markdown using tree-sitter grammar." + (setq-local font-lock-defaults nil + treesit-font-lock-feature-list '((delimiter) + (paragraph))) + + (setq-local treesit-simple-imenu-settings + `(("Headings" markdown-ts-imenu-node-p nil markdown-ts-imenu-name-function))) + + (when (treesit-ready-p 'markdown) + (treesit-parser-create 'markdown) + (markdown-ts-setup))) + +(derived-mode-add-parents 'markdown-ts-mode '(markdown-mode)) + +(if (treesit-ready-p 'markdown) + (add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-ts-mode))) + +(provide 'markdown-ts-mode) +;;; markdown-ts-mode.el ends here -- 2.39.2