[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/expand-region af2916b89d 2/2: expand-region: Memoize ex
|
From: |
ELPA Syncer |
|
Subject: |
[elpa] externals/expand-region af2916b89d 2/2: expand-region: Memoize expansion results |
|
Date: |
Thu, 4 Jan 2024 12:58:26 -0500 (EST) |
branch: externals/expand-region
commit af2916b89d8b5e520ff4ee7214bab62a0fdb3cec
Author: Karthik Chikmagalur <karthikchikmagalur@gmail.com>
Commit: Magnar Sveen <magnars@gmail.com>
expand-region: Memoize expansion results
expand-region-core.el (er--expand-region-1, er--saved-expansions): Use
a new buffer-local variable, `er--saved-expansions`, to hold
information about the point/mark returned by `er/try-expand-list'. If
using `er/expand-region' or `er/contract-region' repeatedly, use this
memoized data instead of recomputing all expansions. This speeds up
expand-region significantly when there are a large number of or
expensive functions in `er/try-expand-list'.
expand-region.el (er/expand-region): Clear the saved expansion data in
`er--saved-expansions` on the first (non-chained) invocation of
`er/expand-region' or `er-contract-region`.
---
expand-region-core.el | 37 ++++++++++++++++++++++++++-----------
expand-region.el | 2 ++
2 files changed, 28 insertions(+), 11 deletions(-)
diff --git a/expand-region-core.el b/expand-region-core.el
index 1f60dbe974..e2829cdcb3 100644
--- a/expand-region-core.el
+++ b/expand-region-core.el
@@ -50,6 +50,12 @@
"t if this is the first invocation of `er/expand-region' or
`er/contract-region'."
(not (memq last-command '(er/expand-region er/contract-region))))
+(defvar-local er--saved-expansions nil
+ "List of region data used to avoid redundant computation.
+
+When expand-region or contract-region is called repeatedly, save
+the data here and reuse when possible.")
+
(defun er--prepare-expanding ()
(when (and (er--first-invocation)
(not (use-region-p)))
@@ -109,17 +115,26 @@ moving point or mark as little as possible."
(setq start (point)))
(er--save-excursion
- (while try-list
- (ignore-errors
- (save-mark-and-excursion
- (funcall (car try-list))
- (when (and (region-active-p)
- (er--this-expansion-is-better start end best-start
best-end))
- (setq best-start (point))
- (setq best-end (mark))
- (when (and er--show-expansion-message (not (minibufferp)))
- (message "%S" (car try-list))))))
- (setq try-list (cdr try-list))))
+ (while try-list
+ (ignore-errors
+ (save-mark-and-excursion
+ ;; Try expansion or fetch memoized value
+ (if-let* ((try-func (car try-list))
+ ((not (er--first-invocation)))
+ (bounds (alist-get try-func er--saved-expansions))
+ ((or (>= (point) (car bounds)) (<= (mark) (cadr
bounds)))))
+ (progn (set-mark (cadr bounds))
+ (goto-char (car bounds)))
+ (funcall try-func)
+ (setf (alist-get try-func er--saved-expansions) (list (point)
(mark))))
+ ;; Test expansion against best expansion so far
+ (when (and (region-active-p)
+ (er--this-expansion-is-better start end best-start
best-end))
+ (setq best-start (point))
+ (setq best-end (mark))
+ (when (and er--show-expansion-message (not (minibufferp)))
+ (message "%S" (car try-list))))))
+ (setq try-list (cdr try-list))))
(setq deactivate-mark nil)
;; if smart cursor enabled, decide to put it at start or end of region:
diff --git a/expand-region.el b/expand-region.el
index ebaaca2967..78a9bef446 100644
--- a/expand-region.el
+++ b/expand-region.el
@@ -157,6 +157,8 @@ before calling `er/expand-region' for the first time."
(setq arg (- arg 1))
(when (eq 'early-exit (er--expand-region-1))
(setq arg 0)))
+ (when (er--first-invocation)
+ (setq-local er--saved-expansions nil))
(when (and expand-region-fast-keys-enabled
(not (memq last-command '(er/expand-region
er/contract-region))))
(er/prepare-for-more-expansions))))