branch: elpa/typst-ts-mode
commit 01ef0d45b9b658de7f620401a155b4c9592897c2
Author: Ziqi Yang <mr.ziqiy...@gmail.com>
Commit: Ziqi Yang <mr.ziqiy...@gmail.com>

    feat: better functionality for typst watch process
---
 typst-ts-mode.el | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 96 insertions(+), 9 deletions(-)

diff --git a/typst-ts-mode.el b/typst-ts-mode.el
index 02de48cf0e..1571d933fb 100644
--- a/typst-ts-mode.el
+++ b/typst-ts-mode.el
@@ -28,6 +28,7 @@
 ;;; Code:
 
 (require 'treesit)
+(require 'compile)
 
 (defgroup typst-ts nil
   "Tree Sitter enabled Typst Writing."
@@ -73,6 +74,7 @@ The compile options will be passed to the
   :type 'string
   :group 'typst-ts)
 
+
 (defcustom typst-ts-mode-watch-process-name "*Typst-Watch*"
   "Process name for `typst watch' sub-command."
   :type 'string
@@ -83,6 +85,20 @@ The compile options will be passed to the
   :type 'string
   :group 'typst-ts)
 
+(defcustom typst-ts-mode-display-watch-process-bufer-automatically 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)
+
+(defcustom typst-ts-mode-display-watch-process-buffer-parameters
+  `(display-buffer-at-bottom
+    (window-height . fit-window-to-buffer))
+  "Display buffer parameters."
+  :type 'symbol
+  :group 'typst-ts)
+
 (defvar typst-ts-mode-before-watch-hook nil
   "Hook runs after compile.")
 
@@ -409,8 +425,6 @@ The compile options will be passed to the
      (attach ["^" "_"] @font-lock-operator-face)
      (align) @font-lock-operator-face)))
 
-
-
 (defconst typst-ts-mode--bracket-node-types
   '("block" "content" "group")
   "Bracket node types.")
@@ -530,7 +544,12 @@ buffer before compilation."
   ;; define them inside a let binding.
   (add-hook 'compilation-finish-functions
             (typst-ts-mode-compile--compilation-finish-function 
(current-buffer)))
-  (compile compile-command))
+  (compile
+   (format "%s compile %s %s"
+           typst-ts-mode-executable-location
+           (file-name-nondirectory buffer-file-name)
+           typst-ts-mode-compile-options)
+   'typst-ts-compilation-mode))
 
 ;;;###autoload
 (defun typst-ts-mode-preview (file)
@@ -551,6 +570,7 @@ buffer before compilation."
       (remove-hook 'compilation-finish-functions
                    
(typst-ts-mode-compile-and-preview--compilation-finish-function cur-buffer)))))
 
+;;;###autoload
 (defun typst-ts-mode-compile-and-preview ()
   "Compile & Preview.
 Assuming the compile output file name is in default style."
@@ -562,17 +582,64 @@ Assuming the compile output file name is in default 
style."
              (current-buffer)))
   (typst-ts-mode-compile))
 
+(defun typst-ts-mode--watch-process-filter (proc output)
+  "Filter the `typst watch' process output.
+Only error will be transported to the process buffer.
+See `(info \"(elisp) Filter Functions\")'.
+PROC: process; OUTPUT: new output from PROC."
+  (when (buffer-live-p (process-buffer proc))
+    (with-current-buffer (process-buffer proc)
+      (erase-buffer)
+      (let ((window (get-buffer-window))
+            (re (rx bol "error:" (+ not-newline) "\n   ┌─ "
+                    (+ not-newline) ":" ;; file
+                    (+ num) ":"         ;; start-line
+                    (+ num) "\n"
+                    (+ (+ (or blank num)) "│" (* not-newline) "\n")))
+            (next-match-start-pos 0)
+            res-output)
+        (while (string-match re output next-match-start-pos)
+          (setq res-output (concat
+                            res-output
+                            (when res-output "\n")
+                            (substring output (match-beginning 0) (match-end 
0)))
+                next-match-start-pos (match-end 0)))
+        ;; Insert the Error text
+        (if (not res-output)
+            (when (and typst-ts-mode-display-watch-process-bufer-automatically 
window)
+              (delete-window window))
+          (insert res-output)
+          (goto-char (point-min))
+          (when typst-ts-mode-display-watch-process-bufer-automatically
+            (typst-ts-mode-display-watch-buffer)))))))
+
+(defun typst-ts-mode-display-watch-buffer ()
+  "Display typst watch process buffer."
+  (interactive)
+  (if (not (buffer-live-p (get-buffer 
typst-ts-mode-watch-process-buffer-name)))
+      (user-error "The typst watch process buffer %s is not alive!" 
typst-ts-mode-watch-process-buffer-name)
+    (display-buffer
+     typst-ts-mode-watch-process-buffer-name
+     typst-ts-mode-display-watch-process-buffer-parameters)))
+
 ;;;###autoload
 (defun typst-ts-mode-watch ()
   "Watch(hot compile) current typst file."
   (interactive)
   (run-hooks typst-ts-mode-before-watch-hook)
-  (start-process-shell-command
-   typst-ts-mode-watch-process-name typst-ts-mode-watch-process-buffer-name
-   (format "%s watch %s %s"
-           typst-ts-mode-executable-location
-           (file-name-nondirectory buffer-file-name)
-           typst-ts-mode-watch-options))
+  (with-current-buffer (get-buffer-create 
typst-ts-mode-watch-process-buffer-name)
+    (erase-buffer)
+    (unless (eq major-mode 'typst-ts-compilation-mode)
+      (typst-ts-compilation-mode)
+      (read-only-mode -1)))
+  (set-process-filter
+   (start-process-shell-command
+    typst-ts-mode-watch-process-name typst-ts-mode-watch-process-buffer-name
+    (format "%s watch %s %s"
+            typst-ts-mode-executable-location
+            (file-name-nondirectory buffer-file-name)
+            typst-ts-mode-watch-options))
+   'typst-ts-mode--watch-process-filter)
   (message "Start Watch :3"))
 
 ;;;###autoload
@@ -580,6 +647,10 @@ Assuming the compile output file name is in default style."
   "Stop watch process."
   (interactive)
   (delete-process typst-ts-mode-watch-process-name)
+  ;; delete associated watch process buffer and window
+  (let ((window (get-buffer-window typst-ts-mode-watch-process-buffer-name)))
+    (kill-buffer typst-ts-mode-watch-process-buffer-name)
+    (delete-window window))
   (run-hooks typst-ts-mode-after-watch-hook)
   (message "Stop Watch :‑."))
 
@@ -591,6 +662,22 @@ Assuming the compile output file name is in default style."
       (typst-ts-mode-watch-stop)
     (typst-ts-mode-watch)))
 
+(defvar typst-ts-compilation-mode-error
+  (cons (rx bol "error:" (+ not-newline) "\n   ┌─ "
+            (group (+ not-newline)) ":" ;; file
+            (group (+ num)) ":"         ;; start-line
+            (group (+ num)) "\n")       ;; start-col
+        '(1 2 3))
+  "Regexp for Error in compilation buffer.")
+
+(define-compilation-mode typst-ts-compilation-mode "Typst Compilation"
+  "Customized major mode for typst watch compilation."
+  (setq-local compilation-error-regexp-alist-alist nil)
+  (add-to-list 'compilation-error-regexp-alist-alist
+               (cons 'typst-error typst-ts-compilation-mode-error))
+  (setq-local compilation-error-regexp-alist nil)
+  (add-to-list 'compilation-error-regexp-alist 'typst-error))
+
 (defvar typst-ts-mode-map
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd "C-c C-c c") #'typst-ts-mode-compile-and-preview)

Reply via email to