branch: elpa/typst-ts-mode
commit 34d522c0a0d8eec9a8b3a6855cf394e7d5c8fb84
Author: meowking <mr.meowk...@posteo.com>
Commit: meowking <mr.meowk...@posteo.com>

    feat: enhance fontification of sub/superscripts in math mode
    closes: https://codeberg.org/meow_king/typst-ts-mode/issues/43
---
 typst-ts-faces.el | 146 +++++++++++++++++++++++++++++++++++++++---------------
 typst-ts-mode.el  |  47 +++++++++++++++++-
 2 files changed, 153 insertions(+), 40 deletions(-)

diff --git a/typst-ts-faces.el b/typst-ts-faces.el
index ca956ee1d1..8a65994707 100644
--- a/typst-ts-faces.el
+++ b/typst-ts-faces.el
@@ -46,177 +46,245 @@
 
 (defface typst-ts-shorthand-face
   '((t :inherit shadow))
-  "Face for linebreak.")
+  "Face for linebreak."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-error-face
   '((t :inherit font-lock-warning-face))
-  "Face for linebreak.")
+  "Face for linebreak."
+  :group 'typst-ts-faces)
 
 ;; Markup Faces 
=================================================================
 
 (defface typst-ts-markup-header-indicator-face
   '((t :weight bold))
-  "Face for Typst ts markup header indicator.")
+  "Face for Typst ts markup header indicator."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-face
   '((t :weight bold))
-  "Face for Typst ts markup headers text.")
+  "Face for Typst ts markup headers text."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-indicator-face-1
   `((t :inherit typst-ts-markup-header-indicator-face
        :height ,(nth 0 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-indicator-face'.")
+  "See `typst-ts-markup-header-indicator-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-face-1
   `((t :inherit typst-ts-markup-header-face
        :height ,(nth 0 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-face'.")
+  "See `typst-ts-markup-header-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-indicator-face-2
   `((t :inherit typst-ts-markup-header-indicator-face
        :height ,(nth 1 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-indicator-face'.")
+  "See `typst-ts-markup-header-indicator-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-face-2
   `((t :inherit typst-ts-markup-header-face
        :height ,(nth 1 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-face'.")
+  "See `typst-ts-markup-header-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-indicator-face-3
   `((t :inherit typst-ts-markup-header-indicator-face
        :height ,(nth 2 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-indicator-face'.")
+  "See `typst-ts-markup-header-indicator-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-face-3
   `((t :inherit typst-ts-markup-header-face
        :height ,(nth 2 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-face'.")
+  "See `typst-ts-markup-header-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-indicator-face-4
   `((t :inherit typst-ts-markup-header-indicator-face
        :height ,(nth 3 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-indicator-face'.")
+  "See `typst-ts-markup-header-indicator-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-face-4
   `((t :inherit typst-ts-markup-header-face
        :height ,(nth 3 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-face'.")
+  "See `typst-ts-markup-header-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-indicator-face-5
   `((t :inherit typst-ts-markup-header-indicator-face
        :height ,(nth 4 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-indicator-face'.")
+  "See `typst-ts-markup-header-indicator-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-face-5
   `((t :inherit typst-ts-markup-header-face
        :height ,(nth 4 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-face'.")
+  "See `typst-ts-markup-header-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-indicator-face-6
   `((t :inherit typst-ts-markup-header-indicator-face
        :height ,(nth 5 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-indicator-face'.")
+  "See `typst-ts-markup-header-indicator-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-header-face-6
   `((t :inherit typst-ts-markup-header-face
        :height ,(nth 5 typst-ts-markup-header-scale)))
-  "See `typst-ts-markup-header-face'.")
+  "See `typst-ts-markup-header-face'."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-url-face
   '((t :inherit link))
-  "Face for url.")
+  "Face for url."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-emphasis-indicator-face
   '((t :inherit italic))
-  "Face for emphasis.")
+  "Face for emphasis."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-emphasis-face
   '((t :inherit italic))
-  "Face for emphasis.")
+  "Face for emphasis."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-strong-indicator-face
   '((t :inherit bold))
-  "Face for strong.")
+  "Face for strong."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-strong-face
   '((t :inherit bold))
-  "Face for strong.")
+  "Face for strong."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-item-indicator-face
   '((t :inherit shadow))
-  "Face for item.")
+  "Face for item."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-term-indicator-face
   '((t :inherit shadow))
-  "Face for term indicator.")
+  "Face for term indicator."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-term-term-face
   '((t :inherit bold))
-  "Face for term text.")
+  "Face for term text."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-term-description-face
   '((t :inherit italic))
-  "Face for term description.")
+  "Face for term description."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-quote-face
   '((t :inherit shadow))
-  "Face for quote.")
+  "Face for quote."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-linebreak-face
   '((t :inherit escape-glyph))
-  "Face for linebreak.")
+  "Face for linebreak."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-escape-face
   '((t :inherit escape-glyph))
-  "Face for linebreak.")
+  "Face for linebreak."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-raw-indicator-face
   '((t :inherit shadow))
-  "Face for rawblock and rawspan indicator.")
+  "Face for rawblock and rawspan indicator."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-raw-blob-face
   '((t :inherit shadow))
-  "Face for rawblock and rawspan blob.")
+  "Face for rawblock and rawspan blob."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-rawblock-indicator-face
   '((t :inherit typst-ts-markup-raw-indicator-face))
-  "Face for rawblock indicator.")
+  "Face for rawblock indicator."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-rawblock-lang-face
   '((t :inherit font-lock-type-face))
-  "Face for rawspan ident.")
+  "Face for rawspan ident."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-rawblock-blob-face
   '((t :inherit typst-ts-markup-raw-blob-face))
