branch: elpa/typst-ts-mode commit 208aa360d89a7016554913877fbc18e326dc5878 Author: Meow King <mr.meowk...@anche.no> Commit: Meow King <mr.meowk...@anche.no>
feat: almost done, have some bugs can dynamic loading embedding languages and embedding python works fine, but rust and some other languages like `json` will cause the whole file rendering weird. Use `(typst-ts-els-merge-lang 'rust)` to test. --- typst-ts-embedding-lang-settings.el | 173 +++++++++++------------------------- typst-ts-mode.el | 30 ++++--- 2 files changed, 70 insertions(+), 133 deletions(-) diff --git a/typst-ts-embedding-lang-settings.el b/typst-ts-embedding-lang-settings.el index cde20a4e81..3c6cbf4288 100644 --- a/typst-ts-embedding-lang-settings.el +++ b/typst-ts-embedding-lang-settings.el @@ -24,6 +24,13 @@ ;;; Code: (require 'treesit) +(defcustom typst-ts-highlight-raw-block-langs-not-in-settings nil + "Whether to highlight raw block of language that is not in settings. +The cost for setting up these languages is usually higher than those +languages in settings." + :type 'boolean + :group 'typst-ts) + (defvar typst-ts-embedding-lang-settings '((python . (:feature python @@ -80,84 +87,19 @@ (let ((settings (alist-get lang typst-ts-embedding-lang-settings))) (if settings (typst-ts-els-merge-settings settings) - (signal 'lang-no-in-settings '(lang))))) - -(defun typst-ts-els--try-get-variable--try-name (prefixes postfixes) - (let (variable) - (catch 'exit - (cl-loop for prefix in prefixes - for postfix in postfixes - do - (ignore-errors - (setq variable (intern (concat prefix postfix))) - (throw 'exit (eval variable))))))) - -(defun typst-ts-els--try-get-fls--try-name (_lang prefixes) - (typst-ts-els--try-get-variable--try-name - prefixes - '("--font-lock-settings" "-font-lock-settings"))) - -(defun typst-ts-els--try-get-ir--try-name (_lang prefixes) - (typst-ts-els--try-get-variable--try-name - prefixes - '("--indent-rules" "-indent-rules"))) - -(defvar typst-ts-els--try-get-feature-name-list - '("-ts-mode" "-mode" "") - "Used by `typset-ts-els--try-require-feature'.") - -(defvar typst-ts-els--try-variable-prefix-list - '("-ts-mode" "-ts" "") - "Used by `typset-ts-els--try-require-feature'.") - -(defvar typst-ts-els--try-get-fls--func-list - '(typst-ts-els--try-get-fls--try-name) - "TODO documentation.") - -(defvar typst-ts-els--try-get-ir--func-list - '(typst-ts-els--try-get-ir--try-name) - "TODO documentation.") - -(defun typst-ts-els--try-require-feature (lang) - "Try to require feature for LANG. -If success, then return the feature symbol, else nil." - (let (feature) - (catch 'exit - (dolist (elem typst-ts-els--try-get-feature-name-list) - (setq feature - (intern (concat (symbol-name lang) elem))) - (ignore-errors - (require feature) - (throw 'exit feature)))))) - -(defun typst-ts-els--try-get-variable-value (lang prefixes func-list) - "Try to get value of a variable specified for LANG. -The variable is like font lock settings or indentation rules. It is specified -by FUNC-LIST. -Return nil if cannot get. -PREFIXES: a list of variable name prefix. -FUNC-LIST: functions to be called to get the variable value." - (let (value) - (catch 'exit - (dolist (func func-list) - (ignore-errors - (setq value (funcall func lang prefixes)) - (when value - (throw 'exit value))))))) - -(defun typst-ts-els--try-get-font-lock-settings (lang prefixes) - (typst-ts-els--try-get-variable-value - lang prefixes typst-ts-els--try-get-fls--func-list)) - -(defun typst-ts-els--try-get-indentation-rules (lang prefixes) - (typst-ts-els--try-get-variable-value - lang prefixes typst-ts-els--try-get-ir--func-list)) - -;; NOTE this operation is high cost -(defun typst-ts-els--try-get-ts-feature-list (mode) + (error "Language %s not in settings" lang)))) + +(defun typst-ts-els--try-get-ts-settings (mode) (with-temp-buffer + (setq-local delay-mode-hooks t) ; don't run hooks associated with MODE (funcall mode) - treesit-font-lock-feature-list)) + (list + :treesit-font-lock-settings + treesit-font-lock-settings + :treesit-simple-indent-rules + treesit-simple-indent-rules + :treesit-font-lock-feature-list + treesit-font-lock-feature-list))) (defvar-local typst-ts-els--include-languages '(typst) @@ -166,55 +108,45 @@ FUNC-LIST: functions to be called to get the variable value." (defun typst-ts-els-include-dynamically (_ranges _parser) "Include language setting dynamically. Use this function as one notifier of `treesit-parser-notifiers'." - (let ((parsers (treesit-parser-list)) - lang - feature prefixes font-lock-settings indentation-rules ts-feature-list) - (unless (eq (length parsers) (length typst-ts-els--include-languages)) - (dolist (parser parsers) - (setq lang (treesit-parser-language parser)) + (let ((parser-langs (mapcar #'treesit-parser-language (treesit-parser-list))) + lang-ts-mode settings) + (unless (eq (length parser-langs) (length typst-ts-els--include-languages)) + (dolist (lang parser-langs) (unless (member lang typst-ts-els--include-languages) (unwind-protect (condition-case _err ;; first try loading settings from configuration - (typst-ts-els-merge-lang lang) + (progn + (typst-ts-els-merge-lang lang) + (message "Load %s language settings from configuration." lang)) (error - ;; if not found or encountering error during loading, - ;; then guess variables to load - (catch 'exit - (ignore-errors - ;; require feature - (setq feature (typst-ts-els--try-require-feature lang)) - (unless feature - (throw 'exit "no feature found")) - - (setq prefixes - (cl-loop for postfix in typst-ts-els--try-variable-prefix-list - collect (concat (symbol-name lang) postfix))) - - ;; merge font lock settings - (setq font-lock-settings - (typst-ts-els--try-get-font-lock-settings lang prefixes)) - (setq treesit-font-lock-settings - (append treesit-font-lock-settings - font-lock-settings)) - - ;; merge indent rules - (setq indentation-rules - (typst-ts-els--try-get-indentation-rules lang prefixes)) - (setq treesit-simple-indent-rules - (append treesit-simple-indent-rules - indentation-rules)) - - ;; merge ts feature lists - (setq ts-feature-list - (typst-ts-els--try-get-ts-feature-list - (intern (concat (symbol-name lang) postfix)))) - (setq treesit-font-lock-feature-list - (typst-ts-els--merge-features - treesit-font-lock-feature-list - ts-feature-list)) - )))) - (add-to-list typst-ts-els--include-languages lang)) + ;; if language not in setting or encounter error during loading, + ;; then try your luck to load it + (condition-case err + (progn + (setq lang-ts-mode + (intern (concat (symbol-name lang) "-ts-mode"))) + (setq settings + (typst-ts-els--try-get-ts-settings lang-ts-mode)) + + (setq treesit-font-lock-settings + (append treesit-font-lock-settings + (plist-get settings :treesit-font-lock-settings))) + + (setq treesit-simple-indent-rules + (append treesit-simple-indent-rules + (plist-get settings :treesit-simple-indent-rules))) + + (setq treesit-font-lock-feature-list + (typst-ts-els--merge-features + treesit-font-lock-feature-list + (plist-get settings :treesit-font-lock-feature-list))) + (message "Getting %s language settings luckily succeeded." lang)) + (error + (message "Highlighting raw block error: \n%s" + (error-message-string err)))))) + ;; whatever, we won't load that language again + (add-to-list 'typst-ts-els--include-languages lang)) ))))) (defun typst-ts-embedding-lang-settings-test () @@ -224,7 +156,6 @@ Use this function as one notifier of `treesit-parser-notifiers'." (typst-ts-els-merge-settings (cdr setting-entry))) (message "No problem found!")) - (provide 'typst-ts-embedding-lang-settings) ;;; typst-ts-embedding-lang-settings.el ends here diff --git a/typst-ts-mode.el b/typst-ts-mode.el index baa09cdd5b..88a8852094 100644 --- a/typst-ts-mode.el +++ b/typst-ts-mode.el @@ -141,7 +141,7 @@ is eliminated." :group 'typst-ts-faces) (defcustom typst-ts-mode-raw-block-lang-list - '(python) ; TODO + '(python rust) ; TODO "Raw Block Lang List." :type '(list symbol) :group 'typst-ts) @@ -999,11 +999,13 @@ See `treesit-language-at-point-function'." (unless (treesit-ready-p 'typst) (error "Tree-sitter for Typst isn't available")) - (let ((parser (treesit-parser-create 'typst))) - (when typst-ts-mode-highlight-raw-block - (treesit-parser-add-notifier - parser - 'typst-ts-els-include-dynamically))) + (treesit-parser-create 'typst) + + ;; (let ((parser (treesit-parser-create 'typst))) + ;; (when typst-ts-mode-highlight-raw-block + ;; (treesit-parser-add-notifier + ;; parser + ;; 'typst-ts-els-include-dynamically))) ;; Comments. (typst-ts-mode-comment-setup) @@ -1039,14 +1041,18 @@ See `treesit-language-at-point-function'." (file-name-nondirectory buffer-file-name) typst-ts-mode-compile-options)) - ;; use parser notifier to add font lock dynamically - ;; TODO merge indentation rule - ;; TODO merge font lock feature list - (setq-local treesit-language-at-point-function 'typst-ts-mode--language-at-point) - (setq-local treesit-range-settings - (typst-ts-mode--treesit-range-rules typst-ts-mode-raw-block-lang-list)) + ;; (setq-local treesit-range-settings + ;; (typst-ts-mode--treesit-range-rules '(python rust))) + ;; (setq-local treesit-range-settings + ;; (treesit-range-rules + ;; :host 'typst + ;; :embed 'rust + ;; ;; :local t + ;; '((raw_blck + ;; ;; lang: (_) + ;; (blob) @capture)))) ;; Outline (setq-local outline-regexp typst-ts-mode-outline-regexp)