Skip to content

Commit

Permalink
generalize molds that required tree-sitter to be available also with …
Browse files Browse the repository at this point in the history
…treesit

some are missing still, left TODOs in there
  • Loading branch information
ag91 committed Nov 10, 2024
1 parent 239ae4c commit 14608df
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 115 deletions.
10 changes: 8 additions & 2 deletions moldable-emacs.el
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ Optionally start from NODE. Note this keeps text properties in
the :text property of a node."
(let ((root (or
node
(ignore-errors
(with-demoted-errors "me-mold-treesit-to-parse-tree: %S"
(treesit-parse-string ;; in treesit we parse the file only if using a lang-ts-mode
(buffer-string)
(me-major-mode-to-tree-sitter-grammar major-mode)))))
Expand Down Expand Up @@ -491,6 +491,10 @@ the :text property of a node."
(funcall make-node root 0)
(reverse acc))))))

(defun me-tree-node-at-point (point)
(if me-use-treesitter
(me-to-parse-tree (tree-sitter-node-at-point :named point))
(treesit-node-at point nil 'named)))

(defun me-mold-treesitter-to-parse-tree (&optional node)
"Return list of all abstract syntax tree nodes one step away from leaf nodes.
Expand Down Expand Up @@ -549,7 +553,9 @@ Optionally start from NODE."

(defun me-major-mode-to-tree-sitter-grammar (major-mode)
"Find emacs-tree-sitter grammar for MAJOR-MODE."
(alist-get major-mode tree-sitter-major-mode-language-alist))
(if me-use-treesitter
(alist-get major-mode tree-sitter-major-mode-language-alist)
(treesit-language-at (point))))

(defun me-extension-to-tree-sitter-grammar (extension)
"Find emacs-tree-sitter grammar for EXTENSION."
Expand Down
101 changes: 52 additions & 49 deletions molds/contrib.el
Original file line number Diff line number Diff line change
Expand Up @@ -239,55 +239,58 @@ following in your lein project.clj
1))

(me-register-mold
:key "FunctionsComplexity"
:given (:fn (and
(me-require 'code-compass)
(me-require 'tree-sitter)
(not (eq major-mode 'json-mode))
(not (eq major-mode 'csv-mode))
(not (eq major-mode 'yaml-mode))
;; ignore files over 8kb
(<= (/ (buffer-size) 1024) 800)
;; calculating complexities may take 4 secs on certain files, so we just look for functions
(me-extract-functions (me-to-parse-tree))))
:when (:fn
(me-file-updated-last-1-sec-p (buffer-file-name)))
:then (:fn
(let ((complexities
(ignore-errors (me-functions-complexity
(me-to-parse-tree)
#'code-compass-calculate-complexity-stats))))
(with-current-buffer buffername
(erase-buffer)
(org-mode)
(setq-local self complexities)
(me-insert-org-table
`(("Function" .
(:extractor
(lambda (obj) obj)
:handler
(lambda (obj) (ignore-errors
(message "%s" (list obj (plist-get obj :identifier) (plist-get (plist-get obj :node) :buffer-file)))
(me-make-elisp-navigation-link
(plist-get obj :identifier)
(plist-get (plist-get obj :node) :buffer-file))))))
("Complexity" .
(:extractor
(lambda (obj) (alist-get 'total (plist-get obj :complexity)))
:handler
(lambda (s) (me-highlight-function-complexity s))))
("Length" .
(:extractor
(lambda (obj) (alist-get 'n-lines (plist-get obj :complexity)))
:handler
(lambda (s) (me-highlight-function-length s))))
)
(--sort (> (alist-get 'total (plist-get it :complexity))
(alist-get 'total (plist-get other :complexity)))
complexities))
(goto-char (point-min)))
))
:docs "Show a table showing code complexity for the functions in the buffer.")
:key "FunctionsComplexity"
:given (:fn (and
(me-require 'code-compass)
(and
(or (me-require 'tree-sitter)
(me-require 'treesit))
(me-major-mode-to-tree-sitter-grammar major-mode))
(not (eq major-mode 'json-mode))
(not (eq major-mode 'csv-mode))
(not (eq major-mode 'yaml-mode))
;; ignore files over 8kb
(<= (/ (buffer-size) 1024) 800)
;; calculating complexities may take 4 secs on certain files, so we just look for functions
(me-extract-functions (me-to-parse-tree))))
:when (:fn
(me-file-updated-last-1-sec-p (buffer-file-name)))
:then (:fn
(let ((complexities
(ignore-errors (me-functions-complexity
(me-to-parse-tree)
#'code-compass-calculate-complexity-stats))))
(with-current-buffer buffername
(erase-buffer)
(org-mode)
(setq-local self complexities)
(me-insert-org-table
`(("Function" .
(:extractor
(lambda (obj) obj)
:handler
(lambda (obj) (ignore-errors
(message "%s" (list obj (plist-get obj :identifier) (plist-get (plist-get obj :node) :buffer-file)))
(me-make-elisp-navigation-link
(plist-get obj :identifier)
(plist-get (plist-get obj :node) :buffer-file))))))
("Complexity" .
(:extractor
(lambda (obj) (alist-get 'total (plist-get obj :complexity)))
:handler
(lambda (s) (me-highlight-function-complexity s))))
("Length" .
(:extractor
(lambda (obj) (alist-get 'n-lines (plist-get obj :complexity)))
:handler
(lambda (s) (me-highlight-function-length s))))
)
(--sort (> (alist-get 'total (plist-get it :complexity))
(alist-get 'total (plist-get other :complexity)))
complexities))
(goto-char (point-min)))
))
:docs "Show a table showing code complexity for the functions in the buffer.")

;; TODO make mold that let you open a note, this should add a warning if the note is outdated (i.e., the position cannot be found anymore)
(defun me-structure-to-dot-string (structure)
Expand Down
137 changes: 73 additions & 64 deletions molds/core.el
Original file line number Diff line number Diff line change
Expand Up @@ -123,41 +123,46 @@ Useful to run Elisp on the fly without a Playground."
:examples nil)

(me-register-mold
:key "CodeAsTree"
:given (:fn (and
(me-require 'tree-sitter)
(bound-and-true-p tree-sitter-mode)))
:then (:fn
(let* ((tree (me-to-parse-tree)))
(with-current-buffer buffername
(erase-buffer)
(emacs-lisp-mode)
(me-print-to-buffer tree)
(setq-local self tree))))
:docs "You get a flattened tree of all parsed elements.
:key "CodeAsTree"
:given (:fn (and
(or (me-require 'tree-sitter)
(me-require 'treesit))
(me-major-mode-to-tree-sitter-grammar major-mode)))
:then (:fn
(let* ((tree (me-to-parse-tree)))
(with-current-buffer buffername
(erase-buffer)
(emacs-lisp-mode)
(me-print-to-buffer tree)
(setq-local self tree))))
:docs "You get a flattened tree of all parsed elements.
You can transform this to extract information with the Playground mold."
:examples ((
:name "JSON to code flattened tree"
:given
(:type file :name "/tmp/test.json" :mode json-mode :contents "{\n \"a\": 1,\n \"b\": [1,2]\n}\n")
:then
(:type buffer :name "CodeAsTree" :mode emacs-lisp-mode :contents "((:type object :text \"{\\n \\\"a\\\": 1,\\n \\\"b\\\": [1,2]\\n}\" :begin 1 :end 27 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"{\" :text \"{\" :begin 1 :end 2 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type pair :text \"\\\"a\\\": 1\" :begin 5 :end 11 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type string :text \"\\\"a\\\"\" :begin 5 :end 8 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"\\\"\" :text \"\\\"\" :begin 5 :end 6 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type string_content :text \"a\" :begin 6 :end 7 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"\\\"\" :text \"\\\"\" :begin 7 :end 8 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \":\" :text \":\" :begin 8 :end 9 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type number :text \"1\" :begin 10 :end 11 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \",\" :text \",\" :begin 11 :end 12 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type pair :text \"\\\"b\\\": [1,2]\" :begin 15 :end 25 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type string :text \"\\\"b\\\"\" :begin 15 :end 18 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"\\\"\" :text \"\\\"\" :begin 15 :end 16 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type string_content :text \"b\" :begin 16 :end 17 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"\\\"\" :text \"\\\"\" :begin 17 :end 18 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \":\" :text \":\" :begin 18 :end 19 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type array :text \"[1,2]\" :begin 20 :end 25 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"[\" :text \"[\" :begin 20 :end 21 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type number :text \"1\" :begin 21 :end 22 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \",\" :text \",\" :begin 22 :end 23 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type number :text \"2\" :begin 23 :end 24 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"]\" :text \"]\" :begin 24 :end 25 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"}\" :text \"}\" :begin 26 :end 27 :buffer \"test.json\" :buffer-file \"/tmp/test.json\"))\n"))
))
:examples ((
:name "JSON to code flattened tree"
:given
(:type file :name "/tmp/test.json" :mode json-mode :contents "{\n \"a\": 1,\n \"b\": [1,2]\n}\n")
:then
(:type buffer :name "CodeAsTree" :mode emacs-lisp-mode :contents "((:type object :text \"{\\n \\\"a\\\": 1,\\n \\\"b\\\": [1,2]\\n}\" :begin 1 :end 27 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"{\" :text \"{\" :begin 1 :end 2 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type pair :text \"\\\"a\\\": 1\" :begin 5 :end 11 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type string :text \"\\\"a\\\"\" :begin 5 :end 8 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"\\\"\" :text \"\\\"\" :begin 5 :end 6 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type string_content :text \"a\" :begin 6 :end 7 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"\\\"\" :text \"\\\"\" :begin 7 :end 8 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \":\" :text \":\" :begin 8 :end 9 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type number :text \"1\" :begin 10 :end 11 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \",\" :text \",\" :begin 11 :end 12 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type pair :text \"\\\"b\\\": [1,2]\" :begin 15 :end 25 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type string :text \"\\\"b\\\"\" :begin 15 :end 18 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"\\\"\" :text \"\\\"\" :begin 15 :end 16 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type string_content :text \"b\" :begin 16 :end 17 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"\\\"\" :text \"\\\"\" :begin 17 :end 18 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \":\" :text \":\" :begin 18 :end 19 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type array :text \"[1,2]\" :begin 20 :end 25 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"[\" :text \"[\" :begin 20 :end 21 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type number :text \"1\" :begin 21 :end 22 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \",\" :text \",\" :begin 22 :end 23 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type number :text \"2\" :begin 23 :end 24 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"]\" :text \"]\" :begin 24 :end 25 :buffer \"test.json\" :buffer-file \"/tmp/test.json\")\n (:type \"}\" :text \"}\" :begin 26 :end 27 :buffer \"test.json\" :buffer-file \"/tmp/test.json\"))\n"))
))

(me-register-mold
:key "NodeAtPointToTree"
:given (:fn (and
(me-require 'tree-sitter)
(ignore-errors (tree-sitter-node-at-point :named))))
:then (:fn
(let* ((tree (me-to-parse-tree (tree-sitter-node-at-point :named))))
(with-current-buffer buffername
(erase-buffer)
(emacs-lisp-mode)
(me-print-to-buffer tree)
(setq-local self tree)
(current-buffer))))
:docs "You can obtain the code tree for the node at point.
:key "NodeAtPointToTree"
:let ((node-at-point (me-tree-node-at-point (point))))
:given (:fn (and
(or (me-require 'tree-sitter)
(me-require 'treesit))
(me-major-mode-to-tree-sitter-grammar major-mode)
node-at-point)
)
:then (:fn
(let* ((tree (me-to-parse-tree node-at-point)))
(with-current-buffer buffername
(erase-buffer)
(emacs-lisp-mode)
(me-print-to-buffer tree)
(setq-local self tree)
(current-buffer))))
:docs "You can obtain the code tree for the node at point.
This is a more focused view than `CodeToTree.'")

(me-register-mold
Expand Down Expand Up @@ -889,42 +894,45 @@ It specializes for source code."
(:type buffer :name "Node at point" :mode emacs-lisp-mode :contents "(list 1 2 3)\n"))))


;; TODO fix tree-sitter to work with treesit as well
(me-register-mold
:key "SimilarToNodeAtPoint"
:given (:fn (and
(-elem-index 'tree-sitter-mode minor-mode-list)
(ignore-errors (tree-sitter-node-at-point :named))))
:then (:fn
(let* ((tree (me-find-similar-nodes
(car (me-to-parse-tree (tree-sitter-node-at-point :named)))
(me-to-parse-tree))))
(with-current-buffer buffername
(emacs-lisp-mode)
(erase-buffer)
(me-print-to-buffer tree)
(setq-local self tree))))
:docs "You can gather all the nodes similar to the current one ordered by similarity."
:examples nil)
:key "SimilarToNodeAtPoint"
:given (:fn (and
(-elem-index 'tree-sitter-mode minor-mode-list)
(ignore-errors (tree-sitter-node-at-point :named))))
:then (:fn
(let* ((tree (me-find-similar-nodes
(car (me-to-parse-tree (tree-sitter-node-at-point :named)))
(me-to-parse-tree))))
(with-current-buffer buffername
(emacs-lisp-mode)
(erase-buffer)
(me-print-to-buffer tree)
(setq-local self tree))))
:docs "You can gather all the nodes similar to the current one ordered by similarity."
:examples nil)

;; TODO fix tree-sitter to work with treesit as well
(me-register-mold
:key "SamePrefixToNodeAtPoint"
:given (:fn (and
(-elem-index 'tree-sitter-mode minor-mode-list)
(ignore-errors (tree-sitter-node-at-point :named))))
:then (:fn
(let* ((tree (--filter
(s-prefix-p
(substring (plist-get (car (me-to-parse-tree (tree-sitter-node-at-point :named))) :text) 0 3) ; hardcoding 3 chars, also probably want just to add a same prefix option to my similarity function
(plist-get it :text))
(me-to-parse-tree))))
(with-current-buffer buffername
(emacs-lisp-mode)
(erase-buffer)
(me-print-to-buffer tree)
(setq-local self tree))))
:docs "You can gather all the nodes similar to the current one ordered by similarity."
:examples nil)
:key "SamePrefixToNodeAtPoint"
:given (:fn (and
(-elem-index 'tree-sitter-mode minor-mode-list)
(ignore-errors (tree-sitter-node-at-point :named))))
:then (:fn
(let* ((tree (--filter
(s-prefix-p
(substring (plist-get (car (me-to-parse-tree (tree-sitter-node-at-point :named))) :text) 0 3) ; hardcoding 3 chars, also probably want just to add a same prefix option to my similarity function
(plist-get it :text))
(me-to-parse-tree))))
(with-current-buffer buffername
(emacs-lisp-mode)
(erase-buffer)
(me-print-to-buffer tree)
(setq-local self tree))))
:docs "You can gather all the nodes similar to the current one ordered by similarity."
:examples nil)

;; TODO fix tree-sitter to work with treesit as well
(me-register-mold
:key "ProjectNodesToPlayground"
:given (:fn (and
Expand All @@ -943,6 +951,7 @@ It specializes for source code."
:docs "You can gather all the nodes of a project in a Playground."
:examples nil)

;; TODO fix tree-sitter to work with treesit as well
(me-register-mold
:key "ProjectNodesSameLanguageToPlayground"
:given (:fn (and
Expand Down

0 comments on commit 14608df

Please sign in to comment.