aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS.org2
-rw-r--r--compat-27.el194
-rw-r--r--compat-tests.el58
-rw-r--r--compat.texi93
4 files changed, 4 insertions, 343 deletions
diff --git a/NEWS.org b/NEWS.org
index 7532f7c..6ed9400 100644
--- a/NEWS.org
+++ b/NEWS.org
@@ -5,6 +5,8 @@
- compat-27: Drop obsolete ~compat-call dired-get-marked-files~.
- compat-29: Add ~with-restriction~ and ~without-restriction~.
- compat-29: Drop ~with-narrowing~.
+- compat-27: Drop ~text-property-search-forward~ and ~-backward~. These functions
+ should be provided by a separate ~text-property-search~ ELPA package.
* Release of "Compat" Version 29.1.3.4
diff --git a/compat-27.el b/compat-27.el
index 30aa97c..c39ce52 100644
--- a/compat-27.el
+++ b/compat-27.el
@@ -607,200 +607,6 @@ January 1st being 1."
month (1+ month)))
(list nil nil nil ordinal month year nil nil nil)))
-;;;; Defined in text-property-search.el
-
-(declare-function make-prop-match nil)
-(compat-guard (not (fboundp 'make-prop-match)) ;; <compat-tests:prop-match>
- (cl-defstruct (prop-match) beginning end value))
-
-(compat-defun text-property-search-forward ;; <compat-tests:text-property-search-forward>
- (property &optional value predicate not-current)
- "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.
-
-If PREDICATE is a function, it will be called with two arguments:
-VALUE and the value of PROPERTY. The function should return
-non-nil if these two values are to be considered a match.
-
-Two special values of PREDICATE can also be used:
-If PREDICATE is t, that means a value must `equal' VALUE to be
-considered a match.
-If PREDICATE is nil (which is the default value), a value will
-match if is not `equal' to VALUE. Furthermore, a nil PREDICATE
-means that the match region is ended if the value changes. For
-instance, this means that if you loop with
-
- (while (setq prop (text-property-search-forward \\='face))
- ...)
-
-you will get all distinct regions with non-nil `face' values in
-the buffer, and the `prop' object will have the details about the
-match. See the manual for more details and examples about how
-VALUE and PREDICATE interact.
-
-If NOT-CURRENT is non-nil, the function will search for the first
-region that doesn't include point and has a value of PROPERTY
-that matches VALUE.
-
-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
-of the match, use `prop-match-beginning' and `prop-match-end' for
-the buffer positions that limit the region, and
-`prop-match-value' for the value of PROPERTY in the region."
- (let* ((match-p
- (lambda (prop-value)
- (funcall
- (cond
- ((eq predicate t)
- #'equal)
- ((eq predicate nil)
- (lambda (val p-val)
- (not (equal val p-val))))
- (predicate))
- value prop-value)))
- (find-end
- (lambda (start)
- (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 (next-single-property-change (point) property))
- (if (not end)
- (progn
- (goto-char (point-max))
- (setq end (point)
- ended t))
- (goto-char end)
- (unless (funcall match-p (get-text-property (point) property))
- (setq ended t)))))
- ;; End this at the first place the property changes value.
- (setq end (next-single-property-change (point) property nil (point-max)))
- (goto-char end))
- (make-prop-match
- :beginning start
- :end end
- :value (get-text-property start property))))))
- (cond
- ;; No matches at the end of the buffer.
- ((eobp)
- nil)
- ;; We're standing in the property we're looking for, so find the
- ;; end.
- ((and (funcall match-p (get-text-property (point) property))
- (not not-current))
- (funcall find-end (point)))
- (t
- (let ((origin (point))
- (ended nil)
- pos)
- ;; Find the next candidate.
- (while (not ended)
- (setq pos (next-single-property-change (point) property))
- (if (not pos)
- (progn
- (goto-char origin)
- (setq ended t))
- (goto-char pos)
- (if (funcall match-p (get-text-property (point) property))
- (setq ended (funcall find-end (point)))
- ;; Skip past this section of non-matches.
- (setq pos (next-single-property-change (point) property))
- (unless pos
- (goto-char origin)
- (setq ended t)))))
- (and (not (eq ended t))
- ended))))))
-
-(compat-defun text-property-search-backward ;; <compat-tests:text-property-search-backward>
- (property &optional value predicate not-current)
- "Search for the previous region of text whose PROPERTY matches VALUE.
-
-Like `text-property-search-forward', which see, but searches backward,
-and if a matching region is found, place point at the start of the region."
- (let* ((match-p
- (lambda (prop-value)
- (funcall
- (cond
- ((eq predicate t)
- #'equal)
- ((eq predicate nil)
- (lambda (val p-val)
- (not (equal val p-val))))
- (predicate))
- value prop-value)))
- (find-end
- (lambda (start)
- (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 (funcall match-p (get-text-property (point) property))
- (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))))))
- (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.
- ((funcall match-p (get-text-property (1- (point)) property))
- (let ((origin (point))
- (match (funcall find-end (1- (point)) property value predicate)))
- ;; When we want to ignore the current element, then repeat the
- ;; search if we haven't moved out of it yet.
- (if (and not-current
- (equal (get-text-property (point) property)
- (get-text-property origin property)))
- (text-property-search-backward property value predicate)
- match)))
- (t
- (let ((origin (point))
- (ended nil)
- pos)
- ;; Find the previous 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 (funcall match-p (get-text-property (point) property))
- (setq ended
- (funcall find-end (point)))
- ;; 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))))))
-
;;;; Defined in ring.el
(compat-defun ring-resize (ring size) ;; <compat-tests:ring-resize>
diff --git a/compat-tests.el b/compat-tests.el
index ba6cec4..d18e973 100644
--- a/compat-tests.el
+++ b/compat-tests.el
@@ -55,7 +55,6 @@
(require 'subr-x)
(require 'time-date)
(require 'image)
-(require 'text-property-search nil t)
;; Setup tramp mock
(require 'tramp)
@@ -2380,63 +2379,6 @@
(should-equal (compat-call plist-get plist "one" #'string=) "eins")
(should-equal plist '("one" "eins" "two" 2 "three" 3))))
-(ert-deftest prop-match ()
- (should (prop-match-p (make-prop-match)))
- (should (prop-match-p (make-prop-match :end 1)))
- (should (prop-match-p (make-prop-match :beginning 1 :end 2 :value 3)))
- (should-equal 1 (prop-match-beginning (make-prop-match :beginning 1 :end 2 :value 3)))
- (should-equal 2 (prop-match-end (make-prop-match :beginning 1 :end 2 :value 3)))
- (should-equal 3 (prop-match-value (make-prop-match :beginning 1 :end 2 :value 3)))
- (should-not (prop-match-p nil))
- (should-not (prop-match-p []))
- (should-not (prop-match-p 'symbol))
- (should-not (prop-match-p "string"))
- (should-not (prop-match-p '(1 2 3))))
-
-(ert-deftest text-property-search-forward ()
- (with-temp-buffer
- (insert "one "
- (propertize "two " 'prop 'val)
- "three "
- (propertize "four " 'prop 'wert)
- "five ")
- (goto-char (point-min))
- (let ((match (text-property-search-forward 'prop)))
- (should (prop-match-p match))
- (should-equal (prop-match-beginning match) 5)
- (should-equal (prop-match-end match) 9)
- (should-equal (prop-match-value match) 'val))
- (let ((match (text-property-search-forward 'prop)))
- (should (prop-match-p match))
- (should-equal (prop-match-beginning match) 15)
- (should-equal (prop-match-end match) 20)
- (should-equal (prop-match-value match) 'wert))
- (should-not (text-property-search-forward 'prop))
- (goto-char (point-min))
- (should-not (text-property-search-forward 'non-existant))))
-
-(ert-deftest text-property-search-backward ()
- (with-temp-buffer
- (insert "one "
- (propertize "two " 'prop 'val)
- "three "
- (propertize "four " 'prop 'wert)
- "five ")
- (goto-char (point-max))
- (let ((match (text-property-search-backward 'prop)))
- (should (prop-match-p match))
- (should-equal (prop-match-beginning match) 15)
- (should-equal (prop-match-end match) 20)
- (should-equal (prop-match-value match) 'wert))
- (let ((match (text-property-search-backward 'prop)))
- (should (prop-match-p match))
- (should-equal (prop-match-beginning match) 5)
- (should-equal (prop-match-end match) 9)
- (should-equal (prop-match-value match) 'val))
- (should-not (text-property-search-backward 'prop))
- (goto-char (point-max))
- (should-not (text-property-search-backward 'non-existant))))
-
(ert-deftest color-dark-p ()
(should (color-dark-p '(0 0 0)))
(should (color-dark-p '(0.5 0.5 0.5)))
diff --git a/compat.texi b/compat.texi
index 521ca11..c64565e 100644
--- a/compat.texi
+++ b/compat.texi
@@ -1424,97 +1424,6 @@ This function creates an empty file named @var{filename}. As
function signals an error.
@end defun
-@defun text-property-search-forward prop &optional value predicate not-current
-Search for the next region that has text property @var{prop} set to
-@var{value} according to @var{predicate}.
-
-This function is modeled after @code{search-forward} and friends in
-that it moves point, but it returns a structure that describes the
-match instead of returning it in @code{match-beginning} and friends.
-
-If the text property can't be found, the function returns @code{nil}.
-If it's found, point is placed at the end of the region that has this
-text property match, and a @code{prop-match} structure is returned.
-
-@var{predicate} can either be @code{t} (which is a synonym for
-@code{equal}), @code{nil} (which means ``not equal''), or a predicate
-that will be called with two parameters: The first is @var{value}, and
-the second is the value of the text property we're inspecting.
-
-If @var{not-current}, if point is in a region where we have a match,
-then skip past that and find the next instance instead.
-
-The @code{prop-match} structure has the following accessors:
-@code{prop-match-beginning} (the start of the match),
-@code{prop-match-end} (the end of the match), and
-@code{prop-match-value} (the value of @var{property} at the start of
-the match).
-
-In the examples below, imagine that you're in a buffer that looks like
-this:
-
-@example
-This is a bold and here's bolditalic and this is the end.
-@end example
-
-That is, the ``bold'' words are the @code{bold} face, and the
-``italic'' word is in the @code{italic} face.
-
-With point at the start:
-
-@lisp
-(while (setq match (text-property-search-forward 'face 'bold t))
- (push (buffer-substring (prop-match-beginning match)
- (prop-match-end match))
- words))
-@end lisp
-
-This will pick out all the words that use the @code{bold} face.
-
-@lisp
-(while (setq match (text-property-search-forward 'face nil t))
- (push (buffer-substring (prop-match-beginning match)
- (prop-match-end match))
- words))
-@end lisp
-
-This will pick out all the bits that have no face properties, which
-will result in the list @samp{("This is a " "and here's " "and this is
-the end")} (only reversed, since we used @code{push}).
-
-@lisp
-(while (setq match (text-property-search-forward 'face nil nil))
- (push (buffer-substring (prop-match-beginning match)
- (prop-match-end match))
- words))
-@end lisp
-
-This will pick out all the regions where @code{face} is set to
-something, but this is split up into where the properties change, so
-the result here will be @samp{("bold" "bold" "italic")}.
-
-For a more realistic example where you might use this, consider that
-you have a buffer where certain sections represent URLs, and these are
-tagged with @code{shr-url}.
-
-@lisp
-(while (setq match (text-property-search-forward 'shr-url nil nil))
- (push (prop-match-value match) urls))
-@end lisp
-
-This will give you a list of all those URLs.
-
-@xref{elisp,,,Property Search}.
-@end defun
-
-@defun text-property-search-backward prop &optional value predicate not-current
-This is just like @code{text-property-search-forward}, but searches
-backward instead. Point is placed at the beginning of the matched
-region instead of the end, though.
-
-@xref{elisp,,,Property Search}.
-@end defun
-
@subsection Extended Definitions
These functions must be called explicitly via @code{compat-call},
since their calling convention or behavior was extended in Emacs 27.1:
@@ -1673,6 +1582,8 @@ The @code{iso8601} library.
@item
The @code{exif} library.
@item
+The @code{text-property-search} library.
+@item
The @code{image-converter} library.
@end itemize