@@ -1003,9 +1003,9 @@ If there is no namespace, returns nil."
10031003(defun clojure-ts--node-child-skip-metadata (node n )
10041004 " Return the Nth child of NODE like `treesit-node-child' , sans metadata.
10051005Skip the optional metadata node at pos 0 if present."
1006- (let ((value-nodes (thread-last ( treesit-node-children node t )
1007- ( seq-filter ( lambda ( child )
1008- ( string= (treesit-node-field-name child) " value " ))) )))
1006+ (let ((value-nodes (treesit-filter-child node
1007+ # 'clojure-ts--value-type-node-p
1008+ t )))
10091009 (seq-elt value-nodes n)))
10101010
10111011(defun clojure-ts--first-value-child (node )
@@ -1147,6 +1147,10 @@ Includes a dispatch value when applicable (defmethods)."
11471147 " Return non-nil if NODE represents a protocol or interface definition."
11481148 (clojure-ts--definition-node-match-p clojure-ts--interface-type-regexp node))
11491149
1150+ (defun clojure-ts--value-type-node-p (node )
1151+ " Return non-nil if field name of the NODE is value."
1152+ (string= (treesit-node-field-name node) " value" ))
1153+
11501154(defvar clojure-ts--imenu-settings
11511155 `((" Namespace" " list_lit" clojure-ts--ns-node-p)
11521156 (" Function" " list_lit" clojure-ts--function-node-p
@@ -1436,17 +1440,34 @@ If NS is defined, then the fully qualified symbol is passed to
14361440 (seq-sort (lambda (spec1 _spec2 )
14371441 (equal (car spec1) :block )))))))))
14381442
1439- (defun clojure-ts--find-semantic-rules-for-node (node )
1440- " Return a list of semantic rules for NODE."
1441- (let* ((first-child (clojure-ts--node-child-skip-metadata node 0 ))
1442- (symbol-name (clojure-ts--named-node-text first-child))
1443- (symbol-namespace (clojure-ts--node-namespace-text first-child)))
1443+ (defvar clojure-ts--dynamic-indent-for-symbol-cache
1444+ (make-hash-table :test 'equal ))
1445+
1446+ (defvar clojure-ts--dynamic-indent-for-symbol-cache-p nil
1447+ " If set to nil, do not use cache for dynamic indentation rules." )
1448+
1449+ (defun clojure-ts--find-semantic-rules-for-symbol (node )
1450+ " Return a list of semantic rules for symbol NODE.
1451+
1452+ If rules are not found return :not-found symbol."
1453+ (let ((symbol-name (clojure-ts--named-node-text node))
1454+ (symbol-namespace (clojure-ts--node-namespace-text node)))
14441455 (or (clojure-ts--dynamic-indent-for-symbol symbol-name symbol-namespace)
14451456 (alist-get symbol-name
14461457 clojure-ts--semantic-indent-rules-cache
14471458 nil
14481459 nil
1449- #'equal ))))
1460+ #'equal )
1461+ :not-found )))
1462+
1463+ (defun clojure-ts--find-semantic-rules-for-node (node )
1464+ " Return a list of semantic rules for NODE."
1465+ (let* ((first-child (clojure-ts--first-value-child node))
1466+ (symbol-full-name (treesit-node-text first-child)))
1467+ (if clojure-ts--dynamic-indent-for-symbol-cache-p
1468+ (with-memoization (gethash symbol-full-name clojure-ts--dynamic-indent-for-symbol-cache)
1469+ (clojure-ts--find-semantic-rules-for-symbol first-child))
1470+ (clojure-ts--find-semantic-rules-for-symbol first-child))))
14501471
14511472(defun clojure-ts--find-semantic-rule (node parent current-depth )
14521473 " Return a suitable indentation rule for NODE, considering the CURRENT-DEPTH.
@@ -1458,7 +1479,8 @@ increasing the CURRENT-DEPTH. If a rule is not found upon reaching the
14581479root of the syntax tree, it returns nil. A rule is considered a match
14591480only if the CURRENT-DEPTH matches the rule's required depth."
14601481 (let* ((idx (- (treesit-node-index node) 2 )))
1461- (if-let* ((rule-set (clojure-ts--find-semantic-rules-for-node parent)))
1482+ (if-let* ((rule-set (clojure-ts--find-semantic-rules-for-node parent))
1483+ ((not (equal rule-set :not-found ))))
14621484 (if (zerop current-depth)
14631485 (let ((rule (car rule-set)))
14641486 (if (equal (car rule) :block )
@@ -1913,9 +1935,11 @@ between BEG and END."
19131935 (end (clojure-ts--end-of-defun-pos)))
19141936 (list start end))))))
19151937 (setq end (copy-marker end))
1938+ (clrhash clojure-ts--dynamic-indent-for-symbol-cache)
19161939 (let* ((sexps-to-align (clojure-ts--get-nodes-to-align beg (marker-position end)))
19171940 ; ; We have to disable it here to avoid endless recursion.
1918- (clojure-ts-align-forms-automatically nil ))
1941+ (clojure-ts-align-forms-automatically nil )
1942+ (clojure-ts--dynamic-indent-for-symbol-cache-p t ))
19191943 (save-excursion
19201944 (indent-region beg (marker-position end))
19211945 (dolist (sexp sexps-to-align)
@@ -2567,6 +2591,28 @@ before DELIM-OPEN."
25672591 (goto-char pos))
25682592 (user-error " Must be invoked inside a list" )))
25692593
2594+ (defun clojure-ts--toggle-ignore-next-sexp (&optional n )
2595+ " Insert or delete N `#_' ignore macros at the current point.
2596+
2597+ Point must be directly before a sexp or the #_ characters. When acting
2598+ on a top level form, insert #_ on a new line preceding the form to
2599+ prevent indentation changes."
2600+
2601+ (dotimes (_ (or n 1 )) (insert-before-markers " #_" )))
2602+
2603+ (defun clojure-ts-toggle-ignore (&optional n )
2604+ " Toggle the #_ ignore reader form for the sexp at point.
2605+
2606+ With the numeric argument, toggle N number of #_ forms at the same point.
2607+
2608+ e.g. with N = 2:
2609+ |a b c => #_#_a b c"
2610+ (interactive " p" )
2611+ (let ((sexp (treesit-thing-at-point 'sexp 'nested )))
2612+ (goto-char (treesit-node-start sexp))
2613+ (clojure-ts--toggle-ignore-next-sexp n)
2614+ ))
2615+
25702616(defvar clojure-ts-refactor-map
25712617 (let ((map (make-sparse-keymap )))
25722618 (keymap-set map " C-t" #'clojure-ts-thread )
0 commit comments