emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] scratch/prop-search f83e2ac 2/2: Reimplement backward sear


From: Lars Ingebrigtsen
Subject: [Emacs-diffs] scratch/prop-search f83e2ac 2/2: Reimplement backward searching the hard way
Date: Tue, 17 Apr 2018 12:23:12 -0400 (EDT)

branch: scratch/prop-search
commit f83e2ac1b491bf718741e678afb9c9fe60c1825b
Author: Lars Ingebrigtsen <address@hidden>
Commit: Lars Ingebrigtsen <address@hidden>

    Reimplement backward searching the hard way
---
 lisp/emacs-lisp/text-property-search.el | 82 +++++++++++++++++++++++++++++++--
 1 file changed, 79 insertions(+), 3 deletions(-)

diff --git a/lisp/emacs-lisp/text-property-search.el 
b/lisp/emacs-lisp/text-property-search.el
index 40644dc..9d05aa3 100644
--- a/lisp/emacs-lisp/text-property-search.el
+++ b/lisp/emacs-lisp/text-property-search.el
@@ -63,7 +63,7 @@ value of PROPERTY at the start of the region."
   (if (and (text-property--match-p value (get-text-property (point) property)
                                    predicate)
            (not not-immediate))
-      (text-property--find-end (point) property value predicate)
+      (text-property--find-end-forward (point) property value predicate)
     (let ((origin (point))
           (ended nil)
           pos)
@@ -78,7 +78,8 @@ value of PROPERTY at the start of the region."
           (if (text-property--match-p value (get-text-property (point) 
property)
                                       predicate)
               (setq ended
-                    (text-property--find-end (point) property value predicate))
+                    (text-property--find-end-forward
+                     (point) property value predicate))
             ;; Skip past this section of non-matches.
             (setq pos (next-single-property-change (point) property))
             (unless pos
@@ -87,7 +88,7 @@ value of PROPERTY at the start of the region."
       (and (not (eq ended t))
            ended))))
 
-(defun text-property--find-end (start property value predicate)
+(defun text-property--find-end-forward (start property value predicate)
   (let (end)
     (if (and value
              (null predicate))
@@ -113,6 +114,81 @@ value of PROPERTY at the start of the region."
                      :end end
                      :value (get-text-property start property))))
 
+
+(defun text-property-search-backward (property &optional value predicate
+                                               not-immediate)
+  "Search for the previous region that has text property PROPERTY set to VALUE.
+See `text-property-search-forward' for further documentation."
+  (interactive
+   (list
+    (let ((string (completing-read "Search for property: " obarray)))
+      (when (> (length string) 0)
+        (intern string obarray)))))
+  (cond
+   ;; We're at the start of the buffer; no previous matches.
+   ((bobp)
+    nil)
+   ;; We're standing in the property we're looking for, so find the
+   ;; end.
+   ((and (text-property--match-p
+          value (get-text-property (1- (point)) property)
+          predicate)
+         (not not-immediate))
+    (text-property--find-end-backward (1- (point)) property value predicate))
+   (t
+    (forward-char -1)
+    (let ((origin (point))
+          (ended nil)
+          pos)
+      ;; Fix the next candidate.
+      (while (not ended)
+        (setq pos (previous-single-property-change (point) property))
+        (if (not pos)
+            (progn
+              (goto-char origin)
+              (setq ended t))
+          (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))
+            ;; Skip past this section of non-matches.
+            (setq pos (previous-single-property-change (point) property))
+            (unless pos
+              (goto-char origin)
+              (setq ended t)))))
+      (and (not (eq ended t))
+           ended)))))
+
+(defun text-property--find-end-backward (start property value predicate)
+  (let (end)
+    (if (and value
+             (null predicate))
+        ;; This is the normal case: We're looking for areas where the
+        ;; values aren't, so we aren't interested in sub-areas where the
+        ;; property has different values, all non-matching value.
+        (let ((ended nil))
+          (while (not ended)
+            (setq end (previous-single-property-change (point) property))
+            (if (not end)
+                (progn
+                  (goto-char (point-min))
+                  (setq end (point)
+                        ended t))
+              (goto-char (1- end))
+              (unless (text-property--match-p
+                       value (get-text-property (point) property) predicate)
+                (goto-char end)
+                (setq ended t)))))
+      ;; End this at the first place the property changes value.
+      (setq end (previous-single-property-change
+                 (point) property nil (point-min)))
+      (goto-char end))
+    (make-prop-match :beginning end
+                     :end (1+ start)
+                     :value (get-text-property end property))))
+
 (defun text-property--match-p (value prop-value predicate)
   (cond
    ((eq predicate t)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]