Skip to content

Commit 7e07e8e

Browse files
committed
Fix imenu, speedup align-forms
1 parent 32490c8 commit 7e07e8e

File tree

2 files changed

+55
-16
lines changed

2 files changed

+55
-16
lines changed

clojure-ts-mode.el

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,13 +1003,10 @@ 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.
10051005
Skip the optional metadata node at pos 0 if present."
1006-
(let ((first-child (treesit-node-child node 0 t)))
1007-
(treesit-node-child
1008-
node
1009-
(if (clojure-ts--metadata-node-p first-child)
1010-
(1+ n)
1011-
n)
1012-
t)))
1006+
(let ((value-nodes (thread-last (treesit-node-children node t)
1007+
(seq-filter (lambda (child)
1008+
(string= (treesit-node-field-name child) "value"))))))
1009+
(seq-elt value-nodes n)))
10131010

10141011
(defun clojure-ts--first-value-child (node)
10151012
"Return the first value child of the given NODE.
@@ -1439,17 +1436,34 @@ If NS is defined, then the fully qualified symbol is passed to
14391436
(seq-sort (lambda (spec1 _spec2)
14401437
(equal (car spec1) :block)))))))))
14411438

1442-
(defun clojure-ts--find-semantic-rules-for-node (node)
1443-
"Return a list of semantic rules for NODE."
1444-
(let* ((first-child (clojure-ts--node-child-skip-metadata node 0))
1445-
(symbol-name (clojure-ts--named-node-text first-child))
1446-
(symbol-namespace (clojure-ts--node-namespace-text first-child)))
1439+
(defvar clojure-ts--dynamic-indent-for-symbol-cache
1440+
(make-hash-table :test 'equal))
1441+
1442+
(defvar clojure-ts--dynamic-indent-for-symbol-cache-p nil
1443+
"If set to nil, do not use cache for dynamic indentation rules.")
1444+
1445+
(defun clojure-ts--find-semantic-rules-for-symbol (node)
1446+
"Return a list of semantic rules for symbol NODE.
1447+
1448+
If rules are not found return :not-found symbol."
1449+
(let ((symbol-name (clojure-ts--named-node-text node))
1450+
(symbol-namespace (clojure-ts--node-namespace-text node)))
14471451
(or (clojure-ts--dynamic-indent-for-symbol symbol-name symbol-namespace)
14481452
(alist-get symbol-name
14491453
clojure-ts--semantic-indent-rules-cache
14501454
nil
14511455
nil
1452-
#'equal))))
1456+
#'equal)
1457+
:not-found)))
1458+
1459+
(defun clojure-ts--find-semantic-rules-for-node (node)
1460+
"Return a list of semantic rules for NODE."
1461+
(let* ((first-child (clojure-ts--node-child-skip-metadata node 0))
1462+
(symbol-full-name (treesit-node-text first-child)))
1463+
(if clojure-ts--dynamic-indent-for-symbol-cache-p
1464+
(with-memoization (gethash symbol-full-name clojure-ts--dynamic-indent-for-symbol-cache)
1465+
(clojure-ts--find-semantic-rules-for-symbol first-child))
1466+
(clojure-ts--find-semantic-rules-for-symbol first-child))))
14531467

14541468
(defun clojure-ts--find-semantic-rule (node parent current-depth)
14551469
"Return a suitable indentation rule for NODE, considering the CURRENT-DEPTH.
@@ -1461,7 +1475,8 @@ increasing the CURRENT-DEPTH. If a rule is not found upon reaching the
14611475
root of the syntax tree, it returns nil. A rule is considered a match
14621476
only if the CURRENT-DEPTH matches the rule's required depth."
14631477
(let* ((idx (- (treesit-node-index node) 2)))
1464-
(if-let* ((rule-set (clojure-ts--find-semantic-rules-for-node parent)))
1478+
(if-let* ((rule-set (clojure-ts--find-semantic-rules-for-node parent))
1479+
((not (equal rule-set :not-found))))
14651480
(if (zerop current-depth)
14661481
(let ((rule (car rule-set)))
14671482
(if (equal (car rule) :block)
@@ -1916,9 +1931,11 @@ between BEG and END."
19161931
(end (clojure-ts--end-of-defun-pos)))
19171932
(list start end))))))
19181933
(setq end (copy-marker end))
1934+
(clrhash clojure-ts--dynamic-indent-for-symbol-cache)
19191935
(let* ((sexps-to-align (clojure-ts--get-nodes-to-align beg (marker-position end)))
19201936
;; We have to disable it here to avoid endless recursion.
1921-
(clojure-ts-align-forms-automatically nil))
1937+
(clojure-ts-align-forms-automatically nil)
1938+
(clojure-ts--dynamic-indent-for-symbol-cache-p t))
19221939
(save-excursion
19231940
(indent-region beg (marker-position end))
19241941
(dolist (sexp sexps-to-align)
@@ -2570,6 +2587,28 @@ before DELIM-OPEN."
25702587
(goto-char pos))
25712588
(user-error "Must be invoked inside a list")))
25722589

2590+
(defun clojure-ts--toggle-ignore-next-sexp (&optional n)
2591+
"Insert or delete N `#_' ignore macros at the current point.
2592+
2593+
Point must be directly before a sexp or the #_ characters. When acting
2594+
on a top level form, insert #_ on a new line preceding the form to
2595+
prevent indentation changes."
2596+
2597+
(dotimes (_ (or n 1)) (insert-before-markers "#_")))
2598+
2599+
(defun clojure-ts-toggle-ignore (&optional n)
2600+
"Toggle the #_ ignore reader form for the sexp at point.
2601+
2602+
With the numeric argument, toggle N number of #_ forms at the same point.
2603+
2604+
e.g. with N = 2:
2605+
|a b c => #_#_a b c"
2606+
(interactive "p")
2607+
(let ((sexp (treesit-thing-at-point 'sexp 'nested)))
2608+
(goto-char (treesit-node-start sexp))
2609+
(clojure-ts--toggle-ignore-next-sexp n)
2610+
))
2611+
25732612
(defvar clojure-ts-refactor-map
25742613
(let ((map (make-sparse-keymap)))
25752614
(keymap-set map "C-t" #'clojure-ts-thread)

test/samples/refactoring.clj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@
141141
false)
142142

143143
(when-not true
144-
(println "Hello world"))
144+
(println #_#_"Hello world" "again"))
145145

146146
(extend-protocol prepare/SettableParameter
147147
clojure.lang.IPersistentMap

0 commit comments

Comments
 (0)