I am looking for something like thing-at-point
for a regexp. For example, I want a function called regexp-at-point-p
that will return the matched text if the text around the point matches the regexp with a looking back bound of the beginning of the current line. This seems tricky. I can't easily use re-search-backward, because it won't return a full match, it only matches up to the current point, and it doesn't always match a complicated regexp.
Here are the two regexps I tested for a #hashtag
simple regex: #[a-zA-Z]+
complicated regex: \(?:^\|[[:blank:]]\|[](),.:;[{}]\)#\{1\}\(?1:[^#[:digit:]]\(?:[^ #+[:punct:][:space:]]+[-_]?\)+\)\(?:[[:blank:]]\|$\|[[:punct:]]\)
with the point inside the #hashtag, I would expect regexp-at-point-p should return "#hashtag" for both of these regexps.
My current solution is this. It does not match multiline expressions before the current line, which is fine for me, but it works on both regexps above.
(defun regexp-at-point-p (regexp)
"Return match if the text around point matches REGEXP."
(save-excursion
(let ((p (point))
(lbp (line-beginning-position))
(match))
(while (and (not (setq match (looking-at regexp)))
(>= (point) lbp))
(backward-char))
(when (and match
(>= p (match-beginning 0))
(<= p (match-end 0)))
(message (match-string 0))))))
It works, but it doesn't seem like the right way to do this. I tried an alternate version that would go to the beginning of the line and use re-search-forward, but it had a similar form.
This version seems like it should work (and it does for the simple regexp, but not for the complicated one). A similar approach with looking-back
has the same limitation.
(defun regexp-at-point-p (regexp)
"Return match if the text around point matches REGEXP."
(save-excursion
(let* ((p (point))
(lbp (line-beginning-position))
(match (re-search-backward regexp lbp t 1)))
(when match
;; re-search-backward can give partial matches up to point. This sets
;; match data to the whole pattern.
(looking-at regexp))
(when (and (>= p (match-beginning 0))
(<= p (match-end 0)))
(message (match-string 0))))))
Is there a more canonical way to do this? or is this just not a good way to check if point is on a regexp?