Tangle Typst. 导出Typst文件中的代码块

这两天变成了重度Typst用户,因为在搞点文学编程,就做了一个导出代码块的函数:

(defvar typst--initialized-files nil
  "List of files that have been initialized for the current tangle operation.")

(defun typst--initialize-file (path)
  "Initialize a temporary file for the PATH and return the temp file's path."
  (let ((temp-path (make-temp-file "typst" nil ".tmp")))
    (push (cons temp-path path) typst--initialized-files)
    temp-path))

(defun typst--tangle (node)
  "Recursively process each raw_blck NODE in the treesit parsed tree."
  (if (equal (treesit-node-type node) "raw_blck")
      (let* ((beg (treesit-node-start node))
             (path-line (treesit-node-text (treesit-node-on (- beg 2) (- beg 1))))
             (original-path (when (> (length path-line) 2) (string-trim (substring path-line 2))))
             (temp-path (when original-path
                          (or (car (rassoc original-path typst--initialized-files))
                              (typst--initialize-file original-path))))
             (content-node (car (treesit-filter-child node (lambda (n) (equal (treesit-node-type n) "blob")))))
             (content (when content-node (string-trim (treesit-node-text content-node)))))
        (when temp-path
          (append-to-file content nil temp-path)
          (append-to-file "\n" nil temp-path)
          (message "Tangled to temp file: %s." temp-path)))
    (dolist (child (treesit-node-children node))
      (typst--tangle child))))


(defun typst-tangle ()
  "Tangle the current typst file."
  (interactive)
  (setq typst--initialized-files nil)
  (let ((root (treesit-buffer-root-node)))
    (typst--tangle root)
    (dolist (pair typst--initialized-files)
      (let ((temp-path (car pair))
            (original-path (cdr pair)))
        (rename-file temp-path original-path t)
        (message "Moved %s to %s" temp-path original-path)))
    (setq typst--initialized-files nil)))

使用方法:

  1. 需要treesit和typst-ts-mode

  2. 比如typst文件内容是 (忽略那个反斜杆…)

...

// xx.py
\```python
print(1)
print(2)
\```

...

运行 M-x typst-tangle,会将python的code block里面的两个print先导出到tmp文件,再移动到xx.py里面

注意

因为刚写好自用。暂时不确定会不会有什么特别的问题。

5 个赞