-  "Face for rawblock blob.")
+  "Face for rawblock blob."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-rawspan-indicator-face
   '((t :inherit typst-ts-markup-raw-indicator-face))
-  "Face for rawspan indicator.")
+  "Face for rawspan indicator."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-rawspan-blob-face
   '((t :inherit typst-ts-markup-raw-blob-face))
-  "Face for rawspan blob.")
+  "Face for rawspan blob."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-label-face
   '((t :inherit homoglyph))
-  "Face for label.")
+  "Face for label."
+  :group 'typst-ts-faces)
 
 (defface typst-ts-markup-reference-face
   '((t :inherit homoglyph))
-  "Face for reference.")
+  "Face for reference."
+  :group 'typst-ts-faces)
 
 ;; Code Faces 
===================================================================
 
 (defface typst-ts-code-indicator-face
   '((t :inherit shadow))
-  "Face for code indicator #.")
+  "Face for code indicator #."
+  :group 'typst-ts-faces)
 
 ;; Math Faces 
===================================================================
 
 (defface typst-ts-math-indicator-face
   '((t :inherit shadow))
-  "Face for math indicator $.")
+  "Face for math indicator $."
+  :group 'typst-ts-faces)
+
+;; code from Auctex 
+(defface typst-ts-superscript-face
+  '((t (:height 0.85)))
+  "Face used for superscripts."
+  :group 'typst-ts-faces)
+
+;; code from Auctex 
+(defface typst-ts-subscript-face
+  '((t (:height 0.85)))
+  "Face used for subscripts."
+  :group 'typst-ts-faces)
+
+;; code from Auctex 
+(defface typst-ts-script-char-face
+  (let ((font '(:inherit underline)))
+    `((((class grayscale) (background light))
+       (:foreground "gray25" ,@font))
+      (((class grayscale) (background dark))
+       (:foreground "gray" ,@font))
+      (((class color) (background light))
+       (:foreground "DarkRed"))
+      (((class color) (background dark))
+       (:foreground "salmon"))
+      (t (,@font))))
+  "Face used for the script chars ^ and _."
+  :group 'typst-ts-faces)
+
+
 
 (provide 'typst-ts-faces)
 
diff --git a/typst-ts-mode.el b/typst-ts-mode.el
index d0247adc7f..94e01267f2 100644
--- a/typst-ts-mode.el
+++ b/typst-ts-mode.el
@@ -70,6 +70,17 @@ NOTE this option must be set before the first 
loading(opening typst file)"
   :type 'boolean
   :group 'typst-ts)
 
+;; code from Auctex
+(defcustom typst-ts-mode-math-script-display '((raise -0.5) . (raise 0.5))
+  "Display specification for subscript and superscript content.
+The car is used for subscript, the cdr is used for superscripts."
+  :type '(cons (choice (sexp :tag "Subscript form")
+                       (const :tag "No lowering" nil))
+               (choice (sexp :tag "Superscript form")
+                       (const :tag "No raising" nil)))
+  :group 'typst-ts)
+
+
 ;; 
==============================================================================
 ;; TODO typst has three modes (namely 'markup', 'code' and 'math')
 ;; Currently only add common settings to syntax table
@@ -214,7 +225,10 @@ NOTE this option must be set before the first 
loading(opening typst file)"
    :language 'typst
    :feature 'math-standard
    '((symbol) @font-lock-constant-face
-     (letter) @font-lock-constant-face)
+     (letter) @font-lock-constant-face
+     (attach
+      ["^" "_"] @typst-ts-script-char-face
+      (_) @typst-ts-mode-render-math-scripts-fn))
 
    :language 'typst
    :feature 'math-extended
@@ -227,6 +241,36 @@ NOTE this option must be set before the first 
loading(opening typst file)"
 If you want to enable/disable specific font lock feature, please change
 `treesit-font-lock-level' or modify `typst-ts-mode-font-lock-feature-list'.")
 
+;; modified from Auctex
+(defun typst-ts-mode-unfontify-region (beg end &rest _ignored)
+  "Unfontify region from BEG to END."
+  (font-lock-default-unfontify-region beg end)
+  (while (< beg end)
+    (let ((next (next-single-property-change beg 'display nil end))
+          (prop (get-text-property beg 'display)))
+      (when (and (eq (car-safe prop) 'raise)
+                 (null (cddr prop)))
+        (remove-text-properties beg next '(display rear-nonsticky)))
+      (setq beg next))))
+
+
+(defun typst-ts-mode-render-math-scripts-fn (node override start end)
+  (let* ((ns (treesit-node-start node))
+         (ne (treesit-node-end node))
+         (prev-node-text (treesit-node-text (treesit-node-prev-sibling node)))
+         (display-properties (pcase prev-node-text
+                               ("_" (car typst-ts-mode-math-script-display))
+                               ("^" (cdr typst-ts-mode-math-script-display))))
+         (face (pcase prev-node-text
+                 ("_" 'typst-ts-subscript-face)
+                 ("^" 'typst-ts-superscript-face))))
+    (add-text-properties
+     ns ne
+     `(
+       rear-nonsticky (display)
+       display ,display-properties
+       face ,face))))
+
 (defun typst-ts-mode-highlight-raw-block-fn (blob-node _override _start _end)
   "A function used in function `typst-ts-mode-font-lock-rules'.
 This function assign `typst-ts-markup-rawblock-blob-face' to those raw block
@@ -632,6 +676,7 @@ typst tree sitter grammar (at least %s)!" 
(current-time-string min-time))
 
   (treesit-major-mode-setup)
 
+  (setq-local font-lock-unfontify-region-function 
#'typst-ts-mode-unfontify-region)
   (setq-local indent-line-function #'typst-ts-mode-indent-line-function))
 
 ;;;###autoload

Reply via email to