branch: elpa/typst-ts-mode
commit 7e3f11e675a5c13323f0a64aa7cd3057277a854a
Author: Meow King <mr.meowk...@anche.no>
Commit: Meow King <mr.meowk...@anche.no>

    feat: add detailed documentation
---
 README.md                                          |   8 ++
 ...block-highlighting-mechanism-explain-0.plantuml |  52 +++++++++
 .../raw-block-highlighting-mechanism-explain-0.png | Bin 0 -> 76229 bytes
 ...block-highlighting-mechanism-explain-1.plantuml |  64 +++++++++++
 .../raw-block-highlighting-mechanism-explain-1.png | Bin 0 -> 113446 bytes
 doc/raw-block-highlighing.md                       |  66 +++++++++++
 typst-ts-embedding-lang-settings.el                | 126 +++++++++++----------
 typst-ts-mode.el                                   |  21 +---
 8 files changed, 256 insertions(+), 81 deletions(-)

diff --git a/README.md b/README.md
index de3ac6f60a..5f6ae564eb 100644
--- a/README.md
+++ b/README.md
@@ -106,6 +106,14 @@ because Typst itself do this style. You may find 
`auto-save-visited-mode`,
 6. `typst-ts-markup-header-same-height` and `typst-ts-markup-header-scale` to 
control header height. 
 7. `typst-ts-mode-before-compile-hook` and `typst-ts-mode-after-compile-hook`
 
