[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/el-search 1f81442 241/332: [el-search] Improve forward
From: |
Stefan Monnier |
Subject: |
[elpa] externals/el-search 1f81442 241/332: [el-search] Improve forward search functions |
Date: |
Tue, 1 Dec 2020 15:48:54 -0500 (EST) |
branch: externals/el-search
commit 1f81442f7cfb56a67dc698273f2423d6a54b76cf
Author: Michael Heerdegen <michael_heerdegen@web.de>
Commit: Michael Heerdegen <michael_heerdegen@web.de>
[el-search] Improve forward search functions
The goal of this commit is to further align syntax and semantics of
el-search's forward search functions with Emacs text search functions.
* packages/el-search/el-search.el (el-search--search-pattern-1)
(el-search-forward): Implement COUNT argument. Make the NOERROR
argument behave like in `search-forward' when neither nil or t. Raise
error for invalid search bounds. Search further after a found match
ends after BOUND - a subsequent match may still end before. Fix
behavior when BOUND is exceeded. Enhance docstrings.
---
el-search.el | 123 +++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 81 insertions(+), 42 deletions(-)
diff --git a/el-search.el b/el-search.el
index 82b8b60..d45d9ca 100644
--- a/el-search.el
+++ b/el-search.el
@@ -970,13 +970,27 @@ N times."
(funcall matcher expression))
-(defun el-search--search-pattern-1 (matcher &optional noerror bound
heuristic-matcher)
+(defun el-search--search-pattern-1 (matcher &optional noerror bound
heuristic-matcher count)
"Like `el-search-forward' but accepts a matcher as first argument.
In addition, a HEURISTIC-MATCHER corresponding to the MATCHER can
-be specified as third optional argument."
- (if (not (derived-mode-p 'emacs-lisp-mode))
- (if noerror nil (error "Buffer not in emacs-lisp-mode: %s"
(buffer-name)))
- (let ((match-beg nil) (opoint (point)) current-expr)
+be specified as fourth argument, and COUNT becomes the fifth argument."
+ (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-backward-1 matcher noerror bound heuristic-matcher (-
count)))
+ ((and bound (< bound (point)))
+ (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-max))
+ opoint))
+ (if noerror nil (signal 'search-failed nil)))))
;; when inside a string or comment, move past it
(let ((syntax-here (syntax-ppss)))
@@ -987,41 +1001,57 @@ be specified as third optional argument."
(forward-line 1)
(while (and (not (eobp)) (looking-at (rx (and (* space) ";"))))
(forward-line 1))))
-
- (cond
- ((catch 'no-match
- (while (and (not match-beg) (or (not bound) (<= (point) bound)))
- (condition-case nil
- (setq current-expr (el-search--ensure-sexp-start))
- (end-of-buffer
- (goto-char opoint)
- (throw 'no-match t)))
- (let ((end-of-defun nil))
- (cond
- ((and el-search-optimized-search
- heuristic-matcher
- (looking-at "^(")
- (not (funcall heuristic-matcher
- (current-buffer)
- (thunk-delay
- (el-search--flatten-tree
- (save-excursion
- (prog1 (el-search-read (current-buffer))
- (setq end-of-defun (point)))))))))
- (goto-char (or end-of-defun
- ;; The thunk hasn't been forced
- (scan-lists (point) 1 0))))
- ((el-search--match-p matcher current-expr)
- (setq match-beg (point)
- opoint (point)))
- (t (el-search--skip-expression current-expr))))))
- (if noerror nil (signal 'search-failed nil)))
- ((and bound match-beg)
- (and (<= (scan-sexps match-beg 1) bound)
- match-beg))
- (t match-beg)))))
-
-(defun el-search-forward (pattern &optional bound noerror)
+ (if count
+ (cond
+ ((= count 0) (point)) ;this is what the vanilla search functions do
+ ((catch 'success
+ (while (< 0 count)
+ (cond
+ ((not (el-search--search-pattern-1 matcher 'noerror bound
heuristic-matcher))
+ (throw 'success nil))
+ ((= 1 count)
+ (throw 'success t))
+ (t
+ (cl-decf count)
+ (el-search--skip-expression nil t)))))
+ (point))
+ (t (funcall fail)))
+ (let ((match-beg nil) current-expr)
+ (if (catch 'no-match
+ (while (not match-beg)
+ (condition-case nil
+ (setq current-expr (el-search--ensure-sexp-start))
+ (end-of-buffer (throw 'no-match t)))
+ (let ((end-of-defun nil))
+ (cond
+ ((and el-search-optimized-search
+ heuristic-matcher
+ (looking-at "^(")
+ (not (funcall heuristic-matcher
+ (current-buffer)
+ (thunk-delay
+ (el-search--flatten-tree
+ (save-excursion
+ (prog1 (el-search-read
(current-buffer))
+ (setq end-of-defun
(point)))))))))
+ (goto-char (or end-of-defun
+ ;; the thunk hasn't been forced
+ (scan-lists (point) 1 0))))
+ ((el-search--match-p matcher current-expr)
+ (setq match-beg
+ (and (or (not bound)
+ (<= (scan-sexps match-beg 1) bound)
+ ;; don't fail for >: a subsequent match
may end before BOUND
+ )
+ (point))))
+ (t (el-search--skip-expression current-expr))))
+ (when (and bound (<= bound (point)))
+ (throw 'no-match t)))
+ nil)
+ (funcall fail)
+ match-beg)))))))
+
+(defun el-search-forward (pattern &optional bound noerror count)
"Search for el-search PATTERN in current buffer from point.
Set point to the beginning of the occurrence found and return point.
@@ -1031,9 +1061,18 @@ value of nil means search to the end of the accessible
portion of
the buffer.
Optional third argument NOERROR, if non-nil, means if fail just
-return nil (no error)."
+return nil (no error); when not t, in addition also move to limit
+of search.
+
+The optional fourth argument COUNT is a number that indicates the
+search direction and the number of occurrences to search for. If
+it is positive, search forward for COUNT successive occurrences;
+if it is negative, search backward for -COUNT occurrences. The
+match found is the COUNTth/-COUNTth one in the buffer starting
+after/before the origin of the search."
(el-search--search-pattern-1 (el-search-make-matcher pattern) noerror bound
- (el-search-heuristic-matcher pattern)))
+ (el-search-heuristic-matcher pattern)
+ count))
;; FIXME: make this also a declaration spec?
- [elpa] externals/el-search c878a24 173/332: Fix "Make amount of context around occur matches adjustable", (continued)
- [elpa] externals/el-search c878a24 173/332: Fix "Make amount of context around occur matches adjustable", Stefan Monnier, 2020/12/01
- [elpa] externals/el-search f6b1aec 180/332: Some details, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 8583d46 191/332: Fix resuming a single-buffer query-replace, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 365f93f 197/332: * el-search/el-search.el: Some buffer display related minor tweaks, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search c69dd52 205/332: * el-search/el-search.el: Some minor tweaks, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search c41288f 208/332: Make el-search key binding installation more flexible, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 8d20f8a 217/332: Add face `el-search-highlight-in-prompt-face', Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 75f94f9 218/332: Improve quit/error handling in el-search-query-replace, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search b278fb7 219/332: Update a variable when splicing mode is toggled, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 8175417 237/332: * el-search/el-search.el: More minor tweaks, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 1f81442 241/332: [el-search] Improve forward search functions,
Stefan Monnier <=
- [elpa] externals/el-search 5c3bd4e 247/332: [el-search] Add bindings for first/last match jumping, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 3699425 246/332: [el-search] Add command 'el-search-last-buffer-match', Stefan Monnier, 2020/12/01
- [elpa] externals/el-search cf68daf 249/332: [el-search] Avoid most calls to 'scan-sexps', Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 894f8b1 254/332: [el-search] More minor tweaks, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 6c5a6b4 265/332: [el-search] Fix an infloop in el-search--search-pattern-1, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search b830be5 263/332: [el-search] Some scrolling tweaks, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search e60f228 267/332: [el-search] Don't try to kill modified buffers, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search 34f734e 258/332: [el-search] Add special scroll commands, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search d4ad652 278/332: [el-search] Implement an explicit quit command, Stefan Monnier, 2020/12/01
- [elpa] externals/el-search fbe70bf 284/332: [el-search] Add C-h help, Stefan Monnier, 2020/12/01