branch: elpa/typst-ts-mode commit 929dfdda6a469ca7c5a06aad2e933647fc64bf54 Author: Huan Thieu Nguyen <nguyenthieuh...@gmail.com> Commit: Huan Thieu Nguyen <nguyenthieuh...@gmail.com>
fix: patch applied #41 FIXMEs still need to be solved --- .gitignore | 4 + side/utils.el | 2 + typst-ts-compile.el | 19 ++--- typst-ts-editing.el | 206 ++++++++++++++++++++-------------------------- typst-ts-faces.el | 9 +- typst-ts-misc-commands.el | 4 +- typst-ts-mode.el | 14 ++-- typst-ts-watch-mode.el | 32 ++++--- 8 files changed, 128 insertions(+), 162 deletions(-) diff --git a/.gitignore b/.gitignore index 468ecbf29f..f329d1e806 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,7 @@ makem.sh # Added by cargo /target + +# ELPA-generated files. +/typst-ts-mode-autoloads.el +/typst-ts-mode-pkg.el diff --git a/side/utils.el b/side/utils.el index fa056e3dab..c27d771ccb 100644 --- a/side/utils.el +++ b/side/utils.el @@ -24,6 +24,8 @@ ;;; Code: +(require 'treesit) + (defun typst-ts/util/setup-indent-debug-environment () (interactive) (setq debug-on-error t diff --git a/typst-ts-compile.el b/typst-ts-compile.el index 6c73c68d24..9347ac1326 100644 --- a/typst-ts-compile.el +++ b/typst-ts-compile.el @@ -26,29 +26,25 @@ :group 'typst-ts) (defcustom typst-ts-compile-executable-location "typst" - "The location or name(if in variable `exec-path') for Typst executable." - :type 'string - :group 'typst-ts-compile) + "The location or name (if in variable `exec-path') for Typst executable." + :type 'string) (defcustom typst-ts-compile-options "" "User defined compile options for `typst-ts-compile'. The compile options will be passed to the end of `<typst-executable> compile <current-file>' command." - :type 'string - :group 'typst-ts) + :type 'string) (defcustom typst-ts-compile-before-compilation-hook nil "Hook runs after compile." - :type 'hook - :group 'typst-ts) + :type 'hook) (defcustom typst-ts-compile-after-compilation-hook nil "Hook runs after compile. Note the requirement of this hook is the same as `compilation-finish-functions'. Also note that this hook runs with typst buffer(the buffer you are editing) as the current buffer." - :type 'hook - :group 'typst-ts) + :type 'hook) (defun typst-ts-compile--compilation-finish-function (cur-buffer) "Compilation finish function. @@ -92,7 +88,7 @@ If BUFFER is nil, it means use the current buffer. CHECK: non-nil mean check the file existence. Return nil if the BUFFER has not associated file or the there is no compiled pdf file when CHECK is non-nil." - (when-let ((typst-file (buffer-file-name buffer))) + (when-let* ((typst-file (buffer-file-name buffer))) (let ((res (concat (file-name-base typst-file) ".pdf"))) (if check (when (file-exists-p res) @@ -120,8 +116,7 @@ Assuming the compile output file name is in default style." (defcustom typst-ts-mode-preview-function 'browse-url "Function that opens PDF documents for preview." - :type 'function - :group 'typst-ts) + :type 'function) ;;;###autoload (defun typst-ts-preview (&optional buffer) diff --git a/typst-ts-editing.el b/typst-ts-editing.el index a1badb2e6e..8ccb82dd07 100644 --- a/typst-ts-editing.el +++ b/typst-ts-editing.el @@ -268,72 +268,49 @@ Using ARG argument will ignore the context and it will insert a heading instead. "Handle RET depends on condition. When prefix ARG is non-nil, call global return function." (interactive "P") - (let (execute-result) - (unless current-prefix-arg - (setq - execute-result - (catch 'execute-result - (let* ((cur-pos (point)) - (cur-node (treesit-node-at cur-pos)) - (cur-node-type (treesit-node-type cur-node)) - (parent-node (treesit-node-parent cur-node)) ; could be nil - (parent-node-type (treesit-node-type parent-node)) - node) - ;; (message "%s %s" cur-node parent-node) - (cond - ;; on item node end - ((and (eolp) - (setq node (typst-ts-core-parent-util-type - (typst-ts-core-get-parent-of-node-at-bol-nonwhite) - "item" t t))) - (let* ((item-node node) - (has-children (treesit-node-child item-node 1)) - (next-line-pos - (save-excursion - (forward-line 1) - (point))) - (next-line-node - (typst-ts-core-get-parent-of-node-at-bol-nonwhite - next-line-pos)) - (next-line-top-node ; get container type or `item' type node + (or + ;; FIXME: This kind of magic/electric behavior should probably be + ;; controllable via a custom var (and described in the docstring). + (when (and (null arg) (eolp)) + (let* (;; (cur-pos (point)) + ;; (cur-node (treesit-node-at cur-pos)) + ;; (cur-node-type (treesit-node-type cur-node)) + ;; (parent-node (treesit-node-parent cur-node)) ; could be nil + ;; (parent-node-type (treesit-node-type parent-node)) + (node (typst-ts-core-parent-util-type + (typst-ts-core-get-parent-of-node-at-bol-nonwhite) + "item" t t))) + ;; (message "%s %s" cur-node parent-node) + (cond + ;; on item node end + (node + (let* ((has-children (treesit-node-child node 1)) + (next-line-pos (line-beginning-position 2)) + (next-line-node + (typst-ts-core-get-parent-of-node-at-bol-nonwhite + next-line-pos)) + (next-line-top-node ; get container type or `item' type node + (typst-ts-core-parent-util-type + next-line-node + (regexp-opt '("code" "item")) + t))) + (if has-children + ;; example: + ;; - #[| <- return + ;; ] + (if (and next-line-top-node + ;; end of buffer situation (or next line is the end + ;; line (and no newline character)) + (not (equal + (line-number-at-pos next-line-pos) + (line-number-at-pos (point-max))))) + (call-interactively #'newline) + (typst-ts-mode-insert--item node)) + ;; no text means delete the item on current line: (item -) + (delete-region (line-beginning-position) (line-end-position)) + ;; whether the previous line is in an item + (let* ((prev-line-item-node (typst-ts-core-parent-util-type - next-line-node - (regexp-opt '("code" "item")) - t))) - (if has-children - ;; example: - ;; - #[| <- return - ;; ] - (if (and next-line-top-node - ;; end of buffer situation (or next line is the end - ;; line (and no newline character)) - (not (equal - (line-number-at-pos next-line-pos) - (line-number-at-pos (point-max))))) - (call-interactively #'newline) - (typst-ts-mode-insert--item item-node)) - ;; no text means delete the item on current line: (item -) - (delete-region (line-beginning-position) (line-end-position)) - ;; whether the previous line is in an item - (let* ((prev-line-item-node - (typst-ts-core-parent-util-type - (typst-ts-core-get-parent-of-node-at-bol-nonwhite - (save-excursion - (forward-line -1) - (point))) - "item" t t))) - (if prev-line-item-node - (progn - (delete-line) - (forward-line -1) - (end-of-line) - (call-interactively #'newline)) - (indent-according-to-mode))))) - (throw 'execute-result 'success)) - ))))) - ;; execute default action if not successful - (unless (eq execute-result 'success) - ;; we only need to look for global keybinding, see `(elisp) Active Keymaps' (let ((global-ret-function (global-key-binding (kbd "RET")))) (if (not current-prefix-arg) (call-interactively global-ret-function) @@ -407,52 +384,46 @@ When there is no section it will insert a heading below point." (defun typst-ts-mode-cycle (&optional _arg) "Cycle." (interactive "P") - (let (execute-result node) - (setq - execute-result - ;; plz manually throw `\'success' to `execute-result' - (catch 'execute-result - (when-let* ((cur-pos (point)) - (cur-node (treesit-node-at cur-pos)) - (cur-node-type (treesit-node-type cur-node)) - (cur-line-nonwhite-bol-node - (typst-ts-core-get-node-at-bol-nonwhite)) - (cur-line-nonwhite-bol-node-type - (treesit-node-type cur-line-nonwhite-bol-node)) - (parent-node (treesit-node-parent cur-node)) ; could be nil - (parent-node-type (treesit-node-type parent-node))) - (cond - ((equal parent-node-type "raw_blck") - (insert-tab) - (throw 'execute-result 'success)) - - - ((setq node - (typst-ts-core-parent-util-type - cur-line-nonwhite-bol-node "item" t t)) - (let* ((cur-item-node node) - (prev-significant-node - (typst-ts-core-prev-sibling-ignore-types - cur-item-node - "parbreak")) - (prev-significant-node-type - (treesit-node-type prev-significant-node)) - prev-item-node) - - (if (equal prev-significant-node-type "item") - (setq prev-item-node prev-significant-node) - (if (equal - "item" - (treesit-node-type - (treesit-node-parent prev-significant-node))) - (setq prev-item-node (treesit-node-parent - prev-significant-node)))) - - ;; (message "%s, %s" cur-item-node prev-item-node) - - (unless prev-item-node - (throw 'execute-result 'default)) - + (let (node) + (or + (when-let* ((cur-pos (point)) + (cur-node (treesit-node-at cur-pos)) + (cur-node-type (treesit-node-type cur-node)) + (cur-line-nonwhite-bol-node + (typst-ts-core-get-node-at-bol-nonwhite)) + (_ (treesit-node-type cur-line-nonwhite-bol-node)) + (parent-node (treesit-node-parent cur-node)) ; could be nil + (parent-node-type (treesit-node-type parent-node))) + (cond + ((equal parent-node-type "raw_blck") + (insert-tab) + 'success) + + + ((setq node + (typst-ts-core-parent-util-type + cur-line-nonwhite-bol-node "item" t t)) + (let* ((cur-item-node node) + (prev-significant-node + (typst-ts-core-prev-sibling-ignore-types + cur-item-node + "parbreak")) + (prev-significant-node-type + (treesit-node-type prev-significant-node)) + prev-item-node) + + (if (equal prev-significant-node-type "item") + (setq prev-item-node prev-significant-node) + (if (equal + "item" + (treesit-node-type + (treesit-node-parent prev-significant-node))) + (setq prev-item-node (treesit-node-parent + prev-significant-node)))) + + ;; (message "%s, %s" cur-item-node prev-item-node) + + (when prev-item-node (let* ((cur-item-node-start-column (typst-ts-core-column-at-pos (treesit-node-start cur-item-node))) @@ -470,20 +441,17 @@ When there is no section it will insert a heading below point." cur-item-node (- typst-ts-mode-indent-offset (abs offset))))) - (throw 'execute-result 'success))) + 'success))))) + ;; execute default action if not successful + (call-interactively (global-key-binding (kbd "TAB")))))) - (t nil))))) - ;; execute default action if not successful - (unless (eq execute-result 'success) - (call-interactively (global-key-binding (kbd "TAB")))))) - -(defun typst-ts-mode-auto-fill-function () +(defun typst-ts-mode-auto-fill-function () ;FIXME: Unused? "Function for `auto-fill-mode'. Inserts newline and indents according to context." (when (>= (current-column) (current-fill-column)) (insert "\n") - (typst-ts-mode-indent-line-function))) + (indent-according-to-mode))) (provide 'typst-ts-editing) diff --git a/typst-ts-faces.el b/typst-ts-faces.el index ca956ee1d1..8fe82a002e 100644 --- a/typst-ts-faces.el +++ b/typst-ts-faces.el @@ -26,18 +26,17 @@ :prefix "typst-ts-faces" :group 'typst-ts) + (defcustom typst-ts-markup-header-same-height t "Whether to make header face in markup context share the same height." - :type 'boolean - :group 'typst-ts-faces) + :type 'boolean) (defcustom typst-ts-markup-header-scale '(2.0 1.7 1.4 1.1 1.0 1.0) "Header Scale." - :type '(list number number number number number number) - :group 'typst-ts-faces) + :type '(list number number number number number number)) -;; Face ========================================================================= +;; Face ========================================================================= (defface typst-ts-watch-modeline-indicator-face '((t :inherit (underline bold))) "Face for typst watch modeline indicator.") diff --git a/typst-ts-misc-commands.el b/typst-ts-misc-commands.el index 62ebd81c1c..9b1d64478a 100644 --- a/typst-ts-misc-commands.el +++ b/typst-ts-misc-commands.el @@ -50,8 +50,10 @@ (file-name (file-relative-name buffer-file-name base-path)) (output-file-name (file-name-with-extension file-name "md"))) + ;; FIXME: Use `start-process' so we don't need to `shell-quote-argument'? (async-shell-command - (concat "pandoc -o " output-file-name " " file-name)))) + (concat "pandoc -o " (shell-quote-argument output-file-name) + " " (shell-quote-argument file-name))))) (defun typst-ts-mc-search-typst-symbol () (interactive) diff --git a/typst-ts-mode.el b/typst-ts-mode.el index d22ca4dadf..17d7b42701 100644 --- a/typst-ts-mode.el +++ b/typst-ts-mode.el @@ -57,8 +57,7 @@ This is used for grammar minimum version check. The modified time of the grammar file is used for comparing. This variable is used in `typst-ts-mode-check-grammar-version'." :type '(choice (string :tag "typst tree sitter grammar file location") - (const :tag "Don't enable grammar version check" nil)) - :group 'typst-ts) + (const :tag "Don't enable grammar version check" nil))) ;; `git log -n1 --date=raw` or `git log -n1 --format="%at"` (defvar typst-ts-mode--grammar-minimum-version-timestamp 1713791627 @@ -67,10 +66,9 @@ This variable is used in `typst-ts-mode-check-grammar-version'." (defcustom typst-ts-mode-enable-raw-blocks-highlight nil "Whether to enable raw block highlighting. NOTE this option must be set before the first loading(opening typst file)" - :type 'boolean - :group 'typst-ts) + :type 'boolean) -;; ============================================================================== +;; ============================================================================== ;; TODO typst has three modes (namely 'markup', 'code' and 'math') ;; Currently only add common settings to syntax table (defvar typst-ts-mode-syntax-table @@ -534,9 +532,11 @@ typst tree sitter grammar (at least %s)!" (current-time-string min-time)) ;; patch `electric-pair-post-self-insert-function' function (when electric-pair-mode ;; add-function :override buffer-locally doesn't work, so we do this... - (remove-hook 'post-self-insert-hook 'electric-pair-post-self-insert-function t) + ;; FIXME: Try and find a better way (maybe by changing electric-pair). + (remove-hook 'post-self-insert-hook + 'electric-pair-post-self-insert-function t) (add-hook 'post-self-insert-hook - 'typst-ts-mode-electric-pair-open-newline-between-pairs-psif + #'typst-ts-mode-electric-pair-open-newline-between-pairs-psif t)) ;; Set Compile Command diff --git a/typst-ts-watch-mode.el b/typst-ts-watch-mode.el index ee1c5b1d02..f7d93309d4 100644 --- a/typst-ts-watch-mode.el +++ b/typst-ts-watch-mode.el @@ -40,39 +40,33 @@ "User defined compile options for `typst-ts-watch'. The compile options will be passed to the `<typst-executable> watch <current-file>' sub-command." - :type 'string - :group 'typst-ts-watch) + :type 'string) (defcustom typst-ts-watch-process-name "*Typst-Watch*" "Process name for `typst watch' sub-command." - :type 'string - :group 'typst-ts-watch) + :type 'string) (defcustom typst-ts-watch-process-buffer-name "*Typst-Watch*" "Process buffer name for `typst watch' sub-command." - :type 'string - :group 'typst-ts-watch) + :type 'string) (defcustom typst-ts-watch-auto-display-compilation-error t "Whether the typst watch process buffer should be displayed automatically. This means the buffer will be displayed when error occurs, hide when error is eliminated." - :type 'boolean - :group 'typst-ts-watch) + :type 'boolean) (defcustom typst-ts-watch-display-buffer-parameters '(display-buffer-at-bottom (window-height . fit-window-to-buffer)) "Display buffer parameters. -Note that since the major mode of typst watch buffer is derived from compilation +Note that since the major mode of typst watch buffer is derived from compilation mode. If you have a rule like `((derived-mode . compilation-mode) ...)' in your `display-buffer-alist', then this option will be covered by that rule." - :type 'symbol - :group 'typst-ts-watch) + :type 'symbol) (defvar typst-ts-before-watch-hook nil "Hook runs before compile.") - (defvar typst-ts-after-watch-hook nil "Hook runs after compile.") @@ -124,18 +118,20 @@ PROC: process; OUTPUT: new output from PROC." (run-hooks typst-ts-before-watch-hook) (with-current-buffer (get-buffer-create typst-ts-watch-process-buffer-name) (erase-buffer) - (unless (eq major-mode 'typst-ts-compilation-mode) + (unless (derived-mode-p 'typst-ts-compilation-mode) (typst-ts-compilation-mode) (read-only-mode -1))) (set-process-filter + ;; FIXME: Do we really need a shell, with the associated need to + ;; `shell-quote-argument'? (start-process-shell-command typst-ts-watch-process-name typst-ts-watch-process-buffer-name (format "%s watch %s %s" - typst-ts-compile-executable-location - (file-name-nondirectory buffer-file-name) + (shell-quote-argument typst-ts-compile-executable-location) + (shell-quote-argument (file-name-nondirectory buffer-file-name)) typst-ts-watch-options)) - 'typst-ts--watch-process-filter) - (message "Start Watch :3")) + #'typst-ts--watch-process-filter) + (message "Start Watch")) ;; FIXME: ":3"? ;;;###autoload (defun typst-ts-watch-stop () @@ -148,7 +144,7 @@ PROC: process; OUTPUT: new output from PROC." (when window (delete-window window))) (run-hooks typst-ts-after-watch-hook) - (message "Stop Watch :‑.")) + (message "Stop Watch")) (provide 'typst-ts-watch-mode) ;;; typst-ts-watch-mode.el ends here