ov
ov copied to clipboard
"Empty" overlays are ignored
Hi,
I've noticed that "empty" overlays (i.e. overlays whose beginning and end points are the same) are ignored in functions like ov-next and ov-prev. This seems to be because ov-at is used, which uses overlays-at, which does not return empty overlays. However, overlays-in does return them.
I did some refactoring of ov-next and ov-prev which seems to fix it, but they should be tested further. I also used pcase to simplify the dispatching. Also, the any, property, and property-value functions could be factored out, since they're the same except for which functions they call to get next/previous overlays.
Another issue is that ov-at only returns one overlay even if there are multiple overlays there. This becomes a small problem when other functions are built on top of it. :) This is a deeper problem, though. Probably, there should be sibling functions to these that return all overlays rather than only one.
Please let me know what you think. I can send a PR if you like, but this probably needs a bit more work.
This library is extremely useful, thanks for making it!
(cl-defun ov-prev (&optional point-or-prop prop-or-val (val 'any))
"Get the previous overlay satisfying a condition.
If POINT-OR-PROP is a symbol, get the previous overlay with this
property being non-nil.
If PROP-OR-VAL is non-nil, the property should have this value.
If POINT-OR-PROP is a number, get the previous overlay after this
point.
If PROP-OR-VAL and VAL are also specified, get the previous
overlay after POINT-OR-PROP having property PROP-OR-VAL set to
VAL (with VAL unspecified, only the presence of property is
tested)."
(cl-labels ((any (pos)
(car (overlays-in (previous-overlay-change pos) (previous-overlay-change pos))))
(property (pos property)
(save-excursion
(goto-char pos)
(cl-loop while (and (not (bobp))
(goto-char (previous-overlay-change (point))))
when (cl-loop for ov in (overlays-in (point) (point))
when (plist-get (ov-prop ov) property)
return ov)
return it)))
(property-value (pos property value)
(save-excursion
(goto-char pos)
(cl-loop while (and (not (bobp))
(goto-char (previous-overlay-change (point))))
when (cl-loop for ov in (overlays-in (point) (point))
for ov-value = (plist-get (ov-prop ov) property)
when (equal ov-value value)
return ov)
return it))))
(pcase point-or-prop
((pred numberp) (pcase prop-or-val
(`nil (any point-or-prop))
(_ (pcase val
('any (property point-or-prop prop-or-val))
(_ (property-value point-or-prop prop-or-val val))))))
(`nil (any (point)))
(_ (pcase prop-or-val
(`nil (property (point) point-or-prop))
(_ (pcase val
('any (property (point) point-or-prop))
(_ (property-value point-or-prop prop-or-val val)))))))))
(cl-defun ov-next (&optional point-or-prop prop-or-val (val 'any))
"Get the next overlay satisfying a condition.
If POINT-OR-PROP is a symbol, get the next overlay with this
property being non-nil.
If PROP-OR-VAL is non-nil, the property should have this value.
If POINT-OR-PROP is a number, get the next overlay after this
point.
If PROP-OR-VAL and VAL are also specified, get the next overlay
after POINT-OR-PROP having property PROP-OR-VAL set to VAL (with
VAL unspecified, only the presence of property is tested)."
(cl-labels ((any (pos)
(car (overlays-in (next-overlay-change pos) (next-overlay-change pos))))
(property (pos property)
(save-excursion
(goto-char pos)
(cl-loop while (and (not (bobp))
(goto-char (next-overlay-change (point))))
when (cl-loop for ov in (overlays-in (point) (point))
when (plist-get (ov-prop ov) property)
return ov)
return it)))
(property-value (pos property value)
(save-excursion
(goto-char pos)
(cl-loop while (and (not (bobp))
(goto-char (next-overlay-change (point))))
when (cl-loop for ov in (overlays-in (point) (point))
for ov-value = (plist-get (ov-prop ov) property)
when (equal ov-value value)
return ov)
return it))))
(pcase point-or-prop
((pred numberp) (pcase prop-or-val
(`nil (any point-or-prop))
(_ (pcase val
('any (property point-or-prop prop-or-val))
(_ (property-value point-or-prop prop-or-val val))))))
(`nil (any (point)))
(_ (pcase prop-or-val
(`nil (property (point) point-or-prop))
(_ (pcase val
('any (property (point) point-or-prop))
(_ (property-value point-or-prop prop-or-val val)))))))))
@ShingoFukuyama Ping? :)
I'm OK with this patch. If you want to add it, please just push or send PR (makes more one-work separate clear and makes easy to revert the whole PR if found issues).
IIUC there is a small oversight in the proposed patch (thanks @alphapapa!): In ov-next, use eobp instead of bobp.
@sgleizes Thanks, good catch.
@alphapapa you aren't by any chance interested in maintaining this package? Or any other packages in the orphanage for that matter?