branch: elpa/typst-ts-mode
commit 7f6bf64232f1b120c4a4696a02be2f0a506b04b6
Merge: 972dc69d6b c3c78a9a2c
Author: Meow King <mr.meowk...@posteo.com>
Commit: Meow King <mr.meowk...@posteo.com>

    Merge pull request 'release: 0.12.1' (#75) from develop into main
    
    Reviewed-on: https://codeberg.org/meow_king/typst-ts-mode/pulls/75
---
 typst-ts-editing.el       | 113 ++++++++++++++++++++++++++++++++++++++++++++--
 typst-ts-misc-commands.el |  48 ++++++++++++++++++++
 typst-ts-mode.el          |  91 ++++++++++++++++++++++++++++++-------
 3 files changed, 232 insertions(+), 20 deletions(-)

diff --git a/typst-ts-editing.el b/typst-ts-editing.el
index 08c3d0f5a0..92efafb700 100644
--- a/typst-ts-editing.el
+++ b/typst-ts-editing.el
@@ -84,7 +84,7 @@ DIRECTION is one of following symbols:
     (setq rows (seq-partition grid-cells amount-of-columns))
     (setq current (seq-elt rows row-index))
     (setq to-switch
-          (pcase direction
+          (pcase-exhaustive direction
             ('up
              (progn
                (when (= row-index 0)
@@ -94,9 +94,7 @@ DIRECTION is one of following symbols:
              (progn
                (when (length= rows (1+ row-index))
                  (user-error "Already on last row"))
-               (seq-elt rows (1+ row-index))))
-            (_
-             (error "DIRECTION: %s is not one of: `up', `down'" direction))))
+               (seq-elt rows (1+ row-index))))))
     (let ((start1 (treesit-node-start (car current)))
           (end1 (treesit-node-end (car (last current))))
           (start2 (treesit-node-start (car to-switch)))
@@ -171,6 +169,113 @@ Up/down means moving the cell to another row while 
keeping the column index."
     (transpose-regions (treesit-node-start cell) (treesit-node-end cell)
                        (treesit-node-start to-switch) (treesit-node-end 
to-switch))))
 
