Skip to content

Commit 51850f5

Browse files
committed
Speedup align-forms by introducing indentation rules caching
1 parent 8e5e910 commit 51850f5

File tree

2 files changed

+51
-9
lines changed

2 files changed

+51
-9
lines changed

clojure-ts-mode.el

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1436,17 +1436,34 @@ If NS is defined, then the fully qualified symbol is passed to
14361436
(seq-sort (lambda (spec1 _spec2)
14371437
(equal (car spec1) :block)))))))))
14381438

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)))
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)))
14441451
(or (clojure-ts--dynamic-indent-for-symbol symbol-name symbol-namespace)
14451452
(alist-get symbol-name
14461453
clojure-ts--semantic-indent-rules-cache
14471454
nil
14481455
nil
1449-
#'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))))
14501467

14511468
(defun clojure-ts--find-semantic-rule (node parent current-depth)
14521469
"Return a suitable indentation rule for NODE, considering the CURRENT-DEPTH.
@@ -1458,7 +1475,8 @@ increasing the CURRENT-DEPTH. If a rule is not found upon reaching the
14581475
root of the syntax tree, it returns nil. A rule is considered a match
14591476
only if the CURRENT-DEPTH matches the rule's required depth."
14601477
(let* ((idx (- (treesit-node-index node) 2)))
1461-
(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))))
14621480
(if (zerop current-depth)
14631481
(let ((rule (car rule-set)))
14641482
(if (equal (car rule) :block)
@@ -1913,9 +1931,11 @@ between BEG and END."
19131931
(end (clojure-ts--end-of-defun-pos)))
19141932
(list start end))))))
19151933
(setq end (copy-marker end))
1934+
(clrhash clojure-ts--dynamic-indent-for-symbol-cache)
19161935
(let* ((sexps-to-align (clojure-ts--get-nodes-to-align beg (marker-position end)))
19171936
;; We have to disable it here to avoid endless recursion.
1918-
(clojure-ts-align-forms-automatically nil))
1937+
(clojure-ts-align-forms-automatically nil)
1938+
(clojure-ts--dynamic-indent-for-symbol-cache-p t))
19191939
(save-excursion
19201940
(indent-region beg (marker-position end))
19211941
(dolist (sexp sexps-to-align)
@@ -2567,6 +2587,28 @@ before DELIM-OPEN."
25672587
(goto-char pos))
25682588
(user-error "Must be invoked inside a list")))
25692589

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+
25702612
(defvar clojure-ts-refactor-map
25712613
(let ((map (make-sparse-keymap)))
25722614
(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)