创建major mode, 如何定义子样式

emasc lisp新手。最近看到一个类似latex的文档系统typst, 就想写个major mode试试。由于typst把代码和文档结合在一起,keyword样式有点不好搞。就想在大括号内内部样式能不能覆盖整体样式。这是一个typst文档的例子

#{
  // 这里是代码
  align(center)[
    #block(text(weight: 700, 1.75em, title))
    #v(1em, weak: true)
    #date
  ]
}

= Introduction
这里是文档

这是我的部分代码,注释部分是chatgpt对我这个问题的解答,试了下没有效果

;; (defun typst-inner-face-match (limit)
;;   (catch 'found
;;     (while (re-search-forward "{\\([^}]*\\)}" limit t)
;;       (let ((text-start (match-beginning 1))
;;              (text-end (match-end 1)))
;;         (when (and text-start text-end)
;;           (set-match-data (list text-start text-end))
;;           (throw 'found t))))
;;     nil))

;; (defface typst-custom-face
;;   '((t (:foreground "green")))
;;   "Custom face for text inside braces."
;;   :group 'markup-faces)

(defvar typst-font-lock-keywords
  `((,(regexp-opt typst-global-keywords t) . font-lock-keyword-face)
     ("\\(#\\w+\\)[[(]" . '(1 font-lock-function-name-face))
     ;; (typst-inner-face-match . typst-custom-face)
     )
  "Minimal highlighting expressions for typst mode")

总的代码可以在github上看到:GitHub - Ziqi-Yang/typst-mode.el: An Emacs major mode for a markup-based typesetting system `typst`

所以这个问题大概是问「如何依据词法元素所在的特定的词法环境决定它如何 font lock」?

大概可以参考:

  1. Org-mode,参考 org-set-font-lock-defaults
  2. web-mode,参考 web-mode-fontify,fontify 是完全自制的
  3. mmm-mode
2 个赞
  • keyword 可以借助 re-builder 调试。你的例子我没看明白,这里是代码 究竟是指当前行(由于没代码,所以留下占位符,一如底下的 这里是文档),还是它下面整块都是代码?代码到底是这个文档系统自己的指令,还是类似 markdown/orgmode 里的代码块?不如你直接圈出要高亮的单词/句子。

  • 子模式可以参考 Emacs 内置的 mhtm-mode

    (defconst mhtml--js-submode
      (mhtml--construct-submode 'js-mode
                                :name "JS"
                                :end-tag "</script>"
                                :syntax-table js-mode-syntax-table
                                :propertize #'js-syntax-propertize
                                :keymap js-mode-map))
    
  • 其他参考楼上提到几个模式。 mmm-mode 看起来比较容易使用:mmm-jinja2/mmm-jinja2.el at master · glynnforrest/mmm-jinja2 · GitHub

2 个赞

哦哦,其实是类似于markdown mode和org mode里的代码块。大括号内都表示代码,大括号和大括号所在行两者的外部表示文档。

我觉得web mode挺类似的,看看~

基于 tree sitter 应该会容易一些,也准确一些

SeniorMars/tree-sitter-typst: A TreeSitter parser for the Typst File Format (github.com)