+(defun typst-ts-editing-item-list-change-type (type)
+  "Change the list type of the item list at point to TYPE.
+TYPE is a symbol one of: (numbered, ordered, bullet)
+
+1. one
+2. two
+
++ one
++ two
+
+- one
+- two"
+  (interactive
+   (list (intern (completing-read "Choose list type: "
+                                  '("numbered" "ordered" "bullet")
+                                  nil t))))
+  (let ((item (typst-ts-editing-item--at-point-p))
+        (previous-item nil)
+        (current-type-p nil)
+        (marker nil)
+        (marker-start nil)
+        (new-marker (pcase-exhaustive type
+                      ('numbered 1)
+                      ('ordered "+")
+                      ('bullet "-")))
+        (insert-fn nil))
+    (unless item
+      (user-error "Not on a item list"))
+    (setq current-type-p (treesit-node-text (treesit-node-child item 0)))
+    (cond
+     ((string= "-" current-type-p)
+      (setq current-type-p
+            (lambda (x)
+              (string= "-" (treesit-node-text
+                            (treesit-node-child x 0))))))
+     ((string= "+" current-type-p)
+      (setq current-type-p
+            (lambda (x)
+              (string= "+" (treesit-node-text
+                            (treesit-node-child x 0))))))
+     (t
+      (setq current-type-p
+            (lambda (x)
+              (not (= 0 (string-to-number
+                         (treesit-node-text
+                          (treesit-node-child x 0)))))))))
+    (pcase-exhaustive type
+      ('numbered
+       (setq insert-fn
+             (lambda ()
+               (insert (format "%d." new-marker))
+               (setq new-marker (1+ new-marker)))))
+      ('ordered
+       (setq insert-fn
+             (lambda ()
+               (insert "+"))))
+      ('bullet
+       (setq insert-fn
+             (lambda ()
+               (insert "-")))))
+    ;; traverse the list up
+    (setq previous-item (treesit-node-prev-sibling item))
+    (while (and item
+                (string= (treesit-node-type previous-item) "item")
+                (funcall current-type-p previous-item))
+      (setq item previous-item)
+      (setq previous-item (treesit-node-prev-sibling item)))
+    (atomic-change-group
+      (save-excursion
+        (while (and item
+                    (string= (treesit-node-type item) "item")
+                    (funcall current-type-p item))
+          (setq marker (treesit-node-child item 0))
+          (setq marker-start (treesit-node-start marker))
+          (goto-char marker-start)
+          (delete-region marker-start (treesit-node-end marker))
+          (funcall insert-fn)
+          ;; item is now invalid, need to revalidate it
+          (setq item (treesit-node-next-sibling
+                      (treesit-node-parent
+                       (treesit-node-at marker-start)))))))))
+
+(defun typst-ts-editing-item-list-renumber ()
+  "Cleanup the numbered list at point.
+
+   1. one
+   2. two
+   3. three
+
+   Now remove 2.
+
+   1. one
+   3. three
+
+   Run command
+
+   1. one
+   2. three"
+  (interactive)
+  (let ((current-item (typst-ts-editing-item--at-point-p)))
+    (when (or (not current-item)
+              (= (string-to-number
+                  (treesit-node-text (treesit-node-child current-item 0)))
+                 0))
+      (user-error "Not on a numbered list"))
+    (typst-ts-editing-item-list-change-type 'numbered)))
+
 (defun typst-ts-editing-grid-cell-down ()
   "See `typst-ts-editing-grid-cell--move'."
   (interactive)
diff --git a/typst-ts-misc-commands.el b/typst-ts-misc-commands.el
index 526fc5e2a3..bffe9901d9 100644
--- a/typst-ts-misc-commands.el
+++ b/typst-ts-misc-commands.el
@@ -24,6 +24,23 @@
 
 (require 'treesit)
 
+(defun typst-ts-mc-open-thing-function (thing type)
+  "Open THING which is of TYPE.
+TYPE is one of the following symbols: (local url)
+
+If it is url it will open it outside Emacs.
+When it is local it will open it inside Emacs (THING will be a relative link)."
+  (pcase-exhaustive type
+    ('url
+     (browse-url thing))
+    ('local
+     (find-file thing))))
+
+(defcustom typst-ts-mc-open-function #'typst-ts-mc-open-thing-function
+  "The function that is called by `typst-ts-mc-open-at-point'."
+  :type 'function
+  :group 'typst)
+
 (defun typst-ts-mc-install-grammar ()
   "Install Typst grammar."
   (interactive)
@@ -72,6 +89,37 @@ Require pandoc to be installed."
   (interactive)
   (browse-url "https://typst.app/universe";))
 
+(defun typst-ts-mc-open-at-point ()
+  "Follow thing at point.
+
+By default it will call `typst-ts-mc-open-thing-function'.
+Default behavior can be changed in `typst-ts-mc-open-function'."
+  (interactive)
+  (let ((node (treesit-node-at (point)))
+        type thing)
+    (if (string= (treesit-node-type node) "url")
+        (funcall typst-ts-mc-open-function
+                 (treesit-node-text node)
+                 'url)
+      (setq node (treesit-node-parent node))
+      (setq type (treesit-node-type node))
+      ;; remove the quotes in "text"
+      (setq thing (substring (treesit-node-text node) 1 -1))
+      (if (and (string= type "string")
+               (file-exists-p thing))
+          (funcall typst-ts-mc-open-function
+                   thing
+                   'local)
+        (user-error "Not on an openable thing")))))
+
+(defun typst-ts-mc-insert-link ()
+  "Insert a local relative file link."
+  (interactive)
+  (let ((link (read-file-name "File: ")))
+    (when (or (not link) (= (length link) 0))
+      (user-error "No input"))
+    (insert (file-relative-name link))))
+
 (provide 'typst-ts-misc-commands)
 
 ;;; typst-ts-misc-commands.el ends here
diff --git a/typst-ts-mode.el b/typst-ts-mode.el
index 1d8267f80a..a5a0f24311 100644
--- a/typst-ts-mode.el
+++ b/typst-ts-mode.el
@@ -1,7 +1,7 @@
 ;;; typst-ts-mode.el --- Tree Sitter support for Typst  -*- lexical-binding: 
t; -*-
 ;; Copyright (C) 2023-2025 The typst-ts-mode Project Contributors
 
-;; Version: 0.12.0
+;; Version: 0.12.1
 ;; Author: Ziqi Yang <mr.meowk...@anche.no>
 ;; Maintainer: Ziqi Yang <mr.meowk...@anche.no>
 ;;   Huan Nguyen <nguyenthieuh...@gmail.com>
@@ -33,6 +33,7 @@
 (require 'treesit)
 (require 'outline)
 (require 'elec-pair)
+(require 'easymenu)
 
 (require 'typst-ts-embedding-lang-settings)
 (require 'typst-ts-core)
@@ -192,7 +193,7 @@
    :feature 'math-standard  ; part 1
    '((symbol) @font-lock-constant-face
      (letter) @font-lock-constant-face)
-   
+
    :language 'typst
    :feature 'math-standard  ; part 2
    :override 'append
@@ -478,21 +479,7 @@ This function is meant to be used when user hits a return 
key."
     (if (re-search-backward typst-ts-outline-regexp nil t)
         (- (match-end 1) (match-beginning 1))
       0)))
-
-
-;;;###autoload
 (defvar-keymap typst-ts-mode-map
-  "C-c C-c" #'typst-ts-compile  ; use prefix argument to do preview
-  "C-c C-S-C" #'typst-ts-compile-and-preview
-  "C-c C-w" #'typst-ts-watch-mode
-  "C-c C-p" #'typst-ts-preview
-
-  "M-<left>" #'typst-ts-editing-meta-left
-  "M-<right>" #'typst-ts-editing-meta-right
-  "M-<down>" #'typst-ts-editing-meta-down
-  "M-<up>" #'typst-ts-editing-meta-up
-  "M-<return>" #'typst-ts-editing-meta-return
-
   ;; don't bind <return>
   ;; Binding a command to "<return>" is generally a bug.
   ;; Emacs will first look for a binding for `return` and if it finds one
@@ -502,6 +489,78 @@ This function is meant to be used when user hits a return 
key."
   "RET" #'typst-ts-editing-return
   "C-c '" #'typst-ts-edit-indirect)
 
+(easy-menu-define typst-ts-mode-menu typst-ts-mode-map
+  "Menu for `typst-ts-mode'."
+  '("Typst"
+    ("Heading"
+     ["Move Heading Up" typst-ts-editing-meta-up
+      :active (typst-ts-editing-heading--at-point-p)
+      :keys "M-<up>"]
+     ["Move Heading Down" typst-ts-editing-meta-down
+      :active (typst-ts-editing-heading--at-point-p)
+      :keys "M-<down>"]
+     "--"
+     ["Lower Heading Level" typst-ts-editing-meta-left
+      :active (typst-ts-editing-heading--at-point-p)
+      :keys "M-<left>"]
+     ["Increase Heading Level" typst-ts-editing-meta-right
+      :active (typst-ts-editing-heading--at-point-p)
+      :keys "M-<right>"])
+    ("List"
+     ["Toggle Indent" typst-ts-editing-cycle
+      :active (typst-ts-editing-item--at-point-p)
+      :keys "TAB"]
+     ["Insert Item" typst-ts-editing-meta-return
+      :active (typst-ts-editing-item--at-point-p)
+      :keys "M-<return>"]
+     ["Change List Type" typst-ts-editing-item-list-change-type
+      :active (typst-ts-editing-item--at-point-p)]
+     ["Renumber List" typst-ts-editing-item-list-renumber
+      :active (typst-ts-editing-item--at-point-p)]
+     "--"
+     ["Move Item Up" typst-ts-editing-meta-up
+      :active (typst-ts-editing-item--at-point-p)
+      :keys "M-<up>"]
+     ["Move Item Down" typst-ts-editing-meta-down
+      :active (typst-ts-editing-item--at-point-p)
+      :keys "M-<down>"])
+    ("Table/Grid"
+     ["Move Cell Up" typst-ts-editing-meta-up
+      :active (typst-ts-editing-grid-cell--at-point-p)
+      :keys "M-<up>"]
+     ["Move Cell Down" typst-ts-editing-meta-down
+      :active (typst-ts-editing-grid-cell--at-point-p)
+      :keys "M-<down>"]
+     ["Move Cell Left" typst-ts-editing-meta-left
+      :active (typst-ts-editing-grid-cell--at-point-p)
+      :keys "M-<left>"]
+     ["Move Cell Right" typst-ts-editing-meta-right
+      :active (typst-ts-editing-grid-cell--at-point-p)
+      :keys "M-<right>"]
+     "--"
+     ["Move Row Up" typst-ts-editing-grid-row-up
+      :active (typst-ts-editing-grid-cell--at-point-p)]
+     ["Move Row Down" typst-ts-editing-grid-row-down
+      :active (typst-ts-editing-grid-cell--at-point-p)])
+    ("Compile"
+     ["Compile" typst-ts-compile
+      :key "C-c C-c"]
+     ["Compile and Preview" typst-ts-compile-and-preview
+      :key "C-c C-S-C"]
+     ["Preview" typst-ts-preview
+      :key "C-c C-p"]
+     ["Watch Mode" typst-ts-watch-mode
+      :key "C-c C-w"]
+     ["Export to Markdown" typst-ts-mc-export-to-markdown])
+    ("Online"
+     ["Search Symbol/Emoji" typst-ts-mc-search-typst-symbol]
+     ["Recognize Handwritten Symbol" typst-ts-mc-recognize-typst-symbol]
+     ["Search Packages" typst-ts-mc-search-package])
+    ["Symbol/Emoji Picker" typst-ts-editing-symbol-picker]
+    ["Follow Thing at Point" typst-ts-mc-open-at-point
+     :key "C-c C-o"]
+    ["Edit Code Block" typst-ts-edit-indirect
+     :key "C-c '"]))
 
 (defun typst-ts-indent-line-function ()
   "A simple wrapper of `treesit-indent' for handle indentation edge cases.

Reply via email to