[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/el-search ce8835b 242/332: [el-search] Factor out `el-s
From: |
Stefan Monnier |
Subject: |
[elpa] externals/el-search ce8835b 242/332: [el-search] Factor out `el-search-backward' |
Date: |
Tue, 1 Dec 2020 15:48:54 -0500 (EST) |
branch: externals/el-search
commit ce8835b8046cff2dc6155e916307cceb2abf62f8
Author: Michael Heerdegen <michael_heerdegen@web.de>
Commit: Michael Heerdegen <michael_heerdegen@web.de>
[el-search] Factor out `el-search-backward'
This commit provides a non-interactive backward search function
analogue to `el-search-forward'.
(el-search--search-backward-1, el-search-backward): New functions.
(el-search-pattern-backward): Rewrite to use `el-search-backward'.
---
el-search.el | 182 ++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 124 insertions(+), 58 deletions(-)
diff --git a/el-search.el b/el-search.el
index d45d9ca..1176275 100644
--- a/el-search.el
+++ b/el-search.el
@@ -2466,11 +2466,102 @@ With prefix arg, restart the current search."
(setq el-search--success nil))
(el-search-continue-search))
+(defun el-search--search-backward-1 (matcher &optional noerror bound
heuristic-matcher count)
+ "Like `el-search-backward' but accepts a matcher as first argument.
+In addition, a HEURISTIC-MATCHER corresponding to the MATCHER can
+be specified as fourth argument, and COUNT becomes the fifth argument.
+
+This function is the counterpart of `el-search--search-pattern-1'."
+ (cond
+ ((not (derived-mode-p 'emacs-lisp-mode))
+ (if noerror nil (error "Buffer not in emacs-lisp-mode: %s" (buffer-name))))
+ ((and count (not (integerp count)))
+ (signal 'wrong-type-argument (list 'integerp count)))
+ ((and count (< count 0))
+ (el-search--search-pattern-1 matcher noerror bound heuristic-matcher (-
count)))
+ ((and bound (< (point) bound))
+ (error "Invalid search bound (wrong side of point)"))
+ (t
+ (let* ((opoint (point))
+ (fail (lambda ()
+ (goto-char
+ (if (not (memq noerror '(nil t)))
+ (or bound (point-min))
+ opoint))
+ (if noerror nil (signal 'search-failed nil)))))
+ (if count
+ (cond
+ ((= count 0) (point)) ;this is what the vanilla search functions do
+ ((catch 'success
+ ;; This is inefficient: O(n^2)
+ (while (< 0 count)
+ (cond
+ ((not (el-search--search-backward-1 matcher 'noerror bound
heuristic-matcher))
+ (throw 'success nil))
+ ((= 1 count)
+ (throw 'success t))
+ (t (cl-decf count)))))
+ (point))
+ (t (funcall fail)))
+ (let ((found-match nil))
+ (let ((outer-loop-done nil))
+ ;; Strategy: search forwards (inner loop) for PATTERN, starting
from
+ ;; this toplevel expression's beginning up to point. If matches
+ ;; starting before point exist, return the last one. If no match
is
+ ;; found, search the top level expression before this one up to its
+ ;; end, etc (outer loop).
+ (while (not outer-loop-done)
+ (let ((hindmost-match nil)
+ (current-upper-limit (point))
+ (current-defun-start (or (syntax-ppss-toplevel-pos
(syntax-ppss))
+ (scan-sexps (point) -1)))
+ (current-defun-end))
+
+ (when current-defun-start
+ ;; Search for the hindmost match starting before
CURRENT-UPPER-LIMIT
+ (let ((done nil))
+ (goto-char current-defun-start)
+ (setq current-defun-end (scan-sexps defun-start 1))
+ (when (and bound (< current-defun-end bound))
+ (setq done t
+ outer-loop-done t
+ found-match nil))
+ (while (and (not done)
+ (el-search--search-pattern-1
+ matcher 'no-error current-defun-end
heuristic-matcher))
+ (if (>= (point) current-upper-limit)
+ (setq done t)
+ (setq hindmost-match (point))
+ (el-search--skip-expression nil t)))))
+
+ (if (not hindmost-match)
+ (if current-defun-start
+ (goto-char current-defun-start)
+ ;; reached bob
+ (setq outer-loop-done t))
+ (setq outer-loop-done t)
+ (setq found-match hindmost-match)))))
+ (if (and found-match (not (and bound (< found-match bound))))
+ (goto-char found-match)
+ (funcall fail))))))))
+
+(defun el-search-backward (pattern &optional bound noerror count)
+ "Search backward for el-search PATTERN from point.
+Set point to the beginning of the occurrence found and return point.
+
+This function is almost identical to `el-search-forward', except
+that by default it searches backward instead of forward, and the
+sign of COUNT also indicates exactly the opposite searching
+direction. See `el-search-forward' for details."
+ (el-search--search-backward-1 (el-search-make-matcher pattern) noerror bound
+ (el-search-heuristic-matcher pattern)
+ count))
+
;;;###autoload
(defun el-search-pattern-backward (pattern)
- "Search the current buffer backward for matches of PATTERN."
- (declare (interactive-only t));; FIXME: define noninteractive version - and
-1 with hms like
- ;; `el-search--search-pattern-1'
+ "Search the current buffer backward for matches of PATTERN.
+See the command `el-search-pattern' for more information."
+ (declare (interactive-only el-search-backward))
(interactive (el-search-pattern--interactive))
(if (eq pattern (el-search--current-pattern))
(progn
@@ -2491,61 +2582,36 @@ With prefix arg, restart the current search."
(el-search--message-no-log "[Wrapped backward search]")
(sit-for .7)
(goto-char (point-max)))
- (let ((outer-loop-done nil)
- (original-point (point))
- (matcher (el-search--current-matcher))
- (heuristic-matcher (el-search--current-heuristic-matcher)))
- ;; Strategy: search forwards (inner loop) for PATTERN, starting from
- ;; this toplevel expression's beginning up to point, then if no match
- ;; is found, search the top level expression before this one up to its
- ;; end, etc (outer loop).
- (while (not outer-loop-done)
- (let ((last-match nil)
- (limit (point))
- (defun-start (or (syntax-ppss-toplevel-pos (syntax-ppss))
- (scan-sexps (point) -1)))
- (done nil) defun-end)
- (when defun-start
- (goto-char defun-start)
- (setq defun-end (scan-sexps defun-start 1))
- (while (and (not done)
- (el-search--search-pattern-1 matcher 'no-error
defun-end))
- (if (>= (point) limit)
- (setq done t)
- (setq last-match (point))
- (el-search--skip-expression nil t))))
- (if (not last-match)
- (if defun-start
- (goto-char defun-start)
- ;; reached bob
- (goto-char original-point)
- (setq outer-loop-done t)
- (if (not (or el-search--success
- (save-excursion
- (goto-char (point-min))
- (el-search--search-pattern-1 matcher t nil
heuristic-matcher))))
- (progn
- (ding)
- (el-search--message-no-log "No matches")
- (sit-for .7))
- (let ((keys (car (where-is-internal
'el-search-pattern-backward))))
- (el-search--message-no-log
- (if keys
- (format "No (more) match; hit %s to wrap search"
(key-description keys))
- "No (more) match")))
- (sit-for .7)
- (goto-char original-point)
- (el-search--set-wrap-flag 'backward)))
- (setq outer-loop-done t)
- (goto-char last-match)
- (setf (el-search-head-position (el-search-object-head
el-search--current-search))
- (copy-marker (point)))
- (setf (el-search-object-last-match el-search--current-search)
- (copy-marker (point)))
- (el-search-hl-sexp)
- (unless (eq last-command 'el-search-pattern)
- (el-search-hl-other-matches (el-search--current-matcher)))
- (setq el-search--success t))))))
+ (if-let ((preceding-match (el-search--search-backward-1
+ (el-search--current-matcher)
+ t nil
+ (el-search--current-heuristic-matcher))))
+ (progn
+ (goto-char preceding-match)
+ (setf (el-search-head-position (el-search-object-head
el-search--current-search))
+ (copy-marker (point)))
+ (setf (el-search-object-last-match el-search--current-search)
+ (copy-marker (point)))
+ (el-search-hl-sexp)
+ (unless (eq last-command 'el-search-pattern)
+ (el-search-hl-other-matches (el-search--current-matcher)))
+ (setq el-search--success t))
+ (if (not (or el-search--success
+ (save-excursion
+ (goto-char (point-min))
+ (el-search--search-pattern-1
+ (el-search--current-matcher) t nil
(el-search--current-heuristic-matcher)))))
+ (progn
+ (ding)
+ (el-search--message-no-log "No matches")
+ (sit-for .7))
+ (let ((keys (car (where-is-internal 'el-search-pattern-backward))))
+ (el-search--message-no-log
+ (if keys
+ (format "No (more) match; hit %s to wrap search" (key-description
keys))
+ "No (more) match")))
+ (sit-for .7)
+ (el-search--set-wrap-flag 'backward))))
(define-obsolete-function-alias 'el-search-previous-match
'el-search-pattern-backward "since el-search-1.3")
- [elpa] externals/el-search 39da179 313/332: [el-search] Minibuffer pattern prompt hints part 3, (continued)
- [elpa] externals/el-search 39da179 313/332: [el-search] Minibuffer pattern prompt hints part 3, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 01c663b 315/332: [el-search] Make el-search-query-replace resumable, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search c95de2b 317/332: [el-search] Shorten el-search-query-replace prompt again, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 76d63d9 326/332: [el-search] Extend possible search domains, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 0212cf9 328/332: * packages/el-search/el-search.el: New command el-search-repository, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 6df1362 332/332: * .gitignore: New file, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 6c0475e 212/332: Allow to save the current el-search to a register, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 7c19468 215/332: Fix el-search's to register save when no search started yet, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search c7709ab 233/332: Fix el-search's check for buffers visiting a given file, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search cda69ae 230/332: * el-search/el-search-x.el: New user option `el-search-lazy-l', Stefan Monnier, 2020/12/01
- [elpa] externals/el-search ce8835b 242/332: [el-search] Factor out `el-search-backward',
Stefan Monnier <=
- [elpa] externals/el-search dfaa7f2 244/332: [el-search] Some more minor tweaks, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search a6c23b5 250/332: * el-search/el-search.el: Correct NOERROR argument uses, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 2a02a81 277/332: [el-search] Let el-search-query-replace add undo boundaries, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 864f0ed 276/332: [el-search] Provide el-search-occur-search-object earlier, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 23cf24d 275/332: [el-search] Enhancements to my last two commits, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search effcb50 271/332: [el-search] Make r hit twice restore a replaced match, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search b9ba337 283/332: [el-search] Allow to work without installing key bindings, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 841a027 287/332: [el-search] Some optimization tweaks, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 70634b7 298/332: [el-search] Avoid bytecomp warning windows pop up, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 22c2f25 297/332: [el-search] Display colored defun match count, Stefan Monnier, 2020/12/01