[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: looking-back
From: |
Tom Wurgler |
Subject: |
Re: looking-back |
Date: |
Tue, 17 Jun 2003 16:44:36 -0400 (EDT) |
Recently "Stefan Monnier" <monnier+gnu/emacs/address@hidden> wrote:
Monnier> What is looking-back meant for ?
I use it in an elisp code I wrote to check on a given string (in this case) at
the end of a line. It was easier to do (end-of-line) (if (looking-back "SI")...
than any other way.
Monnier> (defun looking-back (regexp)
Monnier> "Return t if text before point matches regular expression REGEXP.
Monnier> This function modifies the match data that `match-beginning',
Monnier> `match-end' and `match-data' access; save and restore the match
Monnier> data if you want to preserve them."
Monnier> (save-excursion
Monnier> (let ((beg (point)))
Monnier> (if (re-search-backward regexp nil t)
Monnier> (if (= (match-end 0) beg)
Monnier> t
Monnier> nil)
Monnier> nil))))
Monnier> (if foo t nil) can be simplified to `foo', the problem is that
Huh?
Monnier> (progn
Monnier> (insert "hello")
Monnier> (looking-back "hello\\|l"))
Monnier> returns nil.
For me, I wouldn't put an or in this because one wouldn't know which match it
matched. I make a decision in my code depending on what it is. Which doesn't
help because it says REGEXP and therefore should work, I guess. I don't know
how to do it differently unless you write a splitter to search each "or" piece
one at a time.
Monnier> Another problem is that by warning that match-data
Monnier> will be modified, it implicitly says that other functions that don't
Monnier> mention it probably preserve the match-data, whereas the rule is
Monnier> rather that the match-data is usually not preserved, and especially
Monnier> so for functions taking regexps as arguments.
I just scarfed the docs for looking-at. I have no problem leaving that doc off.
Monnier> Finally, `looking-at' is very fast because it just does a regexp-match.
Monnier> On the other hand `looking-back' is a regexp *search* which tends to be
Monnier> orders of magnitude slower and it will typically search all the way
Monnier> to point-min when the search fails, so we want to add a `limit'
Monnier> argument, as is done for re-search-backward.
I guess I don't see a need to compare speeds to looking-at. Of course, that is
built-in code and this isn't. 99% of the time this is lighting fast too.
Monnier> By the way, the only fix I know for the main problem is to do:
Monnier> (defun looking-back (regexp &optional limit)
Monnier> "Return non-nil if text before point matches REGEXP.
Monnier> Contrary to `looking-at', it will return the shortest match and it is
Monnier> typically orders of magnitude slower."
Monnier> (save-excursion
Monnier> (re-search-backward (concat "\\(?:" regexp "\\)\\=") limit t)))
Monnier> This is also the only use I know of for the \= regexp operator.
Well, this seems to work for the hello\\|l case, but see above.
Monnier> Note that when Tom's original code works correctly, it will tend
Monnier> to be faster because it will stop at the first unsuccessful match
Monnier> whereas mine will always search all the way to `limit' before
Monnier> returning nil.
I gotta think about this some more. How to stop it sooner if it doesn't match.
Monnier> The real answer is to write a regexp-engine that matches backward.
Well, this original method works pretty swell most all the time...
thanks
tom