貪欲なlooking-back関数

通常、後方へのびる正規表現マッチでは極力マッチしないようにに動作します。そのため\\sw+などで単語を拾おうとしても最後の一文字だけ拾われてしまいます。looking-back関数の第三引数にはgreedyというオプションが用意されており、これをtにしてやると後方正規表現でも貪欲にマッチしてくれるようになります。

(and (looking-back "\\sw+") (match-string 0)) ; => o
(and (looking-back "\\sw+" nil t) (match-string 0)) ; => hello

looking-back関数の実装は次のようになります。すごいことやってますが気にしない方向で。

(defun looking-back (regexp &optional limit greedy)
  "Return non-nil if text before point matches regular expression REGEXP.
Like `looking-at' except matches before point, and is slower.
LIMIT if non-nil speeds up the search by specifying a minimum
starting position, to avoid checking matches that would start
before LIMIT.

If GREEDY is non-nil, extend the match backwards as far as
possible, stopping when a single additional previous character
cannot be part of a match for REGEXP.  When the match is
extended, its starting position is allowed to occur before
LIMIT."
  (let ((start (point))
	(pos
	 (save-excursion
	   (and (re-search-backward (concat "\\(?:" regexp "\\)\\=") limit t)
		(point)))))
    (if (and greedy pos)
	(save-restriction
	  (narrow-to-region (point-min) start)
	  (while (and (> pos (point-min))
		      (save-excursion
			(goto-char pos)
			(backward-char 1)
			(looking-at (concat "\\(?:"  regexp "\\)\\'"))))
	    (setq pos (1- pos)))
	  (save-excursion
	    (goto-char pos)
	    (looking-at (concat "\\(?:"  regexp "\\)\\'")))))
    (not (null pos))))