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.