all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: James N V Cash <james.cash@occasionallycogent.com>
To: emacs-devel@gnu.org
Subject: [PATCH] Add option COUNT argument to text-property-search functions
Date: Fri, 30 Jul 2021 15:20:59 -0400	[thread overview]
Message-ID: <87im0rlias.fsf@gmail.com> (raw)


This allows searching forward for the Nth occurance of the text
property, analogously to re-search-forward/backward.

---
 lisp/emacs-lisp/text-property-search.el | 59 +++++++++++++++++++------
 1 file changed, 45 insertions(+), 14 deletions(-)

diff --git a/lisp/emacs-lisp/text-property-search.el b/lisp/emacs-lisp/text-property-search.el
index 7da02a9cb2..fa51488135 100644
--- a/lisp/emacs-lisp/text-property-search.el
+++ b/lisp/emacs-lisp/text-property-search.el
@@ -30,7 +30,7 @@
   beginning end value)

 (defun text-property-search-forward (property &optional value predicate
-                                              not-current)
+                                              not-current count)
   "Search for the next region of text where PREDICATE is true.
 PREDICATE is used to decide whether a value of PROPERTY should be
 considered as matching VALUE.
@@ -59,6 +59,9 @@ text-property-search-forward
 region that doesn't include point and has a value of PROPERTY
 that matches VALUE.

+If COUNT is a positive number, it will search forward COUNT times. If
+negative, it will perform text-property-search-backwards -COUNT times.
+
 If no matches can be found, return nil and don't move point.
 If found, move point to the end of the region and return a
 `prop-match' object describing the match.  To access the details
@@ -74,6 +77,9 @@ text-property-search-forward
    ;; No matches at the end of the buffer.
    ((eobp)
     nil)
+   ;; Negative count means search backwards
+   ((and (numberp count) (< count 0))
+    (text-property-search-backward property value predicate not-current (- count)))
    ;; We're standing in the property we're looking for, so find the
    ;; end.
    ((and (text-property--match-p value (get-text-property (point) property)
@@ -83,25 +89,36 @@ text-property-search-forward
    (t
     (let ((origin (point))
           (ended nil)
+          (count (or count 1))
+          (match t)
           pos)
-      ;; Find the next candidate.
+      ;; Find the COUNT-th next candidate.
       (while (not ended)
         (setq pos (next-single-property-change (point) property))
         (if (not pos)
             (progn
               (goto-char origin)
-              (setq ended t))
+              (setq ended match))
           (goto-char pos)
           (if (text-property--match-p value (get-text-property (point) property)
                                       predicate)
-              (setq ended
-                    (text-property--find-end-forward
-                     (point) property value predicate))
+              (progn
+                (setq match (text-property--find-end-forward
+                             (point) property value predicate))
+                (setq origin (point))
+                (cl-decf count)
+                (if (zerop count)
+                    (setq ended match)
+                  (setq pos (next-single-property-change (point) property))
+                  (if pos
+                      (goto-char pos)
+                    (goto-char origin)
+                    (setq ended match))))
             ;; Skip past this section of non-matches.
             (setq pos (next-single-property-change (point) property))
             (unless pos
               (goto-char origin)
-              (setq ended t)))))
+              (setq ended match)))))
       (and (not (eq ended t))
            ended)))))

@@ -133,7 +150,7 @@ text-property--find-end-forward


 (defun text-property-search-backward (property &optional value predicate
-                                               not-current)
+                                               not-current count)
   "Search for the previous region of text whose PROPERTY matches VALUE.

 Like `text-property-search-forward', which see, but searches backward,
@@ -147,6 +164,9 @@ text-property-search-backward
    ;; We're at the start of the buffer; no previous matches.
    ((bobp)
     nil)
+   ;; Negative count means search forwards
+   ((and (numberp count) (< count 0))
+    (text-property-search-forward property value predicate not-current (- count)))
    ;; We're standing in the property we're looking for, so find the
    ;; end.
    ((text-property--match-p
@@ -165,26 +185,37 @@ text-property-search-backward
    (t
     (let ((origin (point))
           (ended nil)
+          (count (or count 1))
+          (match t)
           pos)
       (forward-char -1)
-      ;; Find the previous candidate.
+      ;; Find the COUNT-th previous candidate.
       (while (not ended)
         (setq pos (previous-single-property-change (point) property))
         (if (not pos)
             (progn
               (goto-char origin)
-              (setq ended t))
+              (setq ended match))
           (goto-char (1- pos))
           (if (text-property--match-p value (get-text-property (point) property)
                                       predicate)
-              (setq ended
-                    (text-property--find-end-backward
-                     (point) property value predicate))
+              (progn
+                (setq match (text-property--find-end-backward
+                             (point) property value predicate))
+                (setq origin (point))
+                (cl-decf count)
+                (if (zerop count)
+                    (setq ended match)
+                  (setq pos (previous-single-property-change (point) property))
+                  (if pos
+                      (goto-char pos)
+                    (goto-char origin)
+                    (setq ended match))))
             ;; Skip past this section of non-matches.
             (setq pos (previous-single-property-change (point) property))
             (unless pos
               (goto-char origin)
-              (setq ended t)))))
+              (setq ended match)))))
       (and (not (eq ended t))
            ended)))))

--
2.25.1



             reply	other threads:[~2021-07-30 19:20 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-30 19:20 James N V Cash [this message]
2021-07-30 19:51 ` [PATCH] Add option COUNT argument to text-property-search functions Lars Ingebrigtsen
2021-07-30 19:55   ` James N. V. Cash
2021-07-30 21:56     ` Dmitry Gutov
2021-07-31  6:56       ` Protesilaos Stavrou
2021-07-31 11:36         ` Lars Ingebrigtsen
2021-07-30 19:59 ` Eli Zaretskii
2021-07-30 20:49   ` James Cash

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87im0rlias.fsf@gmail.com \
    --to=james.cash@occasionallycogent.com \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.