+### Raw block highlighting
+
+For more detailed documentation about raw block highlighting see 
+[this documentation](./doc/raw-block-highlighing.md)  
+1. `typst-ts-mode-enable-raw-blocks-highlight` (default `t`)  
+2. `typst-ts-mode-highlight-raw-blocks-at-startup` (default `t`)  
+3. `typst-ts-highlight-raw-block-langs-not-in-predefined-settings` (default 
`t`)  
+
 ### Consult Imenu Integration
 If you use `consult-iemnu`
 command [consult](https://github.com/minad/consult), you way want this setting.
diff --git a/assets/raw-block-highlighting-mechanism-explain-0.plantuml 
b/assets/raw-block-highlighting-mechanism-explain-0.plantuml
new file mode 100644
index 0000000000..4ab4c34b6a
--- /dev/null
+++ b/assets/raw-block-highlighting-mechanism-explain-0.plantuml
@@ -0,0 +1,52 @@
+@startuml
+start
+floating note
+<color:purple>purple</color>: built-in functions / variables
+<color:blue>blue</color>: typst-ts-mode functions / variable
+<color:red>red</color>: typst-ts-mode raw block configuration variables
+end note
+
+partition customization {
+  :<color:blue>typst-ts-els-lang-tags-map</color>: used in 
<color:purple>treesit-language-at-point-function</color>
+  <color:blue>typst-ts-els-tag-lang-map</color>: used in 
<color:purple>treesit-range-settings</color>
+  <color:blue>typst-ts-embedding-lang-settings</color>;
+  
+  note right
+  use function <color:blue>typst-ts-els--add-lang-tags-relationship</color> and
+  function <color:blue>typst-ts-els--lang-name-remap</color> to change 
variables
+  <color:blue>typst-ts-els-lang-tags-map</color> and 
<color:blue>typst-ts-els-tag-lang-map</color>
+  ====
+  use <color:purple>shortdoc</color> to search for <color:purple>alist</color> 
related
+  functions to modifiy <color:blue>typst-ts-embedding-lang-settings</color>
+  end note
+}
+
+partition mode initialization {
+  :create typst tree sitter parser;
+  
+  if (<color:red> typst-ts-mode-enable-raw-blocks-highlight</color>) is (t) 
then
+  :add <color:blue>typst-ts-els-include-dynamically</color> function to
+  parser notification functions list;
+
+  note right
+  so <color:blue>typst-ts-els-include-dynamically</color> will receive buffer
+  change notification
+  end note
+
+  :set <color:purple>treesit-language-at-point-function</color> and 
<color:purple>treesit-range-settings</color>;
+  
+  note right
+  They are used to create tree sitter parsers. Moreover,
+  <color:purple>treesit-range-settings</color> defined which area these parser
+  will act on.
+  end note
+  
+  :run hooks (functions added in <color:purple>typst-ts-mode-hook</color>);
+
+  if (<color:red> typst-ts-mode-highlight-raw-blocks-at-startup) is (t) then
+  :load and merge predefined settings from variable
+  <color:blue>typst-ts-embedding-lang-settings</color>;
+  endif
+  endif
+}
+@enduml
diff --git a/assets/raw-block-highlighting-mechanism-explain-0.png 
b/assets/raw-block-highlighting-mechanism-explain-0.png
new file mode 100644
index 0000000000..e87d0533ad
Binary files /dev/null and 
b/assets/raw-block-highlighting-mechanism-explain-0.png differ
diff --git a/assets/raw-block-highlighting-mechanism-explain-1.plantuml 
b/assets/raw-block-highlighting-mechanism-explain-1.plantuml
new file mode 100644
index 0000000000..67fee33a8b
--- /dev/null
+++ b/assets/raw-block-highlighting-mechanism-explain-1.plantuml
@@ -0,0 +1,64 @@
+@startuml
+
+floating note
+<color:purple>purple</color>: built-in functions / variables
+<color:blue>blue</color>: typst-ts-mode functions / variable
+<color:red>red</color>: typst-ts-mode raw block configuration variables
+end note
+
+partition editing {
+  if (<color:red> typst-ts-mode-enable-raw-blocks-highlight</color>) is (t) 
then
+    fork
+      partition function: 
<color:purple>treesit-language-at-point-function</color> {
+        floating note: i.e. 
<color:blue>typst-ts-mode--language-at-point</color>
+        :raw block tag (**ignore case**) will be converted to tree sitter
+        language symbol via <color:blue>typst-ts-els-tag-lang-map</color>;
+        if (langauge symbol in map) is (nil) then
+          :use language symbol **typst**;
+        endif
+      }
+
+      if (language symbol **not** in <color:red>treesit-range-settings</color>
+      and dynamic library file for language is loaded) then
+        :treesit will create a toplevel parser of that language;
+        note left
+          which is what we don't want, since it will mess the foncication
+          (i.e. highlight area outside the raw block)
+          we will delete it later
+        end note
+      endif
+      
+    fork again
+      partition <color:purple>treesit-range-settings</color> {
+        :create local parsers (parse specific areas) according to
+        <color:purple>treesit-range-settings</color> (which defines queries for
+        finding area, and specifys parser language for that area);
+      }
+    end fork
+
+    partition function: <color:blue>typst-ts-els-include-dynamically</color> {
+      note
+      this function is called when buffer changes.
+      see <color:red>treesit-parser-add-notifier</color>
+      end note
+
+      :get all parsers (including toplevel, local);
+
+      while (parser in parsers)
+        if (the language of the parser haven't been marked loaded) then
+          if (try load settings via 
<color:blue>typst-ts-embedding-lang-settings</color>) is (not success) then
+            if 
(<color:red>typst-ts-highlight-raw-block-langs-not-in-predefined-settings</color>)
 is (t) then
+              :guess the corresponding tree sitter major mode of the language;
+              :create a temporary buffer with hooks disabled;
+              :load settings from local variables;
+            endif
+          endif
+          :mark the language as loaded;
+        endif
+      endwhile
+    }
+  endif
+}
+
+end
+@enduml
diff --git a/assets/raw-block-highlighting-mechanism-explain-1.png 
b/assets/raw-block-highlighting-mechanism-explain-1.png
new file mode 100644
index 0000000000..e85526cc29
Binary files /dev/null and 
b/assets/raw-block-highlighting-mechanism-explain-1.png differ
diff --git a/doc/raw-block-highlighing.md b/doc/raw-block-highlighing.md
new file mode 100644
index 0000000000..d9ba736fc5
--- /dev/null
+++ b/doc/raw-block-highlighing.md
@@ -0,0 +1,66 @@
+# Raw Block Highlighting
+
+## Customization Option
+1. `typst-ts-mode-enable-raw-blocks-highlight`  
+2. `typst-ts-mode-highlight-raw-blocks-at-startup`  
+Due to the lazy fontification feature of `treesit`, raw blocks won't be 
+highlighted at the startup by default. Set it to `t` to enable this feature.
+3. `typst-ts-highlight-raw-block-langs-not-in-predefined-settings`
+
+## Mechanism
+
+![0](../assets/raw-block-highlighting-mechanism-explain-0.png)  
+![1](../assets/raw-block-highlighting-mechanism-explain-1.png)  
+
+## Customize
+1. add/modify raw block language tags/language relationship.  
+   for example   
+   ~~~typst
+   ```newtag
+   ```
+   ~~~
+   -> customize `typst-ts-els-lang-tags-map` and `typst-ts-els-tag-lang-map`   
+   -> use `typst-ts-els--add-lang-tags-relationship` helper function.  
+2. remap existing raw block language to new raw block language  
+   like `c++` -> `cpp`  
+   -> customize `typst-ts-els-lang-tags-map` and `typst-ts-els-tag-lang-map`  
+   -> use `typst-ts-els--lang-name-remap` helper function.  
+   
+3. add new pre-configured language settings  
+   -> customsize `typst-ts-embedding-lang-settings`  
+   -> use `shortdoc` command to search for `alist` related functions to modify 
it  
+   -> use `typst-ts-embedding-lang-settings-test` function to test your 
configuration.  
+   settings specification: see `typst-ts-embedding-lang-settings`.  
+   explain:  
+   1. key: language name: which is the name specified in your tree sitter 
dynamic library. Or you can find it by:   
+      1. go to the `<xxx>-ts-mode` major mode function  
+      2. find `(treesit-parser-create 'cpp)`. So `cpp` is the language name, 
instead
+      of the `c++`  
+   2. `:feature`: the source file name without extension of the 
`<xxx>-ts-mode`. Or
+      you can find it in variable `features`  
+   3. `:font-lock`: go to the source file, find `treesit-font-lock-settings`  
+   4. `:indentation`: go to the source file, find 
`treesit-simple-indent-rules`  
+   5. `:ts-feature-list`: go to the source file, find 
`treesit-font-lock-feature-list`  
+
+## Current Limitations
+
+1. update raw block language will not delete the old local parser  
+   -> this will cause error of raw block raw block highlighting.
+   -> you need to delete the whole raw block to remove the local parser  
+   -> this is due to the behavior of `treesit--update-ranges-local`  
+   -> currently haven't thought out good way to handle it  
+   
+2. typst raw block cannot live in typst raw block  
+For example:
+~~~typst
+```typ
+= a  // highlight currectly
+```typ
+= b // cannot highlight
+```
+```
+~~~
+This is probably due to the Typst tree sitter parser.
+
+3. Although we also load the indentation configurations, many language in raw 
block
+still cannot do indentation. Some languages like `rust`(`rust-ts-mode`) works.
diff --git a/typst-ts-embedding-lang-settings.el 
b/typst-ts-embedding-lang-settings.el
index b69d2ff3e1..e2cef65afa 100644
--- a/typst-ts-embedding-lang-settings.el
+++ b/typst-ts-embedding-lang-settings.el
@@ -26,17 +26,6 @@
 ;;; Code:
 (require 'treesit)
 
-(defcustom typst-ts-enable-predefined-settings t
-  "Whether to use predefined embedding language settings.
-Use predefined settings will speed up the process of merging tree sitter
-language mode settings.  However, settings (especially feature list)
-may vary with different versions of a language mode, so you may get wrong
-settings.
-If you enable this feature, we highly recommend you to customize it when
-error occurs."
-  :type 'boolean
-  :group 'typst-ts)
-
 (defcustom typst-ts-highlight-raw-block-langs-not-in-predefined-settings t
   "Whether to highlight raw block of language that is not in settings.
 i.e. not in `typst-ts-embedding-lang-settings'.
@@ -225,7 +214,10 @@ languages in settings."
       zig ("zig" )
 
       ))
-  "Tree sitter language -> Raw block tags map.")
+  "Tree sitter language -> Raw block tags map.
+Associated map: `typst-ts-els-tag-lang-map'.
+Please use function `typst-ts-els--add-treesit-range-rules' and
+`typst-ts-els--lang-name-remap' to modify them.")
 
 (defvar typst-ts-els-tag-lang-map
   #s(hash-table
@@ -440,7 +432,10 @@ languages in settings."
       "inc" yasm "mac" yasm "yaws" yaws
       "zig" zig
       ))
-  "Raw block tag -> tree sitter language map.")
+  "Raw block tag -> tree sitter language map.
+Associated map: `typst-ts-els-lang-tags-map'.
+Please use function `typst-ts-els--add-treesit-range-rules' and
+`typst-ts-els--lang-name-remap' to modify them.")
 
 ;; to test settings:
 ;; emacs --batch -l ./typst-ts-embedding-lang-settings.el --eval 
"(typst-ts-embedding-lang-settings-test)"
@@ -661,11 +656,13 @@ languages in settings."
                 '((comments)
                   (constants keywords text links)
                   (nodes)))))
-  "Settings for raw block languages.")
+  "Predefined settings for raw block languages.
+Format: Language name -> settings.
+Use function `typst-ts-embedding-lang-settings-test' to test your settings.")
 
 
 (defun typst-ts-els--merge-features (a b)
-  "Merge `treesit-font-lock-feature-list's A with B."
+  "Merge `treesit-font-lock-feature-list' A with B."
   (when (not (and a b))
     (error "One of the treesit font lock feature list is nil when merge!"))
   (cl-loop for i to 3  ; [0, 3]
@@ -753,6 +750,10 @@ LANG: language symbol."
     (typst-ts-els--treesit-range-rules lang))))
 
 (defun typst-ts-els--try-get-ts-settings (mode)
+  "Try your luck to get related settings for specific tree sitter mode.
+MODE: tree sitter mode.
+This function basically create a temp buffer, then get the tree sitter settings
+from related local variables."
   (with-temp-buffer
     (setq-local delay-mode-hooks t)  ; don't run hooks associated with MODE
     (funcall mode)
@@ -770,13 +771,19 @@ LANG: language symbol."
 
 (defun typst-ts-els-include-dynamically (_ranges _parser)
   "Include language setting dynamically.
+Basically, this function will first try to merge settings from predefined
+settings `typst-ts-embedding-lang-settings'.  If a language is not in the
+predefined settings, then it will try to guess the corresponding tree sitter
+major mode name from the language, try to load it using
+`typst-ts-els--try-get-ts-settings'.
 Use this function as one notifier of `treesit-parser-notifiers'."
   ;; `treesit-language-at-point-function' will ensure that the
   ;; languages in `treesit-parser-list' are valid (not just a random string)
   (let ((parser-langs
          (delete-dups
           (append
-           ;; parsers created by `treesit-language-at-point-function'
+           ;; parsers created by `treesit-language-at-point-function' (
+           ;; `typst-ts-mode--language-at-point'.)
            ;; i.e. parsers cannot be created by `treesit-range-settings'
            (mapcar #'treesit-parser-language (treesit-parser-list))
            ;; parsers created by `treesit-range-settings'
@@ -789,8 +796,6 @@ Use this function as one notifier of 
`treesit-parser-notifiers'."
             (condition-case _err
                 ;; first try loading settings from configuration
                 (progn
-                  (unless typst-ts-enable-predefined-settings
-                    (error "User don't allow to load predefined settings"))
                   ;; note: the `treesit-range-settings' for languages in
                   ;; predefined settings are already settled at mode start
                   (typst-ts-els-merge-lang-settings lang)
@@ -841,6 +846,21 @@ Use this function as one notifier of 
`treesit-parser-notifiers'."
 ;;; Utilities functions for changing language tag relationship (change two maps
 ;;; synchronizely) 
=============================================================
 
+(defun typst-ts-els--get-lang-input (lang)
+  (if (symbolp lang)
+      (intern (downcase (symbol-name lang)))
+    (if (stringp lang)
+        (intern (downcase lang))
+      (error "LANG should be either symbol or string"))))
+
+(defun typst-ts-els--get-tags-input (tags)
+  (if (stringp tags)
+      (list (downcase tags))
+    (if (and (listp tags)
+             (stringp (nth 0 tags)))
+        (mapcar #'downcase tags)
+      (error "TAGS should be either a string or a list of strings"))))
+
 ;;;###autoload
 (defun typst-ts-els--add-lang-tags-relationship (lang tags)
   "Add or modify language tags relationship.
@@ -848,17 +868,8 @@ This function will make changes to 
`typst-ts-els-lang-tags-map' and
 `typst-ts-els-tag-lang-map'.
 LANG: either a symbol or string.
 TAGS: either a string or a list of strings."
-  (let ((lang (if (symbolp lang)
-                  lang
-                (if (stringp lang)
-                    (intern lang)
-                  (error "LANG should be either symbol or string"))))
-        (tags (if (stringp tags)
-                  (list tags)
-                (if (and (listp tags)
-                         (stringp (nth 0 tags)))
-                    tags
-                  (error "Tags should be either a string or a list of 
strings"))))
+  (let ((lang (typst-ts-els--get-lang-input lang))
+        (tags (typst-ts-els--get-tags-input tags))
         (original-tags (gethash lang typst-ts-els-lang-tags-map))
         temp-lang)
     (dolist (tag tags)
@@ -877,16 +888,8 @@ TAGS: either a string or a list of strings."
 This function will remap lang to newlang for `typst-ts-els-lang-tags-map' and
 `typst-ts-els-tag-lang-map'.
 LANG and NEWLANG: either a symbol or string."
-  (let ((lang (if (symbolp lang)
-                  lang
-                (if (stringp lang)
-                    (intern lang)
-                  (error "LANG should be either symbol or string"))))
-        (newlang (if (symbolp newlang)
-                     newlang
-                   (if (stringp newlang)
-                       (intern newlang)
-                     (error "NEWLANG should be either symbol or string"))))
+  (let ((lang (typst-ts-els--get-lang-input lang))
+        (newlang (typst-ts-els--get-lang-input newlang))
         lang-tags newlang-tags)
     (unless (eq lang newlang)
       (setq lang-tags (gethash lang typst-ts-els-lang-tags-map))
@@ -901,28 +904,29 @@ LANG and NEWLANG: either a symbol or string."
 ;;; Test Utilities 
=============================================================
 
 (defun typst-ts-embedding-lang-settings-test ()
-  "Test typst-ts-embedding-lang-settings."
-  (setq-local treesit-font-lock-feature-list
-              '((comment common)
-                (markup-basic code-basic math-basic)
-                (markup-standard code-standard math-standard)
-                (markup-extended code-extended math-extended)))
-  (let (missing-dylibs err-msgs)
-    (dolist (setting-entry typst-ts-embedding-lang-settings)
-      (let ((language (car setting-entry))
-            (config (cdr setting-entry)))
-        (message "Testing %s ..."  language)
-        (unless (treesit-ready-p language t)
-          (setq missing-dylibs (list (symbol-name language))))
-        (condition-case err
-            (typst-ts-els-merge-settings config)
-          (error
-           (setq err-msgs (list (error-message-string err)))))))
-    (message "---------  Missing Tree Sitter Dynamic libraries -------------")
-    (message " (This also could be an error of entry key name in settings) ")
-    (message "%s" (string-join missing-dylibs " "))
-    (message "---------  Error Messages ------------------------------------")
-    (message "%s" (string-join err-msgs "\n"))))
+  "Test `typst-ts-embedding-lang-settings'."
+  (with-temp-buffer
+    (setq-local treesit-font-lock-feature-list
+                '((comment common)
+                  (markup-basic code-basic math-basic)
+                  (markup-standard code-standard math-standard)
+                  (markup-extended code-extended math-extended)))
+    (let (missing-dylibs err-msgs)
+      (dolist (setting-entry typst-ts-embedding-lang-settings)
+        (let ((language (car setting-entry))
+              (config (cdr setting-entry)))
+          (message "Testing %s ..."  language)
+          (unless (treesit-ready-p language t)
+            (setq missing-dylibs (list (symbol-name language))))
+          (condition-case err
+              (typst-ts-els-merge-settings config)
+            (error
+             (setq err-msgs (list (error-message-string err)))))))
+      (message "---------  Missing Tree Sitter Dynamic libraries 
-------------")
+      (message " (This also could be an error of entry key name in settings) ")
+      (message "%s" (string-join missing-dylibs " "))
+      (message "---------  Error Messages 
------------------------------------")
+      (message "%s" (string-join err-msgs "\n")))))
 
 (provide 'typst-ts-embedding-lang-settings)
 
diff --git a/typst-ts-mode.el b/typst-ts-mode.el
index 8ce89229a2..abc1a19a0d 100644
--- a/typst-ts-mode.el
+++ b/typst-ts-mode.el
@@ -28,21 +28,8 @@
 ;; Tree Sitter Support for Typst
 
 ;; TODO
-;; 1. search all other TODOS
-;; 2. enable highlighting raw block at startup
-;; 3. rememeber git commit --amend instead directly
-;; 4. add more predefined configurations
-
-;; add documentations
 ;; add more treesit settings at startup like `treesit-thing-settings'
 
-;; BUGS find:
-;; 
-;; 1. update raw block language will not delete the old local parser
-;;    -> you need to delete the whole raw block to remove the local parser
-;;    -> this is due to the behavior of `treesit--update-ranges-local'
-;;    -> current-haven't thought good way to handle it
-
 ;;; Code:
 
 (require 'treesit)
@@ -167,12 +154,6 @@ is eliminated."
   :set-after '(typst-ts-markup-header-same-height)
   :group 'typst-ts-faces)
 
-(defcustom typst-ts-mode-raw-block-lang-list
-  '(python rust)  ; TODO
-  "Raw Block Lang List."
-  :type '(list symbol)
-  :group 'typst-ts)
-
 ;; Face 
=========================================================================
 (defface typst-ts-watch-modeline-indicator-face
   '((t :inherit (underline bold)))
@@ -1044,7 +1025,7 @@ See `treesit-language-at-point-function'."
   (when (and typst-ts-mode-enable-raw-blocks-highlight
              typst-ts-mode-highlight-raw-blocks-at-startup)
     ;; since currently local parsers haven't created, we cannot only load
-    ;; those necessary parsers 
+    ;; those necessary parsers
     (cl-loop for setting in typst-ts-embedding-lang-settings
              for lang = (car setting)
              for config = (cdr setting)

Reply via email to