From f7c927bca10296959cd4722c0268356380026a22 Mon Sep 17 00:00:00 2001 From: jdormit Date: Sat, 4 May 2024 22:02:51 -0400 Subject: [PATCH] Make origami-treesit more generic --- emacs/.emacs.d/config/init-editing.el | 5 +- emacs/.emacs.d/config/init-treesit.el | 32 ++----- .../origami-treesit/origami-treesit.el | 90 +++++++++++++++++++ 3 files changed, 100 insertions(+), 27 deletions(-) create mode 100644 emacs/.emacs.d/packages/origami-treesit/origami-treesit.el diff --git a/emacs/.emacs.d/config/init-editing.el b/emacs/.emacs.d/config/init-editing.el index 128bd46..ee2c60b 100644 --- a/emacs/.emacs.d/config/init-editing.el +++ b/emacs/.emacs.d/config/init-editing.el @@ -149,6 +149,9 @@ (when-let ((path (origami-fold-find-path-containing tree point))) (let ((parent (origami-fold-parent path))) (dolist (fold (origami-fold-children parent)) - (origami-toggle-node buffer (origami-fold-beg fold)))))))) + (origami-toggle-node buffer (origami-fold-beg fold))))))) + (defun origami-setup () + (evil-local-set-key 'normal (kbd "zM") #'origami-toggle-all-nodes-same-level)) + (add-hook 'origami-mode-hook #'origami-setup)) (provide 'init-editing) diff --git a/emacs/.emacs.d/config/init-treesit.el b/emacs/.emacs.d/config/init-treesit.el index 9fb898b..f678dc7 100644 --- a/emacs/.emacs.d/config/init-treesit.el +++ b/emacs/.emacs.d/config/init-treesit.el @@ -107,32 +107,12 @@ (->> (treesit-query-capture args '((string (string_content) @name))) (-filter (lambda (n) (eq (car n) 'name))) (-map #'cdr) - (-mapcat (lambda (n) (treesit-node-text n t)))))) + (-mapcat (lambda (n) (treesit-node-text n t))))))) - (defun origami-yaml-treesit-parser (create) - (lambda (content) - (let* ((parser (treesit-parser-create 'yaml)) - (root (treesit-parser-root-node parser))) - (cl-labels ((get-node-folds (node) - (if (equal (treesit-node-type node) "block_mapping_pair") - (let ((key-node (treesit-node-child-by-field-name node "key")) - (value-node (treesit-node-child-by-field-name node "value"))) - (list (funcall create - (save-excursion - (goto-char (treesit-node-start node)) - (line-beginning-position)) - (treesit-node-end node) - (save-excursion - (goto-char (treesit-node-start key-node)) - (+ 1 (- (treesit-node-end key-node) (line-beginning-position)))) - (-mapcat #'get-node-folds (treesit-node-children value-node))))) - (-mapcat #'get-node-folds (treesit-node-children node))))) - (get-node-folds root))))) - - (with-eval-after-load 'origami - (add-to-list 'origami-parser-alist '(yaml-ts-mode . origami-yaml-treesit-parser)) - (defun yaml-ts-origami-setup () - (evil-local-set-key 'normal (kbd "zM") #'origami-toggle-all-nodes-same-level)) - (add-hook 'yaml-ts-mode-hook #'yaml-ts-origami-setup))) +(use-package origami-treesit + :straight (:type built-in) + :ensure nil + :load-path "packages/origami-treesit" + :after origami) (provide 'init-treesit) diff --git a/emacs/.emacs.d/packages/origami-treesit/origami-treesit.el b/emacs/.emacs.d/packages/origami-treesit/origami-treesit.el new file mode 100644 index 0000000..98d99ec --- /dev/null +++ b/emacs/.emacs.d/packages/origami-treesit/origami-treesit.el @@ -0,0 +1,90 @@ +;;; origami-treesit.el --- treesit.el integration with origami.el text folding -*- lexical-binding: t; -*- + +;; Copyright (C) 2024 Jeremy Dormitzer + +;; Author: Jeremy Dormitzer +;; Version: 0.1.0 +;; Package-Requires: ((emacs "29.1") (origami "1.0") (dash "2.19.1") (cl-lib "1.0")) +;; Keywords: tools + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; Adds origami parsers based on tree-sitter. + +;;; Code: +(require 'treesit) +(require 'cl-lib) +(require 'dash) + +(cl-defun make-treesit-parser (create + lang + &key + node-matcher-fn + fold-fn) + (lambda (content) + (let* ((parser (treesit-parser-create lang)) + (root (treesit-parser-root-node parser))) + (cl-labels ((get-node-folds (node) + (if (funcall node-matcher-fn node) + (cl-destructuring-bind (start end offset child-nodes) (funcall fold-fn node) + (list (funcall create start end offset (-mapcat #'get-node-folds child-nodes)))) + (-mapcat #'get-node-folds (treesit-node-children node))))) + (get-node-folds root))))) + +(defun origami-yaml-treesit-parser (create) + (make-treesit-parser create 'yaml + :node-matcher-fn (lambda (node) + (member (treesit-node-type node) + '("block_mapping_pair" + "flow_mapping" + "flow_pair" + "flow_sequence"))) + :fold-fn (lambda (node) + (pcase (treesit-node-type node) + ((or "block_mapping_pair" "flow_pair") + (let* ((key-node (treesit-node-child-by-field-name node "key")) + (value-node (treesit-node-child-by-field-name node "value")) + (line-beginning (save-excursion + (goto-char (treesit-node-start node)) + (line-beginning-position))) + (on-own-line? (= (save-excursion + (goto-char (treesit-node-start node)) + (back-to-indentation) + (point)) + (treesit-node-start node))) + (start (save-excursion + (goto-char (treesit-node-start node)) + (if on-own-line? + line-beginning + (treesit-node-start node)))) + (end (treesit-node-end node)) + (offset (+ 1 (if on-own-line? + (- (treesit-node-end key-node) line-beginning) + (length (treesit-node-text key-node t))))) + (child-nodes (treesit-node-children value-node))) + (list start end offset child-nodes))) + ((or "flow_mapping" "flow_sequence") + (let* ((start (treesit-node-start node)) + (end (- (treesit-node-end node) 1)) + (offset 1) + (child-nodes (treesit-node-children node))) + (list start end offset child-nodes))))))) + +(with-eval-after-load 'origami + (add-to-list 'origami-parser-alist '(yaml-ts-mode . origami-yaml-treesit-parser))) + +(provide 'origami-treesit) +;;; origami-treesit.el ends here