Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.4 required=4.0 tests=AWL,MURPHY_SEX_L2 autolearn=no
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 17:04:47 +0000
Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CH4i7b023531
for <192 <at> emacsbugs.donarmstrong.com>; Mon, 12 May 2008 10:04:45 -0700
Received: from localhost (unknown [127.0.0.1])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id D0DDE283C5;
Mon, 12 May 2008 17:04:43 +0000 (UTC)
X-Virus-Scanned: amavisd-new at ece.lsu.edu
Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1])
by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id AMet342Tmzkl; Mon, 12 May 2008 12:04:43 -0500 (CDT)
Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 204C7283C0;
Mon, 12 May 2008 12:04:43 -0500 (CDT)
From: David Koppelman <koppel <at> ece.lsu.edu>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: martin rudalics <rudalics <at> gmx.at>, Chong Yidong <cyd <at> stupidchicken.com>,
192 <at> debbugs.gnu.org, Bruno Haible <bruno <at> clisp.org>,
emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
<yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at>
<87abiwoqzd.fsf <at> stupidchicken.com>
<yg57ie0df8u.fsf <at> nested.ece.lsu.edu>
<jwv4p94r8vp.fsf-monnier+emacsbugreports <at> gnu.org>
<yg5tzh4bqtw.fsf <at> nested.ece.lsu.edu>
<jwvr6c8pbd6.fsf-monnier+emacsbugreports <at> gnu.org>
<yg5d4nra7jb.fsf <at> nested.ece.lsu.edu>
<jwvzlqvmr6g.fsf-monnier+emacsbugreports <at> gnu.org>
Date: Mon, 12 May 2008 12:04:43 -0500
In-Reply-To: <jwvzlqvmr6g.fsf-monnier+emacsbugreports <at> gnu.org> (Stefan
Monnier's message of "Mon, 12 May 2008 12:29:01 -0400")
Message-ID: <yg5od7b8ndg.fsf <at> nested.ece.lsu.edu>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
> a multiline region spanning 0..400. Before fontifying, you need
> to unfontify. The region 100..200 can be completely unfontified, but
Hadn't thought about that. I don't want things to get too elaborate but
it would be nice to have guaranteed behavior below some multi-line size
and not risk slow behavior.
One possibility is to retain the code as it is, except have
extend-region-multiline extend to some maximum size (say, 100 lines)
with the expectation that the larger region would be used for deferred
fontification (I guess jit-lock does that). The only difference with
current operation is that the font-lock-multiline property is ignored
both ensuring proper matches (when the property is not present but a
pattern would match) and avoiding huge sized regions.
Now, if we wanted really large multi-line matches we could unfontify the
larger region but use a window+margin sized region (accounting for all
buffers visiting the file) for the regular patterns and then mark the
other parts of the larger region as unfontified. This would force
re-applying the multi-line patterns on buffer motion, though
we could cache the match data to avoid re-seaching.
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>> I'm proposing that font-lock divide keywords into two or three
>> classes, ordinary, multi-line, and maybe mega-line, matches for
>> multi-line and mega-line keywords would be over much larger
>> regions. Here is how it might work with two classes (keep in mind that
>> I don't yet have a thorough understanding of font-lock and jit-lock):
>
> I do not understand how you propose to solve the main problem:
> Let's say you want to fontify a line spanning chars 100..200 and
> a multiline region spanning 0..400. Before fontifying, you need
> to unfontify. The region 100..200 can be completely unfontified, but
> what about 0..99 and 201..400? You can't unfontify them completely
> since you don't want to refontify them completely either, so you'd need
> to figure out which part of the fontification comes from the
> multiline keywords.
>
> Also, the order between keywords is important, so unless you force all
> multiline keywords to go at the very end, you'd also need to remove (on
> the 0..99 and 201..400 regions) the fontification coming from small
> keywords that were placed after multiline keywords and reapply
> it afterwards?
>
>
> Stefan
David Koppelman <koppel <at> ece.lsu.edu>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.4 required=4.0 tests=AWL,MURPHY_SEX_L2 autolearn=no
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 16:29:11 +0000
Received: from ironport2-out.teksavvy.com (ironport2-out.pppoe.ca [206.248.154.182])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CGT7Pe018635
for <192 <at> emacsbugs.donarmstrong.com>; Mon, 12 May 2008 09:29:09 -0700
X-IronPort-Anti-Spam-Filtered: true
X-IronPort-Anti-Spam-Result: AocDACoNKEjO+JgrdGdsb2JhbACBU5A7ASeYRA
X-IronPort-AV: E=Sophos;i="4.27,474,1204520400";
d="scan'208";a="20421324"
Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238])
by ironport2-out.teksavvy.com with ESMTP; 12 May 2008 12:29:02 -0400
Received: from pastel.home ([206.248.152.43])
by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id SVP40602;
Mon, 12 May 2008 12:29:02 -0400
Received: by pastel.home (Postfix, from userid 20848)
id D415C801D; Mon, 12 May 2008 12:29:01 -0400 (EDT)
From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: David Koppelman <koppel <at> ece.lsu.edu>
Cc: martin rudalics <rudalics <at> gmx.at>, Chong Yidong <cyd <at> stupidchicken.com>,
192 <at> debbugs.gnu.org, Bruno Haible <bruno <at> clisp.org>,
emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
Message-ID: <jwvzlqvmr6g.fsf-monnier+emacsbugreports <at> gnu.org>
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
<yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at>
<87abiwoqzd.fsf <at> stupidchicken.com>
<yg57ie0df8u.fsf <at> nested.ece.lsu.edu>
<jwv4p94r8vp.fsf-monnier+emacsbugreports <at> gnu.org>
<yg5tzh4bqtw.fsf <at> nested.ece.lsu.edu>
<jwvr6c8pbd6.fsf-monnier+emacsbugreports <at> gnu.org>
<yg5d4nra7jb.fsf <at> nested.ece.lsu.edu>
Date: Mon, 12 May 2008 12:29:01 -0400
In-Reply-To: <yg5d4nra7jb.fsf <at> nested.ece.lsu.edu> (David Koppelman's message
of "Mon, 12 May 2008 10:03:52 -0500")
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
> I'm proposing that font-lock divide keywords into two or three
> classes, ordinary, multi-line, and maybe mega-line, matches for
> multi-line and mega-line keywords would be over much larger
> regions. Here is how it might work with two classes (keep in mind that
> I don't yet have a thorough understanding of font-lock and jit-lock):
I do not understand how you propose to solve the main problem:
Let's say you want to fontify a line spanning chars 100..200 and
a multiline region spanning 0..400. Before fontifying, you need
to unfontify. The region 100..200 can be completely unfontified, but
what about 0..99 and 201..400? You can't unfontify them completely
since you don't want to refontify them completely either, so you'd need
to figure out which part of the fontification comes from the
multiline keywords.
Also, the order between keywords is important, so unless you force all
multiline keywords to go at the very end, you'd also need to remove (on
the 0..99 and 201..400 regions) the fontification coming from small
keywords that were placed after multiline keywords and reapply
it afterwards?
Stefan
Stefan Monnier <monnier <at> iro.umontreal.ca>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.2 required=4.0 tests=FVGT_m_MULTI_ODD,
MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 16:22:34 +0000
Received: from www.elogos.de (alextrapp1.equinoxe.de [217.22.192.104])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CGMUj1017885
for <192 <at> emacsbugs.donarmstrong.com>; Mon, 12 May 2008 09:22:31 -0700
Received: by www.elogos.de (Postfix, from userid 4000)
id E54234B635; Mon, 12 May 2008 16:18:43 +0000 (UTC)
Date: Mon, 12 May 2008 16:18:43 +0000
To: Thomas Lord <lord <at> emf.net>
Cc: Stefan Monnier <monnier <at> iro.umontreal.ca>,
Chong Yidong <cyd <at> stupidchicken.com>, 192 <at> debbugs.gnu.org,
emacs-devel <at> gnu.org, martin rudalics <rudalics <at> gmx.at>,
David Koppelman <koppel <at> ece.lsu.edu>, Bruno Haible <bruno <at> clisp.org>
Subject: Re: regexp does not work as documented
Message-ID: <20080512161843.GA15407 <at> www.trapp.net>
References: <yg5skwqc6ho.fsf <at> nested.ece.lsu.edu> <yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at> <87abiwoqzd.fsf <at> stupidchicken.com> <jwv8wygrbss.fsf-monnier+emacsbugreports <at> gnu.org> <482750F4.2050102 <at> emf.net> <jwvlk2gpas3.fsf-monnier+emacsbugreports <at> gnu.org> <4827B9B8.30406 <at> emf.net> <jwvfxsnpryp.fsf-monnier+emacsbugreports <at> gnu.org> <48286862.6040105 <at> emf.net>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8; x-action=pgp-signed
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
In-Reply-To: <48286862.6040105 <at> emf.net>
User-Agent: Mutt/1.5.9i
From: tomas <at> tuxteam.de
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On Mon, May 12, 2008 at 08:55:14AM -0700, Thomas Lord wrote:
[...]
> Why that last one? Because then you can probably use the same
> DFA engine as the heart of a shift-reduce parser and (for languages
> that admit such things) write an incremental parser. (You'd be using
> non-buffer-position DFAs to process token ids emitted by the lexer.)
> You can also use such a feature for things like serial I/O protocols.
...and cool things could be done with process-filter-function and its
cousin after-insert-file-functions (i.e. parse input on-the-fly). Nifty
stuff.
Regards
- -- tomás
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
iD8DBQFIKG3jBcgs9XrR2kYRAtv8AJ9uj1wEjjT4bIPNQxYoYY5iPJW8cwCdE87U
vsVarzdJhCu143kN7OGWh/Q=
=0dcf
-----END PGP SIGNATURE-----
tomas <at> tuxteam.de:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.4 required=4.0 tests=AWL,SPF_HELO_PASS
autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 15:12:07 +0000
Received: from mail.42inc.com (mail.42inc.com [205.149.0.25])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CFC309007163
for <192 <at> emacsbugs.donarmstrong.com>; Mon, 12 May 2008 08:12:05 -0700
X-TFF-CGPSA-Version: 1.5
X-TFF-CGPSA-Filter-42inc: Scanned
X-42-Virus-Scanned: by 42 Antivirus -- Found to be clean.
Received: from [69.236.114.9] (account lord <at> emf.net HELO [192.168.1.64])
by mail.42inc.com (CommuniGate Pro SMTP 5.0.13)
with ESMTPA id 30343388; Mon, 12 May 2008 08:12:02 -0700
Message-ID: <48286862.6040105 <at> emf.net>
Date: Mon, 12 May 2008 08:55:14 -0700
From: Thomas Lord <lord <at> emf.net>
User-Agent: Thunderbird 1.5.0.5 (X11/20060808)
MIME-Version: 1.0
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
CC: Chong Yidong <cyd <at> stupidchicken.com>, 192 <at> debbugs.gnu.org,
emacs-devel <at> gnu.org, martin rudalics <rudalics <at> gmx.at>,
David Koppelman <koppel <at> ece.lsu.edu>, Bruno Haible <bruno <at> clisp.org>
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com> <200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at> <yg5skwqc6ho.fsf <at> nested.ece.lsu.edu> <yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at> <87abiwoqzd.fsf <at> stupidchicken.com> <jwv8wygrbss.fsf-monnier+emacsbugreports <at> gnu.org> <482750F4.2050102 <at> emf.net> <jwvlk2gpas3.fsf-monnier+emacsbugreports <at> gnu.org> <4827B9B8.30406 <at> emf.net> <jwvfxsnpryp.fsf-monnier+emacsbugreports <at> gnu.org>
In-Reply-To: <jwvfxsnpryp.fsf-monnier+emacsbugreports <at> gnu.org>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Stefan Monnier wrote:
> That's what I do in lex.el.
>
>
Sounds nice.
Last bits of experience report, then:
If it isn't so already, it may be easy to make it so
that a choice of which DFA is being used, plus a choice of the
"current state" can be represented as lisp objects and cheaply
copied. That gives the essence of "regular expression continuations".
Handy features that shouldn't be difficult to add (if not present):
Let programmers specify "labels" for each NFA state and then,
for each DFA state, have either a list of all NFA labels that
correspond to that DFA state and/or a more general way to
"combine" NFA state labels to make the DFA label. You can
wind up with many NFA states combined to a single DFA state,
of course, so a "combine" function might be important.
Include scanning functions to:
~ advance the DFA at most N characters (or until failure)
~ advance the DFA to the next non-nil state label (or failure)
In both cases, give a way for lisp programs to get back not only
the label (or failure indication) but also the regular expression
continuation.
Those features are handy so that (for example) lisp programs can
hang a suspended regexp continuation on a buffer character as
a property, doing incremental "re-lexing" in application-specific
ways.
The "advance to non-nil label" feature is useful for writing lisp
programs that *do not* need back-referencing or sub-exp locations
per se.
It is a bit more speculative but also consider functions to:
~ advance the state of a DFA based on characters provided
in a function call rather than read from a buffer -- e.g., a
buffer position should not have to be part of the state of a
running DFA.
(advance-dfa re-continuation chr) => re-continuation
Why that last one? Because then you can probably use the same
DFA engine as the heart of a shift-reduce parser and (for languages
that admit such things) write an incremental parser. (You'd be using
non-buffer-position DFAs to process token ids emitted by the lexer.)
You can also use such a feature for things like serial I/O protocols.
Incremental parsers open the door to robust "syntax directed editing"
which I think could be an exciting direction for IDE features to take.
(Years ago, Thomas Reps and Tim Teitelbaum worked on the "Synthesizer
Generator" which I recall had features along these lines (their parser
guts were probably different from what I suggest). As I (now vaguely)
recall there is a book that talks about their Emacs-based implementation.)
Bye. Thanks. And good luck!
-t
Thomas Lord <lord <at> emf.net>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.5 required=4.0 tests=AWL,MURPHY_SEX_L2 autolearn=no
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 15:03:57 +0000
Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CF3rK6004972
for <192 <at> emacsbugs.donarmstrong.com>; Mon, 12 May 2008 08:03:54 -0700
Received: from localhost (unknown [127.0.0.1])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 47536283CA;
Mon, 12 May 2008 15:03:53 +0000 (UTC)
X-Virus-Scanned: amavisd-new at ece.lsu.edu
Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1])
by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id EhHBp4hL8c4p; Mon, 12 May 2008 10:03:52 -0500 (CDT)
Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 741F6283C6;
Mon, 12 May 2008 10:03:52 -0500 (CDT)
From: David Koppelman <koppel <at> ece.lsu.edu>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: martin rudalics <rudalics <at> gmx.at>, Chong Yidong <cyd <at> stupidchicken.com>,
192 <at> debbugs.gnu.org, Bruno Haible <bruno <at> clisp.org>,
emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
<yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at>
<87abiwoqzd.fsf <at> stupidchicken.com>
<yg57ie0df8u.fsf <at> nested.ece.lsu.edu>
<jwv4p94r8vp.fsf-monnier+emacsbugreports <at> gnu.org>
<yg5tzh4bqtw.fsf <at> nested.ece.lsu.edu>
<jwvr6c8pbd6.fsf-monnier+emacsbugreports <at> gnu.org>
Date: Mon, 12 May 2008 10:03:52 -0500
In-Reply-To: <jwvr6c8pbd6.fsf-monnier+emacsbugreports <at> gnu.org> (Stefan
Monnier's message of "Sun, 11 May 2008 21:28:18 -0400")
Message-ID: <yg5d4nra7jb.fsf <at> nested.ece.lsu.edu>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
> I guess I simply do not understand what you propose. Any improvement in
> the multiline handling is welcome, but beware: this is not an easy area.
I'm proposing that font-lock divide keywords into two or three
classes, ordinary, multi-line, and maybe mega-line, matches for
multi-line and mega-line keywords would be over much larger
regions. Here is how it might work with two classes (keep in mind that
I don't yet have a thorough understanding of font-lock and jit-lock):
Multi-line keywords are explicitly identified as such, perhaps
through keyword syntax or the way they are given to font-lock (say,
using font-lock-multiline-keywords). Explicit identification avoids
performance problems from keywords that, though technically
multi-line, rarely span more than a few lines.
Functions such as font-lock-default-fontify-region would find two
sets of extended regions, ordinary and multi, running functions on
two hooks for this purpose. The multi-line hook might extend the
region based on the size of the largest supported match rather than
using the multline property. The multiline property might still be
useful for non-deferred handling of existing matches.
Functions such as font-lock-fontify-keywords-region would be passed
both extended regions and use the region appropriate for each
keyword they process. The large region is only used on the few
multi-line patterns that need it.
Here I'm assuming that a mode might have hundreds of single-line (or
two-line) keywords and only a few multi-line keywords, and the
multi-line keywords might span no more than hundreds of lines. We
could guarantee that matches for such patterns are perfect (using a
line-count-limit variable).
If there were a third class, mega-line, it would have its own text
property and region-extension hook.
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>> A better solution would be to have font-lock use multi-line extended
>> regions selectively. Perhaps a hint in the current keyword syntax
>> (say, explicitly applying the font-lock-multiline property), or a
>> separate method for providing multi-line keywords to font-lock.
>
> I don't understand the difference between the above and the application
> of font-lock-multiline properties which you seem to have tried and rejected.
>
> I don't necessarily disagree with your rejection of font-lock-multiline:
> it can have disastrous effect indeed if the multiline region becomes large.
>
>> Such keywords would get the multi-line extended regions, the other
>> just the whole-line extensions (or whatever the hooks do).
>> Is this something the font-lock maintainers would consider?
>
> I guess I simply do not understand what you propose. Any improvement in
> the multiline handling is welcome, but beware: this is not an easy area.
>
David Koppelman <koppel <at> ece.lsu.edu>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.4 required=4.0 tests=AWL autolearn=ham
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 13:44:00 +0000
Received: from ironport2-out.teksavvy.com (ironport2-out.pppoe.ca [206.248.154.182])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4CDhuds024956
for <192 <at> emacsbugs.donarmstrong.com>; Mon, 12 May 2008 06:43:57 -0700
X-IronPort-Anti-Spam-Filtered: true
X-IronPort-Anti-Spam-Result: AocDAH/mJ0jO+JgrdGdsb2JhbACBU5A7ASeYEg
X-IronPort-AV: E=Sophos;i="4.27,473,1204520400";
d="scan'208";a="20407483"
Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238])
by ironport2-out.teksavvy.com with ESMTP; 12 May 2008 09:43:50 -0400
Received: from pastel.home ([206.248.152.43])
by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id SSD44550;
Mon, 12 May 2008 09:43:50 -0400
Received: by pastel.home (Postfix, from userid 20848)
id D59D37F83; Mon, 12 May 2008 09:43:49 -0400 (EDT)
From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Thomas Lord <lord <at> emf.net>
Cc: Chong Yidong <cyd <at> stupidchicken.com>, martin rudalics <rudalics <at> gmx.at>,
David Koppelman <koppel <at> ece.lsu.edu>, 192 <at> debbugs.gnu.org,
Bruno Haible <bruno <at> clisp.org>, emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
Message-ID: <jwvfxsnpryp.fsf-monnier+emacsbugreports <at> gnu.org>
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
<yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at>
<87abiwoqzd.fsf <at> stupidchicken.com>
<jwv8wygrbss.fsf-monnier+emacsbugreports <at> gnu.org>
<482750F4.2050102 <at> emf.net>
<jwvlk2gpas3.fsf-monnier+emacsbugreports <at> gnu.org>
<4827B9B8.30406 <at> emf.net>
Date: Mon, 12 May 2008 09:43:49 -0400
In-Reply-To: <4827B9B8.30406 <at> emf.net> (Thomas Lord's message of "Sun, 11 May
2008 20:30:00 -0700")
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
> years ago, is to consider *offline* DFA conversion (a la 'lex(1)').
That's what I do in lex.el.
> The advantage of offline (batch) conversion is that you can burn a lot
> of cycles on DFA minimization and, if your offline converter
> terminates, you've got a reliably linear matcher. The disadvantages
> for *many* uses of regular expressions in Emacs should be pretty
> obvious. For something like font-lock, where the regular expressions
> don't change that often, that might be a good approach -- precompile
> a minimal DFA and then add support for "regular expression
> continuations" when using those tables.
I do not intend to replace src/regexp.c with a matcher based on offline
DFA conversion. Actually, the need to support backrefs makes it pretty
much impossible (tho I'm sure there's a way to adapt an offline DFA so
it can be used with backrefs), and most importantly it has too different
performance characteristics. More specifically, the compilation step
should be made explicit.
In any case I think you did answer my question: an offline DFA matcher
is fine, the worst case is not that common and can be worked around.
This is not that different from the current backtracking matcher.
Stefan
PS: The original motivation for a DFA-matcher is to extend syntax-tables
so they can match match multi-char elements.
Stefan Monnier <monnier <at> iro.umontreal.ca>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.8 required=4.0 tests=AWL,SPF_HELO_PASS
autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 02:46:55 +0000
Received: from mail.42inc.com (mail.42inc.com [205.149.0.25])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4C2kpBt022748
for <192 <at> emacsbugs.donarmstrong.com>; Sun, 11 May 2008 19:46:52 -0700
X-TFF-CGPSA-Version: 1.5
X-TFF-CGPSA-Filter-42inc: Scanned
X-42-Virus-Scanned: by 42 Antivirus -- Found to be clean.
Received: from [69.236.114.9] (account lord <at> emf.net HELO [192.168.1.64])
by mail.42inc.com (CommuniGate Pro SMTP 5.0.13)
with ESMTPA id 30307698; Sun, 11 May 2008 19:46:49 -0700
Message-ID: <4827B9B8.30406 <at> emf.net>
Date: Sun, 11 May 2008 20:30:00 -0700
From: Thomas Lord <lord <at> emf.net>
User-Agent: Thunderbird 1.5.0.5 (X11/20060808)
MIME-Version: 1.0
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
CC: Chong Yidong <cyd <at> stupidchicken.com>, martin rudalics <rudalics <at> gmx.at>,
David Koppelman <koppel <at> ece.lsu.edu>, 192 <at> debbugs.gnu.org,
Bruno Haible <bruno <at> clisp.org>, emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com> <200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at> <yg5skwqc6ho.fsf <at> nested.ece.lsu.edu> <yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at> <87abiwoqzd.fsf <at> stupidchicken.com> <jwv8wygrbss.fsf-monnier+emacsbugreports <at> gnu.org> <482750F4.2050102 <at> emf.net> <jwvlk2gpas3.fsf-monnier+emacsbugreports <at> gnu.org>
In-Reply-To: <jwvlk2gpas3.fsf-monnier+emacsbugreports <at> gnu.org>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Stefan Monnier wrote:
> I have most of the DFA construction code written, but I may take you up
> on that anyway. BTW, regarding the "very expensive in the worst case",
> how common is this worst case in real life?
>
Talking about general purpose use of an engine, as opposed to something
more narrow like "likely font-lock expressions":
It's common enough in "real life" (in my experience) to be exactly the
minimal amount required to make it annoying.
Let me give you some rules of thumb to describe what I mean but I'll
refrain from a long treatise explaining the theory that supports these.
If you have questions I can "unpack" this on list or off.
First, be careful to make a clear distinction between (let's dub the
distinction) "regexps vs. regular expressions". "Regular expressions"
correspond to formally regular languages. Regular expressions can
always be converted to a DFA. "regexps" are what most people use
in most situations. regexps include things like features to extract the
positions that match a sub-pattern. regexps do *not* correspond to
regular languages and *can not* always be converted to DFA. DFA
conversion can help with regexp matching, but it can't solve it completely.
Moreover, you can make pathological regexps (very slow to match) for
every regexp I know of. Henry Spencer (I've heard) asserts that regexps
are NP complete or something around there, though I haven't seen the
proof. (Rx is a hybrid regular expression and regexp engine based on an
on-line (caching, incremental) DFA conversion suggested in the "Dragon"
compiler book and originating from (as I recall) an experiment by
Thompson and one of the other Bell Labs guys. One of whoever it was
privately mentioned that they abandoned it themselves because it was taking
too much code to implement, or something like that.)
That aside, regular expressions are probably plenty for font-lock
functionality,
so let's just talk about those. On-line DFA conversion for those is
likely
practical by multiple means.
The size of a DFA is, worst-case, exponential in the size of the regular
expression.
This is the source of pathological cases that can thwart any DFA
engine. (In exponential
cases, Rx keeps running but more like an NFA, taking a corresponding
performance hit.)
For a time, I was pushing hard on Rx, trying to use it for absolutely
everything.
To make up new problems to solve as in "Ok, let's suppose I can run
X-Kbyte long
regular expressions with lots of | operators, stars, etc. What can I
apply that to?"
One example is lexing for real-world computer languages.
[Aside: you can also use the same engine as the core of a shift-reduce
parser, of course -- and I
did that a long time ago with Guile, to useful effect.]
Almost always, the expressions were such that Rx would have no problem
and give
very pleasing results. However, there were definitely times (for huge
regular expressions
and smaller ones) when things would just absolutely crawl. They happen
"just often
enough" to be an annoyance.
Now, every case of that annoyance that I found (in real-life
applications) had a solution.
I could think for a while on *why* the regular expression I wrote was
blowing up and
then think of a different approach that eliminated the problem. Most
often that
meant not a different but equivalent regular expression -- it meant
going one level up and
changing the way the caller used regular expressions. The caller would
retain the same
functionality but different demands would be made on the regular
expression (or regexp) engine.
And that makes it tricky to drop *blindly* into Emacs. To solve the
unavoidable annoying cases
you really had to know how regular expressions worked at a deep level.
To diagnose
and work around the pathological cases took some expertise.
As a general rule, for something "general purpose" like a libc
implementation or the
default regexp functions in Emacs lisp, there is something to be said
for using NFA matchers.
It's perverse why:
Vast swaths of things that a DFA matcher can do very quickly an NFA
matcher can not.
It's reliably slow. Therefore, people not prepared to think hard about
regexps tend to use
an NFA matcher in pretty limited ways. A powerful regular expression
engine could
simplify their code, at the cost of risking finding a "hard case" -- but
there's no issue since
people quickly give up and don't try to push the match engine that hard.
More concisely:
If you use a DFA matcher You Better Know What You're Doing but also
Most of the Time You Won't Need To So It's Very Convenient.
If you use an NFA matcher You Can Get Away With Not Really Knowing What
You're Doing but also You Won't Be Trying Anything Fancy, Perhaps Losing
Out.
One approach to toss into the mix, this one suggested by Per Bothner
years ago,
is to consider *offline* DFA conversion (a la 'lex(1)'). The
advantage of offline
(batch) conversion is that you can burn a lot of cycles on DFA
minimization and,
if your offline converter terminates, you've got a reliably linear
matcher. The
disadvantages for *many* uses of regular expressions in Emacs should be
pretty obvious.
For something like font-lock, where the regular expressions don't change
that often,
that might be a good approach -- precompile a minimal DFA and then add
support
for "regular expression continuations" when using those tables.
-t
Thomas Lord <lord <at> emf.net>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.4 required=4.0 tests=AWL autolearn=ham
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 01:43:57 +0000
Received: from ironport2-out.teksavvy.com (ironport2-out.teksavvy.com [206.248.154.182])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4C1hrQg012959
for <192 <at> emacsbugs.donarmstrong.com>; Sun, 11 May 2008 18:43:54 -0700
X-IronPort-Anti-Spam-Filtered: true
X-IronPort-Anti-Spam-Result: AmoCAIM9J0jO+JgrdGdsb2JhbACBU5A6ASeXEA
X-IronPort-AV: E=Sophos;i="4.27,470,1204520400";
d="scan'208";a="20309136"
Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238])
by ironport2-out.teksavvy.com with ESMTP; 11 May 2008 21:43:48 -0400
Received: from pastel.home ([206.248.152.43])
by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id SGD37548;
Sun, 11 May 2008 21:43:48 -0400
Received: by pastel.home (Postfix, from userid 20848)
id E689E7F83; Sun, 11 May 2008 21:43:47 -0400 (EDT)
From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Thomas Lord <lord <at> emf.net>
Cc: Chong Yidong <cyd <at> stupidchicken.com>, martin rudalics <rudalics <at> gmx.at>,
David Koppelman <koppel <at> ece.lsu.edu>, 192 <at> debbugs.gnu.org,
Bruno Haible <bruno <at> clisp.org>, emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
Message-ID: <jwvlk2gpas3.fsf-monnier+emacsbugreports <at> gnu.org>
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
<yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at>
<87abiwoqzd.fsf <at> stupidchicken.com>
<jwv8wygrbss.fsf-monnier+emacsbugreports <at> gnu.org>
<482750F4.2050102 <at> emf.net>
Date: Sun, 11 May 2008 21:43:47 -0400
In-Reply-To: <482750F4.2050102 <at> emf.net> (Thomas Lord's message of "Sun, 11 May
2008 13:03:00 -0700")
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
> Well, instead of using heuristics to decide where to re-scan from and
> too, you can cache a record of where the DFA scan arrived at for
> periodic positions in the buffer. Then begin scanning from just
> before any modification for as far as it takes to arrive at a DFA
> state that is the same as last time, updating any highlighting in the
> region between those two points.
That's a very good point. I'm not sure it's worth the trouble to store
it at various buffer positions and check if it's EQ to stop the rescan,
but at least we could match multiline expression one-line at a time.
In any case, it's indeed a non-trivial amount of work because it
probably requires rewriting not just font-lock but all the
foo-mode-font-lock-keywords as well (font-lock-keywords are order
dependent so you can't apply the rule nb 3 after rule nb 4).
> I don't mean to imply that this is a trivial thing to implement in
> Emacs but if you start getting up to building DFAs (very expensive in
> the worst case) and taking intersections (very expensive in the worst
> case) -- both also not all that simple to implement (nor obviously
> possible for Emacs' extended regexp language) -- then the effort may
> be comparable and (re-)visiting the option to adapt Rx to Emacs should
> be worth considering.
I have most of the DFA construction code written, but I may take you up
on that anyway. BTW, regarding the "very expensive in the worst case",
how common is this worst case in real life?
Stefan
Stefan Monnier <monnier <at> iro.umontreal.ca>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.5 required=4.0 tests=AWL,FOURLA autolearn=no
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 12 May 2008 01:28:30 +0000
Received: from ironport2-out.teksavvy.com (ironport2-out.pppoe.ca [206.248.154.182])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4C1SPHc011079
for <192 <at> emacsbugs.donarmstrong.com>; Sun, 11 May 2008 18:28:27 -0700
X-IronPort-Anti-Spam-Filtered: true
X-IronPort-Anti-Spam-Result: AmoCAAs6J0jO+JgrdGdsb2JhbACBU5A6ASeXCw
X-IronPort-AV: E=Sophos;i="4.27,470,1204520400";
d="el'?scan'208";a="20308168"
Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238])
by ironport2-out.teksavvy.com with ESMTP; 11 May 2008 21:28:19 -0400
Received: from pastel.home ([206.248.152.43])
by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id SGO89018;
Sun, 11 May 2008 21:28:18 -0400
Received: by pastel.home (Postfix, from userid 20848)
id 702CD7F83; Sun, 11 May 2008 21:28:18 -0400 (EDT)
From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: David Koppelman <koppel <at> ece.lsu.edu>
Cc: martin rudalics <rudalics <at> gmx.at>, Chong Yidong <cyd <at> stupidchicken.com>,
192 <at> debbugs.gnu.org, Bruno Haible <bruno <at> clisp.org>,
emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
Message-ID: <jwvr6c8pbd6.fsf-monnier+emacsbugreports <at> gnu.org>
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
<yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at>
<87abiwoqzd.fsf <at> stupidchicken.com>
<yg57ie0df8u.fsf <at> nested.ece.lsu.edu>
<jwv4p94r8vp.fsf-monnier+emacsbugreports <at> gnu.org>
<yg5tzh4bqtw.fsf <at> nested.ece.lsu.edu>
Date: Sun, 11 May 2008 21:28:18 -0400
In-Reply-To: <yg5tzh4bqtw.fsf <at> nested.ece.lsu.edu> (David Koppelman's message
of "Sun, 11 May 2008 14:09:31 -0500")
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="=-=-="
--=-=-=
> A better solution would be to have font-lock use multi-line extended
> regions selectively. Perhaps a hint in the current keyword syntax
> (say, explicitly applying the font-lock-multiline property), or a
> separate method for providing multi-line keywords to font-lock.
I don't understand the difference between the above and the application
of font-lock-multiline properties which you seem to have tried and rejected.
I don't necessarily disagree with your rejection of font-lock-multiline:
it can have disastrous effect indeed if the multiline region becomes large.
> Such keywords would get the multi-line extended regions, the other
> just the whole-line extensions (or whatever the hooks do).
> Is this something the font-lock maintainers would consider?
I guess I simply do not understand what you propose. Any improvement in
the multiline handling is welcome, but beware: this is not an easy area.
>> (while (re-search-forward <RE> nil t)
>> (font-lock-fontify-region (match-beginning 0) (match-end 0)))
> I wouldn't do that without suppressing other keywords.
FWIW, I do pretty much exactly the above loop in smerge-mode and
I haven't heard complaints yet.
>> If someone wants that, I have a parser that takes a regexp and turns it
>> into something like `rx' syntax. It uses my lex.el library (which
>> takes an `rx'-like input syntax).
> That sounds useful, either E-mail it to me or let me know
> where to find it.
Find the current version attached. Consider it as 99.9% untested
code, tho. Also you need to eval it before you can byte-compile it.
And I strongly recommend you byte-compile it to reduce the
specpdl usage.
Stefan
--=-=-=
Content-Type: application/emacs-lisp
Content-Disposition: attachment; filename=lex.el
Content-Transfer-Encoding: quoted-printable
;;; lex.el --- Lexical analyser construction
;; Copyright (C) 2008 Stefan Monnier
;; Author: Stefan Monnier <monnier <at> iro.umontreal.ca>
;; Keywords:=20
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Format or regexps, is the same as used for `rx' and `sregex'.
;; Additions:
;; - (ere RE) specify regexps using the ERE syntax.
;; - (inter REs...) (aka `&') make a regexp that only matches
;; if all its branches match. E.g. (inter (ere ".*a.*") (ere ".*b.*"))
;; match any string that contain both an "a" and a "b", in any order.
;; - (case-fold REs...) and (case-sensitive REs...) make a regexp that
;; is case sensitive or not, regardless of case-fold-search.
;; Input format of lexers:
;;
;; ALIST of the form ((RE . VAL) ...)
;; Format of compiled DFA lexers:
;;
;; nil ; The trivial lexer that fails
;; (CHAR . LEXER)
;; (table . CHAR-TABLE)
;; (stop VAL . LEXER) ; Match the empty string at point or LEXER.
;; (check (PREDICATE . ARG) SUCCESS-LEXER . FAILURE-LEXER)
;; Intermediate NFA nodes may additionally look like:
;; (or LEXERs...)
;; (orelse LEXERs...)
;; (and LEXERs...)
;; (join CONT . EXIT)
;;; Todo:
;; - submatches
;; - backrefs
;; - search rather than just match
;; - extensions:
;; - repeated submatches
;; - negation
;; - lookbehind and lookahead
;; - match(&search?) backward
;; - agrep
;;; Notes
;; Search
;; ------
;; To turn a match into a search, the basic idea is to use ".*RE" to get
;; a search-DFA as opposed to the match-DFA generated from "RE".
;; Search in Plan9's regexp library is done as follows: match ".*RE" until
;; reaching the first match and then continue with only "RE". The first
;; ".*RE" match corresponds to a search success for the leftmost shortest
;; match. If we want the longest match, we need to continue. But if we
;; continue with ".*RE" then we have no idea when to stop, so we should only
;; continue with "RE".
;; Downside: we may still match things after the "leftmost longest" match,
;; but hopefully will stop soon after. I.e. we may look at chars past the
;; end of the leftmost longest match, but hopefully not too many.
;; Alternatives:
;; - Like emacs/src/regexp.c, we can just start a match at every buffer
;; position. Advantage: no need for submatch info in order to find
;; (match-beginning 0), no need for a separate search-DFA.
;; Downsize: O(N^2) rather than O(N). But it's no worse than what we live
;; with for decades in src/regexp.c.
;;
;; - After the shortest-search, stop the search and do a longest-match
;; starting at position (match-beginning 0). The good thing is that we
;; will not look at any char further than needed. Also we don't need to
;; figure out how to switch from ".*RE" to "RE" in the middle of the sear=
ch.
;; The downside is that we end up looking twice at the chars common to the
;; shortest and longest matches. Also this doesn't work: the shortest
;; match may not be the leftmost match, so we can't just start the match
;; at (match-beginning 0).
;;
;; - After the shortest-search, use the submatch data to figure out the NFA
;; states (corresponding to the current search-DFA state) which are only
;; reachable from later starting positions than (match-beginning 0),
;; remove them and figure out from that the match-DFA state to which
;; to switch. Problem is: there might not be any such state in the
;; match-DFA.
;;
;; - Generate a specialized search&match-DFA which encodes the job done by
;; Plan9's regexp library. I.e. do a specialized merge on
;; (or LEXER (anything . LEXER)) where whenever we get a `stop' we don't
;; merge any more. After matching such a lexer, we still have to figure
;; which of the matches we had is the leftmost longest match, of course.
;; Actually, it's not that easy: the tail of a `stop' in the match-DFA can
;; only match things whose (match-beginning 0) may be the same as the one
;; of the `stop', whereas we also want to accept longer matches that start
;; before (match-beginning 0). So we want to keep merging on the tail of
;; `stop' nodes, but only "partially" (whatever that means).
;; Lookahead
;; ---------
;; I suspect that the (?=3D<RE>) lookahead can be encoded using something l=
ike
;; `andalso'. Of course, it can also trivially be encoded as a predicate,
;; but then we get an O(N^2) complexity.
;;; Code:
(eval-when-compile (require 'cl))
(defun copy-char-table (ct1)
(let* ((subtype (char-table-subtype ct1))
(ct2 (make-char-table subtype)))
(map-char-table (lambda (c v) (set-char-table-range ct2 c v)) ct1)
(dotimes (i (or (get subtype 'char-table-extra-slots) 0))
(set-char-table-extra-slot ct2 i (char-table-extra-slot ct1 i)))
ct2))
(defun lex--char-table->alist (ct)
(let ((res ()))
(map-char-table (lambda (k v)
(push (cons (if (consp k)
;; If k is a cons cell, we have to
;; copy it because map-char-table
;; reuses it.
(cons (car k) (cdr k))
;; Otherwise, create a trivial cons-cell
;; so we have fewer cases to handle.
(cons k k))
v)
res))
ct)
res))
(defun lex--merge-into (op al1 al2 ct)
(assert (memq op '(and or orelse)))
;; We assume that map-char-table calls its function with increasing
;; `key' arguments.
(while (and al1 al2)
(let ((k1 (caar al1)) (k2 (caar al2)))
(cond
;; Perfect overlap.
((equal k1 k2)
(set-char-table-range ct k1
(lex--merge op (cdr (pop al1)) (cdr (pop al2)=
))))
;; k1 strictly greater than k2.
((and (consp k1) (consp k2) (> (car k1) (cdr k2)))
(let ((v (cdr (pop al1))))
(if (not (eq op 'and)) (set-char-table-range ct k1 v))))
;; k2 strictly greater than k1.
((and (consp k1) (consp k2) (> (car k2) (cdr k1)))
(let ((v (cdr (pop al2))))
(if (not (eq op 'and)) (set-char-table-range ct k2 v))))
;; There's partial overlap.
((and (consp k1) (consp k2) (> (cdr k1) (cdr k2)))
(if (not (eq op 'and))
(set-char-table-range ct (cons (1+ (cdr k2)) (cdr k1)) (cdar al=
1)))
(setcdr k1 (cdr k2)))
((and (consp k1) (consp k2) (< (cdr k1) (cdr k2)))
(if (not (eq op 'and))
(set-char-table-range ct (cons (1+ (cdr k1)) (cdr k2)) (cdar al=
2)))
(setcdr k2 (cdr k1)))
;; Now the tails are equal.
((and (consp k1) (consp k2) (> (car k1) (car k2)))
(set-char-table-range ct k1 (lex--merge op (cdr (pop al1)) (cdar al=
2)))
(setcdr k2 (1- (car k1))))
((and (consp k1) (consp k2) (< (car k1) (car k2)))
(set-char-table-range ct k2 (lex--merge op (cdar al1) (cdr (pop al2=
))))
(setcdr k1 (1- (car k2))))
((assert nil)))))
(if (not (eq op 'and))
(dolist (x (or al1 al2))
(set-char-table-range ct (car x) (cdr x)))))
(defvar lex--states)
(defvar lex--memoize)
(defun lex--set-eq (l1 l2)
(let ((len (length l2)))
(setq l2 (copy-sequence l2))
(while (consp l1)
(assert (=3D len (length l2)))
(unless (> len
(setq len (length (setq l2 (delq (pop l1) l2)))))
(setq l1 t)))
(not l1)))
(define-hash-table-test 'lex--set-eq 'lex--set-eq
(lambda (l)
(let ((hash 0))
(while l
(let ((x (pop l)))
(if (memq x l) (progn (debug) nil)
(setq hash (+ hash (sxhash x))))))
hash)))
=20=20=20=20=20=20
(defun lex--flatten-state (state)
(assert (memq (car state) '(and or orelse)))
(let ((op (car state))
(todo (cdr state))
(done (list state))
(res nil))
(while todo
(setq state (pop todo))
(cond
((null state) (if (eq op 'and) (setq res nil todo nil)))
((memq state done) nil)
((eq (car-safe state) op) (setq todo (append (cdr state) todo)))
(t (unless (memq state res) (push state res)))))
(cons op (nreverse res))))
(defun lex--merge-2 (op lex1 lex2)
(assert (memq op '(and or orelse)))
;; The order between lex1 and lex2 matters: preference is given to lex1.
(cond
((eq lex1 lex2) (debug) lex1) ;CHECK: ruled out by `lex--flatten-state'?
;; ((equal lex1 lex2) lex1) ;Stack overflow :-(
;; Handle the 2 possible nil cases.
;; CHECK: ruled out by `lex--flatten-state'?
((null lex1) (debug) (if (eq op 'and) nil lex2))
((null lex2) (debug) (if (eq op 'and) nil lex1))
;; Do the predicate cases before the `stop' because the stop should
;; always come after the checks.
;; TODO: add optimizations for pairs of `checks' which are redundant,
;; or mutually exclusive, ... although we can also do it in lex-optimize.
((and (eq (car lex1) 'check) (eq (car lex2) 'check)
(equal (nth 1 lex1) (nth 1 lex2))) ; Same predicate.
(list* 'check (nth 1 lex1)
(lex--merge op (nth 2 lex1) (nth 2 lex2))
(lex--merge op (nthcdr 3 lex1) (nthcdr 3 lex2))))
((eq (car lex1) 'check)
(list* 'check (nth 1 lex1)
(lex--merge op (nth 2 lex1) lex2)
(lex--merge op (nthcdr 3 lex1) lex2)))
((eq (car lex2) 'check)
(list* 'check (nth 1 lex2)
(lex--merge op lex1 (nth 2 lex2))
(lex--merge op lex1 (nthcdr 3 lex2))))
;; Joins have the form (join CONT . EXIT) where EXIT is a lexer
;; corresponding to the rest of the regexp after the `and' sub-regexp.
;; All the joins corresponding to the same `and' have the same EXIT.
;; CONT is a lexer that contains another join inside, it corresponds to
;; the decision to not yet leave the `and'.
((and (eq (car lex1) 'join) (eq (car lex2) 'join))
(assert (eq (cddr lex1) (cddr lex2))) ;Check they're the same join.
`(join ,(lex--merge op (cadr lex1) (cadr lex2)) ,@(cddr lex1)))
;; If one the two lex's is a join but the other not, the other must
;; contain a corresponding join somewhere inside.
((eq (car lex1) 'join)
(let ((next (lex--merge op (nth 1 lex1) lex2)))
;; lex1 is a valid exit point but lex2 isn't.
(if (eq op 'and)
next
;; FIXME: lex1 is implicitly an `or' (or `orelse'?) between (cadr
;; lex1) and (cddr lex1). Here we construct an `or' (or `orelse'?)
;; between `next' and (cddr lex1). I.e. we lose the `op' and we do
;; not preserve the ordering between lex2 and (cddr lex1).
`(join ,next ,@(cddr lex1)))))
((eq (car lex2) 'join)
(let ((next (lex--merge op lex1 (nth 1 lex2))))
(if (eq op 'and) next `(join ,next ,@(cddr lex2)))))
;; The three `stop' cases.
((and (eq (car lex1) 'stop) (eq (car lex2) 'stop))
;; Here is where we give precedence to `lex1'.
(if (eq op 'orelse) lex1
(list* 'stop (cadr lex1) (lex--merge op (cddr lex1) (cddr lex2)))))
((eq (car lex1) 'stop)
(let ((next (lex--merge op (cddr lex1) lex2)))
(ecase op
(or (list* 'stop (cadr lex1) next))
(orelse lex1)
;; CHECK: We should have hit a `join' before reaching a `stop'.
(and (debug) next))))
((eq (car lex2) 'stop)
(let ((next (lex--merge op lex1 (cddr lex2))))
;; For `orelse', we want here to delay the `stop' until the point
;; where we know that lex1 doesn't match. Sadly, I don't know how to
;; do it.
(ecase op
;; CHECK: We should have hit a `join' before reaching a `stop'.
(and (debug) next)
;; FIXME: One thing we can do is to mark the value attached to the
;; `stop' so as to indicate that an earlier match may finish later.
;; This way, if the match is not `earlystop', we know it's one of
;; the leftmost ones, and maybe the search loop can avoid some work
;; when determining which is the leftmost longest match.
(orelse (list* 'stop `(earlystop ,(cadr lex2)) next))
((or orelse) (list* 'stop (cadr lex2) next)))))
;; The most general case.
((and (eq (car lex1) 'table) (eq (car lex2) 'table))
(let ((al1 (lex--char-table->alist (cdr lex1)))
(al2 (lex--char-table->alist (cdr lex2)))
(ct (make-char-table 'lexer)))
(lex--merge-into op al1 al2 ct)
(cons 'table ct)))
((and (characterp (car lex1)) (characterp (car lex2))
(eq (car lex1) (car lex2)))
(cons (car lex1) (lex--merge op (cdr lex1) (cdr lex2))))
((and (characterp (car lex1)) (characterp (car lex2)))
(unless (eq op 'and)
(let ((ct (make-char-table 'lexer)))
(aset ct (car lex1) (cdr lex1))
(aset ct (car lex2) (cdr lex2))
(cons 'table ct))))
((and (characterp (car lex1)) (eq (car lex2) 'table))
(let ((next (lex--merge op (cdr lex1) (aref (cdr lex2) (car lex1)))))
(if (eq op 'and)
(if next (cons (car lex1) next))
(let ((ct (copy-sequence (cdr lex2))))
(aset ct (car lex1) next)
(cons 'table ct)))))
((and (eq (car lex1) 'table) (characterp (car lex2)))
(let ((next (lex--merge op (aref (cdr lex1) (car lex2)) (cdr lex2))))
(if (eq op 'and)
(if next (cons (car lex2) next))
(let ((ct (copy-sequence (cdr lex1))))
(aset ct (car lex2) next)
(cons 'table ct)))))
((or (memq (car lex1) '(or orelse and state))
(memq (car lex2) '(or orelse and state)))
;; `state' nodes are nodes whose content is not known yet, so we
;; have to delay the merge via the memoization table.
;; `or' and `and' nodes should only happen when the other `op' is being
;; performed, in which case we can't do the merge either before lex1
;; and lex2 have both been merged.
(lex--merge op lex1 lex2))
((assert nil))))
(defun lex--merge-now (&rest state)
(assert (memq (car state) '(and or orelse)))
;; Re-flatten, in case one of the sub-states was changed.
(setq state (lex--flatten-state state))
(if (<=3D (length state) 2)
;; FIXME: for `and' nodes, this is not enough: we need to look for and
;; remove the corresponding `join' node(s).
(cadr state)
(let ((op (pop state))
(res (pop state)))
(dolist (lex state)
(setq res (lex--merge-2 op res lex)))
(if (and (eq op 'and) (eq (car res) 'join))
;; Eliminate the join once it was all merged.
;; FIXME: This arbitrarily chooses `or' instead of `orelse',
;; and it arbitrarily gives CONT precedence to EXIT. That doesn't
;; sound right.
(lex--merge 'or (cadr res) (cddr res))
res))))
(defun lex--merge (&rest state)
(assert (memq (car state) '(and or orelse)))
(setq state (lex--flatten-state state))
(if (<=3D (length state) 2)
(cadr state)
(or (gethash state lex--memoize)
(progn
;; (debug)
(assert (memq (car state) '(and or orelse)))
(push state lex--states)
;; The `state' node will be later on modified via setcar/setcdr,
;; se be careful to use a copy of it for the key.
(puthash (cons (car state) (cdr state)) state lex--memoize)
state))))
(defun lex--compile-category (category)
(if (and (integerp category) (< category 128))
category
(if (symbolp category)
(if (=3D 1 (length (symbol-name category)))
(aref (symbol-name category) 0)
(require 'rx)
(cdr (assq category rx-categories))))))
(defun lex--compile-syntax (&rest syntaxes)
(mapcar (lambda (x)
(if (and (integerp x) (< x 32)) x
(if (symbolp x)
(setq x (if (=3D 1 (length (symbol-name x)))
(symbol-name x)
(require 'rx)
(cdr (assq x rx-syntax)))))
(if (characterp x) (setq x (string x)))
(car (string-to-syntax x))))
syntaxes))
(defconst lex--char-classes
`((alnum alpha digit)
(alpha word (?a . ?z) (?A . ?Z))
(blank ?\s ?\t)
(cntrl (?\0 . ?\C-_))
(digit (?0 . ?9))
;; Include all multibyte chars, plus all the bytes except 128-159.
(graph (?! . ?~) multibyte (#x3fffa0 . #x3fffff))
;; src/regexp.c handles case-folding inconsistently: lower and upper
;; match both lower- and uppercase ascii chars, but lower also matches
;; uppercase non-ascii chars whereas upper does not match lowercase
;; nonascii chars. Here I simply ignore case-fold for [:lower:] and
;; [:upper:] because it's simpler and doesn't seem worse.
(lower (check (lex--match-lower)))
(upper (check (lex--match-upper)))
(print graph ?\s)
(punct (check (not (lex--match-syntax . ,(lex--compile-syntax "w"))))
(?! . ?/) (?: . ?@) (?\[ . ?`) (?\{ . ?~))
(space (check (lex--match-syntax . ,(lex--compile-syntax " "))))
(xdigit digit (?a . ?f) (?A . ?F))
(ascii (?\0 . ?\177))
(nonascii (?\200 . #x3fffff))
(unibyte ascii (#x3fff00 . #x3fffff))
(multibyte (#x100 . #x3ffeff))
(word (check (lex--match-syntax . ,(lex--compile-syntax "w"))))
;; `rx' alternative names.
(numeric digit)
(num digit)
(control cntrl)
(hex-digit xdigit)
(hex xdigit)
(graphic graph)
(printing print)
(alphanumeric alnum)
(letter alpha)
(alphabetic alpha)
(lower-case lower)
(upper-case upper)
(punctuation punct)
(whitespace space)
(white space))
"Definition of char classes.
Each element has the form (CLASS . DEFINITION) where definition
is a list of elements that can be either CHAR or (CHAR . CHAR),
or CLASS (another char class) or (check (PREDICATE . ARG))
or (check (not (PREDICATE . ARG))).")
(defvar lex--char-equiv-table nil
"Equiv-case table to use to compile case-insensitive regexps.")
(defun lex--char-equiv (char)
(when lex--char-equiv-table
(let ((chars ())
(tmp char))
(while (and (setq tmp (aref lex--char-equiv-table tmp))
(not (eq tmp char)))
(push tmp chars))
(if chars (cons char chars)))))
=20=20=20=20
(defun lex--nfa (re state)
(assert state) ;If `state' is nil we can't match anyway.
(cond
((characterp re)
(let ((chars (lex--char-equiv re)))
(if (null chars)
(cons re state)
(let ((ct (make-char-table 'lexer)))
(dolist (char chars) (aset ct char state))
(cons 'table ct)))))
((stringp re)
(if (null lex--char-equiv-table)
;; (Very) minor optimization.
(nconc (mapcar 'identity re) state)
(lex--nfa `(seq ,@(mapcar 'identity re)) state)))
(t
(ecase (or (car-safe re) re)
((: seq sequence
;; Hack!
group)
(dolist (elem (reverse (cdr re)))
(setq state (lex--nfa elem state)))
state)
((char in not-char)
(let ((chars (cdr re))
(checks nil)
(fail nil)
(char nil) ;The char seen, or nil if none, or t if more than o=
ne.
(ct (make-char-table 'lexer)))
(when (or (eq 'not (car chars)) (eq 'not-char (car re)))
(setq chars (cdr chars))
(set-char-table-range ct t state)
(setq fail state)
(setq state nil))
(while chars
(let ((range (pop chars)))
(cond
((stringp range)
(setq chars (append (cdr (lex--parse-charset range)) chars)))
((symbolp range)
(setq range (or (cdr (assq range lex--char-classes))
(error "Uknown char class `%s'" range)))
(setq chars (append range chars)))
((and (consp range) (eq 'check (car range)))
(push (cadr range) checks))
(t
(setq char (if (or char (not (characterp range))
(and lex--char-equiv-table
(lex--char-equiv range)))
t range))
;; Set the range, first, regardless of case-folding. This is
;; important because case-tables like to be set with few
;; large ranges rather than many small ones, as is done in
;; the case-fold loop.
(set-char-table-range ct range state)
(when (and lex--char-equiv-table
;; Avoid looping over all characters.
(not (equal range '(#x100 . #x3ffeff))))
;; Add all the case-equiv chars.
(let ((i (if (consp range) (car range) range))
(max (if (consp range) (cdr range) range))
char)
(while (<=3D i max)
(setq char i)
(while (and (setq char (aref lex--char-equiv-table cha=
r))
(not (eq char i)))
(aset ct char state))
(setq i (1+ i)))))))))
(let ((res (if (or (eq char t) fail)
(cons 'table ct)
(if char (cons char state)))))
(if (and (not fail) checks)
(setq state (lex--nfa 'anything state)))
(dolist (check checks)
(setq res
(if fail
;; We do an `and' of the negation of the check and r=
es.
(if (eq (car-safe check) 'not)
(list 'check (cadr check) res)
(list* 'check check nil res))
;; An `or' of the check and res.
(if (eq (car-safe check) 'not)
(list 'check (cadr check) res state)
(list* 'check check state res)))))
res)))
((union or | orelse)
(apply 'lex--merge (if (eq (car re) 'orelse) 'orelse 'or)
(mapcar (lambda (re) (lex--nfa re state)) (cdr re))))
((inter intersection &)
;; Just using `and' is not enough because we have to enforce that the
;; sub-regexps (rather than the whole regexp) match the same string.
;; So we need to mark the juncture point.
(let* ((join `(join nil ,@state)))
(apply 'lex--merge 'and
(mapcar (lambda (re) (lex--nfa re join)) (cdr re)))))
((0+ zero-or-more * *\?)
(let ((newstate (list 'state)))
(let ((lexer (lex--nfa (cons 'seq (cdr re)) newstate)))
(setcdr newstate (if (memq (car re) '(*\?))
(list state lexer)
(list lexer state))))
(setcar newstate (if (memq (car re) '(*\?)) 'orelse 'or))
(assert (memq (car newstate) '(and or orelse)))
(push newstate lex--states)
newstate))
=20=20=20=20=20=20
((string-end eos eot buffer-end eob) `(check (lex--match-eobp) ,state=
))
((string-start bos bot buffer-start bob)
`(check (lex--match-bobp) ,state))
((line-end eol) `(check (lex--match-eolp) ,state))
((line-start bol) `(check (lex--match-bolp) ,state))
((word-start bow) `(check (lex--match-bowp) ,state))
((word-end eow) `(check (lex--match-eowp) ,state))
((symbol-start) `(check (lex--match-bosp) ,state))
((symbol-end) `(check (lex--match-eosp) ,state))
((not-word-boundary) `(check (lex--match-not-word-boundary) ,state))
((word-boundary) `(check (lex--match-not-word-boundary) nil . ,state))
((syntax) `(check (lex--match-syntax
. ,(apply 'lex--compile-syntax (cdr re)))
,(lex--nfa 'anything state)))
((not-syntax) `(check (lex--match-syntax
. ,(apply 'lex--compile-syntax (cdr re)))
nil . ,(lex--nfa 'anything state)))
((category) `(check (lex--match-category
. ,(lex--compile-category (cadr re)))
,(lex--nfa 'anything state)))
((not-category) `(check (lex--match-category
. ,(lex--compile-category (cadr re)))
nil . ,(lex--nfa 'anything state)))
=20=20=20=20=20=20
;; `rx' accepts char-classes directly as regexps. Let's reluctantly
;; do the same.
((digit numeric num control cntrl hex-digit hex xdigit blank graphic
graph printing print alphanumeric alnum letter alphabetic alpha asc=
ii
nonascii lower lower-case upper upper-case punctuation punct space
whitespace white)
(lex--nfa `(char ,re) state))
((case-sensitive)
(let ((lex--char-equiv-table nil))
(lex--nfa `(seq ,@(cdr re)) state)))
((case-fold)
(let ((lex--char-equiv-table (get-eqvcase-table (current-case-table)=
)))
(lex--nfa `(seq ,@(cdr re)) state)))
((point
;; Sub groups!
submatch group backref
;; Greediness control
minimal-match maximal-match)
(error "`%s' Not implemented" (or (car-safe re) re)))
((not-newline nonl dot) (lex--nfa '(char not ?\n) state))
(anything (lex--nfa '(char not) state))
((word wordchar) (lex--nfa '(syntax w) state))
((not-wordchar) (lex--nfa '(not-syntax w) state))
(any
;; `rx' uses it for (char ...) sets, and sregex uses it for `dot'.
(lex--nfa (if (consp re) (cons 'char (cdr re)) '(char not ?\n)) stat=
e))
(not
;; The `not' as used in `rx' should be deprecated: we may want to
;; provide real support for a fully general `not', but its semantics
;; will most likely be different. E.g. we may want to let
;; (not (char ...)) match the empty string.
(setq re (cadr re))
(ecase (or (car-safe re) re)
(word-boundary
(message "`not' deprecated: use not-word-boundary")
(lex--nfa 'not-word-boundary state))
((any in char)
(message "`not' deprecated: use (%s not ...)" (or (car-safe re) r=
e))
(lex--nfa (list* (car re) 'not (cdr re)) state))
((category syntax)
(message "`not' deprecated: use not-%s" (car re))
(lex--nfa (cons (intern (format "not-%s" (car re))) (cdr re)) sta=
te))))
(and
;; `rx' defined `and' as `sequence', but we may want to define it
;; as intersection instead.
(error "`and' is deprecated, use `seq', `:', or `sequence' instead"))
=20=20=20=20=20=20=20=20=20
((1+ one-or-more + +\?)
(lex--nfa `(seq (seq ,@(cdr re))
(,(if (memq (car re) '(+\?)) '*\? '0+) ,@(cdr re)))
state))
((opt zero-or-one optional \?)
(lex--nfa `(or (seq ,@(cdr re)) "") state))
((\?\?)
(lex--nfa `(orelse "" (seq ,@(cdr re))) state))
((repeat ** =3D)
(let ((min (nth 1 re))
(max (nth 2 re))
(res (nthcdr 3 re)))
(unless res
(setq res (list max)) (setq max min))
(lex--nfa `(seq ,@(append (make-list (or min 0)
(if (eq (length res) 1)
(car res)
(cons 'seq res)))
(if (null max)
`((0+ ,@res))
(make-list (- max (or min 0))
`(opt ,@res)))))
state)))
((>=3D) (lex--nfa `(repeat ,(nth 1 re) nil ,@(nthcdr 2 re)) state))
((bre re ere)
(lex--nfa (lex-parse-re (nth 1 re) (car re)) state))))))
(defun lex--dfa-wrapper (f)
(let* ((lex--states ())
(lex--memoize (make-hash-table :test 'lex--set-eq))
(res (funcall f))
(postponed ())
(states-dfa (make-hash-table :test 'eq)))
(while lex--states
(dolist (state (prog1 lex--states (setq lex--states nil)))
(let ((merged (apply 'lex--merge-now state)))
(if (memq (car merged) '(and or orelse))
;; The merge could not be performed for some reason:
;; let's re-schedule it.
(push state postponed)
(puthash state merged states-dfa))))
(unless lex--states
;; If states-dfa is empty it means we haven't made any progress,
;; so we're stuck in an infinite loop. Hopefully this cannot happe=
n?
(assert (not (zerop (hash-table-count states-dfa))))
(maphash (lambda (k v)
(unless v
;; With `intersection', lex--merge may end up returning
;; nil if the intersection is empty, so `v' can be
;; nil here. In since `k' is necessarily a cons cell,
;; we can't turn it into nil, so we turn it into
;; a more costly lexer that also fails for all inputs.
(setq v '(?a)))
(setcar k (car v))
(setcdr k (cdr v)))
states-dfa)
(clrhash states-dfa)
(setq lex--states postponed)
(setq postponed nil)))
res))
(defun lex-compile (alist)
(lex--dfa-wrapper
(lambda ()
(let ((lex--char-equiv-table
(if case-fold-search (get-eqvcase-table (current-case-table)))))
(apply 'lex--merge 'or
(mapcar (lambda (x) (lex--nfa (car x) (list 'stop (cdr x))))
alist))))))
(defun lex-search-dfa (match-dfa)
;; This constructs a search-DFA whose last match should be the leftmost
;; longest match.
(lex--dfa-wrapper
(lambda ()
(lex--nfa '(*\? (char not)) match-dfa))))
(defun lex--terminate-if (new old)
(cond
((eq new t) t)
((eq old t) t)
(t (while new (let ((x (pop new))) (if (memq x old) (push x old)))) old)=
))
(defun lex--optimize-1 (lexer)
(let ((terminate nil))
(cons
(case (car lexer)
(table
(let ((ct (cdr lexer))
(char nil))
;; Optimize each entry.
(map-char-table
(lambda (range v)
(let ((cell (lex--optimize v)))
(setq terminate (lex--terminate-if (cdr cell) terminate))
(set-char-table-range ct range (car cell))))
ct)
;; Optimize the internal representation of the table.
(optimize-char-table (cdr lexer))
;; Eliminate the table if possible.
(map-char-table
(lambda (range v)
(setq char
(if (and (characterp range) (null char))
range t)))
ct)
(case char
((nil) nil)
((t) lexer)
(t (setcar lexer 'char) (setcdr lexer (aref ct char)) lexer))))
(stop
(let ((cell (lex--optimize (cddr lexer))))
(setq terminate t)
(setf (cddr lexer) (car cell)))
lexer)
(check
(let* ((test (nth 1 lexer))
(cellf (lex--optimize (nthcdr 3 lexer)))
(fail (setf (nthcdr 3 lexer) (car cellf)))
(cells (lex--optimize (nth 2 lexer)))
(succ (setf (nth 2 lexer) (car cells))))
(setq terminate (lex--terminate-if (cdr cellf) terminate))
(setq terminate (lex--terminate-if (cdr cells) terminate))
(when (eq 'check (car succ))
(cond
((equal test (nth 1 succ)) ;Same successful test.
(debug)
(setf (nth 2 lexer) (setq succ (nth 2 succ))))
;; TODO: we can add rules such as bobp -> eolp,
;; bosp -> bowp, (syntax X) -> (syntax Y X), ...
))
(when (eq 'check (car fail))
(cond
((equal test (nth 1 fail)) ;Same failing test.
(debug)
(setf (nthcdr 3 lexer) (setq fail (nthcdr 3 succ))))
;; TODO: we can add rules such as !eolp -> !bobp,
;; !bowp -> !bosp, !(syntax Y X) -> !(syntax X), ...
))
(if (or succ fail) lexer)))
(t
(assert (characterp (car lexer)))
(let ((cell (lex--optimize (cdr lexer))))
(setq terminate (lex--terminate-if (cdr cell) terminate))
(if (setf (cdr lexer) (car cell))
lexer))))
(if (consp terminate)
(delq lexer terminate)
terminate))))
(defun lex--optimize (lexer)
(when lexer
;; The lex--memoize cache maps lexer states to (LEXER . TERMINATE) where
;; TERMINATE is either t to say that LEXER can terminate or a list of
;; lexers which means that LEXER terminates only if one of the lexers in
;; the list terminates.
(let ((cache (gethash lexer lex--memoize)))
(if cache
;; Optimize (char C) to nil.
(if (and (characterp (caar cache)) (null (cdar cache))) nil cache)
;; Store a value indicating that we're in the process of computing =
it,
;; so when we encounter a loop, we don't recurse indefinitely.
;; Not knowing any better, we start by stating the tautology that
;; `lexer' terminates if and only if `lexer' terminates.
(let ((cell (cons lexer (list lexer))))
(puthash lexer cell lex--memoize)
(let ((res (lex--optimize-1 lexer)))
(if (and (car res) (cdr res))
res
(setcar lexer ?a)
(setcdr lexer nil)
(puthash lexer '(nil) lex--memoize)
nil)))))))
(defun lex-optimize (lexer)
(let ((lex--memoize (make-hash-table :test 'eq)))
(prog1 (car (lex--optimize lexer))
(message "Visited %d states" (hash-table-count lex--memoize)))))
(defmacro lex-case (object posvar &rest cases)
(declare (indent 2))
(let* ((i -1)
(alist (mapcar (lambda (case) (cons (car case) (incf i))) cases))
(lex (lex-compile alist))
(tmpsym (make-symbol "tmp")))
(setq i -1)
`(let ((,tmpsym (lex-match-string ',lex ,object ,posvar)))
(case (cdr ,tmpsym)
,@(mapcar (lambda (case)
`(,(incf i) (set-match-data
(list ,posvar (setq ,posvar (car ,tmpsym)=
)))
,@(cdr case)))
cases)))))
;;; Matching engine
(defun lex--match-bobp (arg pos &optional string)
(=3D pos (if string 0 (point-min))))
(defun lex--match-eobp (arg pos &optional string)
(=3D pos (if string (length string) (point-max))))
(defun lex--match-bolp (arg pos &optional string)
(if string (or (=3D pos 0) (eq ?\n (aref string (1- pos))))
(memq (char-before pos) '(nil ?\n))))
(defun lex--match-eolp (arg pos &optional string)
(if string (or (=3D pos (length string)) (eq ?\n (aref string pos)))
(memq (char-after pos) '(nil ?\n))))
(defun lex--match-bowp (arg pos &optional string)
(and (not (if string (and (> pos 0)
(eq ?w (char-syntax (aref string (1- pos)))))
(and (> pos (point-min)) (eq 2 (car (syntax-after (1- pos))))=
)))
(if string (and (< pos (length string))
(eq ?w (char-syntax (aref string pos))))
(eq 2 (car (syntax-after pos))))))
(defun lex--match-eowp (arg pos &optional string)
(and (if string (and (> pos 0)
(eq ?w (char-syntax (aref string (1- pos)))))
(and (> pos (point-min)) (eq 2 (car (syntax-after (1- pos))))))
(not (if string (and (< pos (length string))
(eq ?w (char-syntax (aref string pos))))
(eq 2 (car (syntax-after pos)))))))
(defun lex--match-bosp (arg pos &optional string)
(and (not (if string
(and (> pos 0)
(memq (char-syntax (aref string (1- pos))) '(?w ?_)))
(and (> pos (point-min))
(memq (car (syntax-after (1- pos))) '(2 3)))))
(if string (and (< pos (length string))
(memq (char-syntax (aref string pos)) '(?w ?_)))
(memq (car (syntax-after pos)) '(2 3)))))
(defun lex--match-eosp (arg pos &optional string)
(and (if string (and (> pos 0)
(memq (char-syntax (aref string (1- pos))) '(?w ?_)))
(and (> pos (point-min)) (memq (car (syntax-after (1- pos))) '(2 3=
))))
(not (if string (and (< pos (length string))
(memq (char-syntax (aref string pos)) '(?w ?_)))
(memq (car (syntax-after pos)) '(2 3))))))
(defun lex--match-not-word-boundary (arg pos &optional string)
(eq (if string (and (> pos 0)
(eq ?w (char-syntax (aref string (1- pos)))))
(and (> pos (point-min)) (eq 2 (car (syntax-after (1- pos))))))
(if string (and (< pos (length string))
(eq ?w (char-syntax (aref string pos))))
(eq 2 (car (syntax-after pos))))))
(defun lex--match-upper (arg pos &optional string)
(when (< pos (if string (length string) (point-max)))
(let ((char (if string (aref string pos) (char-after pos))))
(not (eq (downcase char) char)))))
(defun lex--match-lower (arg pos &optional string)
(when (< pos (if string (length string) (point-max)))
(let ((char (if string (aref string pos) (char-after pos))))
(not (eq (upcase char) char)))))
(defun lex--match-category (category pos &optional string)
(when (< pos (if string (length string) (point-max)))
(aref (char-category-set (if string (aref string pos)
(char-after pos)))
category)))
(defun lex--match-syntax (syntaxes pos &optional string)
(when (< pos (if string (length string) (point-max)))
(memq (car (if string (aref (syntax-table) (aref string pos))
(syntax-after pos)))
syntaxes)))
(defun lex-match-string (lex string &optional start)
;; FIXME: Move this to C.
(unless start (setq start 0))
(let ((match nil))
(while
(progn
(while (eq (car lex) 'check)
(setq lex (if (funcall (car (nth 1 lex)) (cdr (nth 1 lex))
start string)
(nth 2 lex) (nthcdr 3 lex))))
(when (eq (car lex) 'stop)
(setq match (cons start (cadr lex)))
(message "Found match: %s" match)
(setq lex (cddr lex)))
(assert (not (eq (car lex) 'stop)))
(and lex (< start (length string))))
(let ((c (aref string start)))
(setq start (1+ start))
(setq lex (cond
((eq (car lex) 'table) (aref (cdr lex) c))
((integerp (car lex)) (if (eq c (car lex)) (cdr lex))))=
)))
(message "Final search pos considered: %s" start)
match))
=20=20=20=20=20=20=20=20
;;; Regexp parsers.
(defun lex--tokenizer (lex string)
(let ((tokens ())
(i 0)
tmp)
(while (and (< i (length string))
(setq tmp (lex-match-string lex string i)))
(push (cons (cdr tmp) (substring string i (setq i (car tmp)))) tokens=
))
(nreverse tokens)))
(defun lex--parse-charset (string)
(let ((i 0)
(ranges ()))
(when (eq (aref string i) ?^)
(push 'not ranges)
(setq i (1+ i)))
(let ((op nil)
(case-fold-search nil))
(while (not (eq op 'stop))
(lex-case string i
((seq "[:" (0+ (char (?a . ?z) (?A . ?Z))) ":]")
(push (intern (substring string (+ 2 (match-beginning 0))
(- (match-end 0) 2)))
ranges))
((seq anything "-" anything)
(push (cons (aref string (match-beginning 0))
(aref string (1- (match-end 0))))
ranges))
(anything (push (aref string (1- (match-end 0))) ranges))
(eob (setq op 'stop))))
=20=20=20=20=20=20
`(char ,@(nreverse ranges)))))
(defconst lex--parse-re-lexspec
'(((or "*" "+" "?" "*?" "+?" "??") . suffix)
((seq "[" (opt "^") (opt "]")
(0+ (or (seq (char not ?\]) "-" (char not ?\]))
(seq "[:" (1+ (char (?a . ?z) (?A . ?Z))) ":]")
(char not ?\]))) "]") . charset)
((seq "\\c" anything) . category)
((seq "\\C" anything) . not-category)
((seq "\\s" anything) . syntax)
((seq "\\S" anything) . not-syntax)
((seq "\\" (char (?1 . ?9))) . backref)
("\\'" . eob)
("\\`" . bob)
("." . dot)
("^" . bol)
("$" . eol)
("." . dot)
("\\<" . bow)
("\\>" . eow)
("\\_<" . symbol-start)
("\\_>" . symbol-end)
("\\w" . wordchar)
("\\W" . not-wordchar)
("\\b" . word-boundary)
("\\B" . not-word-boundary)
("\\=3D" . point)
((or (seq ?\\ anything) anything) . char)))
=20=20
(defconst lex--parse-ere-lexer
(let ((case-fold-search nil))
(lex-compile
(append '(("(?:" . shy-group)
("|" . or)
((seq "{" (0+ (char (?0 . ?9)))
(opt (seq "," (0+ (char (?0 . ?9))))) "}") . repeat)
((or ")" eob) . stop)
("(" . group))
lex--parse-re-lexspec))))
(defconst lex--parse-bre-lexer
(let ((case-fold-search nil))
(lex-compile
(append '(("\\(?:" . shy-group)
("\\|" . or)
((seq "\\{" (0+ (char (?0 . ?9)))
(opt (seq "," (0+ (char (?0 . ?9))))) "\\}") . repeat)
((or "\\)" eob) . stop)
("\\(" . group))
lex--parse-re-lexspec))))
(defun lex--parse-re (string i lexer)
(let ((stack ())
(op nil)
(res nil)
tmp)
(while (and (not (eq op 'stop))
(setq tmp (lex-match-string lexer string i)))
(ecase (cdr tmp)
(shy-group
(setq tmp (lex--parse-re string (car tmp) lexer))
(unless (eq (aref string (1- (car tmp))) ?\))
(error "Unclosed shy-group"))
(push (cdr tmp) res))
(group
(setq tmp (lex--parse-re string (car tmp) lexer))
(unless (eq (aref string (1- (car tmp))) ?\))
(error "Unclosed shy-group"))
(push (list 'group (cdr tmp)) res))
(suffix
(if (null res) (error "Non-prefixed suffix operator")
(setq res (cons (list (cdr (assoc (substring string i (car tmp))
'(("*" . 0+)
("+" . 1+)
("?" . opt)
("*?" . *\?)
("+?" . +\?)
("??" . \?\?))))
(car res))
(cdr res)))))
(or (push `(or (seq ,@(nreverse res))) stack)
(setq res nil))
(charset
(push (lex--parse-charset (substring string (1+ i) (1- (car tmp))))
res))
(repeat
;; Here we would like to have sub-matches :-(
(let* ((min (string-to-number
(substring string (+ i (if (eq (aref string i) ?\\) 2=
1))
(car tmp))))
(max (let ((comma (string-match "," string i)))
(if (not (and comma (< comma (car tmp))))
min
(if (=3D comma (- (car tmp) 2))
nil
(string-to-number (substring string (1+ comma)))=
)))))
(if (null res) (error "Non-prefixed repeat operator")
(setq res (cons `(repeat ,min ,max ,(car res)) (cdr res))))))
(stop (setq op 'stop))
((syntax category not-syntax not-category)
(push (list (cdr tmp) (aref string (1- (car tmp)))) res))
(backref
(push (list (cdr tmp) (- (aref string (1- (car tmp))) ?0)) res))
(char
(push (aref string (1- (car tmp))) res))
(t (push (cdr tmp) res)))
(setq i (car tmp)))
(let ((re `(seq ,@(nreverse res))))
(while stack (setq re (nconc (pop stack) (list re))))
(cons i re))))
(defun lex-parse-re (string &optional lexer)
(setq lexer (cond ((eq lexer 'ere) lex--parse-ere-lexer)
((memq lexer '(bre re nil)) lex--parse-bre-lexer)
(t lexer)))
(let ((res (lex--parse-re string 0 lexer)))
(if (< (car res) (length string))
(error "Regexp parsing failed around %d: ...%s..."
(substring string (1- i) (1+ i)))
(cdr res))))
;; (defun lex--parse-re (string i)
;; (let ((stack ())
;; (op nil)
;; (res nil))
;; (while (and (not (eq op 'stop)))
;; (lex-case string i
;; ("(?:" ;shy-group.
;; (let ((tmp (lex--parse-re string i)))
;; (setq i (car tmp))
;; (unless (eq (aref string (1- i)) ?\)) (error "Unclosed shy-gr=
oup"))
;; (push (cdr tmp) res)))
;; ((or "*?" "+?" "??")
;; (error "Greediness control unsupported `%s'" (match-string 0 st=
ring)))
;; ((or "*" "+" "?")
;; (if (null res) (error "Non-prefixed suffix operator")
;; (setq res (cons (list (cdr (assq (aref string (1- i))
;; '((?* . 0+)
;; (?+ . 1+)
;; (?? . opt))))
;; (car res))
;; (cdr res)))))
;; ("|" (push `(or (seq ,@(nreverse res))) stack)
;; (setq res nil))
;; ((seq "[" (opt "^") (opt "]")
;; (0+ (or (seq (char not ?\]) "-" (char not ?\]))
;; (seq "[:" (1+ (char (?a . ?z) (?A . ?Z))) ":]=
")
;; (char not ?\]))) "]")
;; (push (lex--parse-charset
;; (substring string (1+ (match-beginning 0))
;; (1- (match-end 0))))
;; res))
;; ((seq "{" (0+ (char (?0 . ?9)))
;; (opt (seq "," (0+ (char (?0 . ?9))))) "}")
;; ;; Here we would like to have sub-matches :-(
;; (let* ((min (string-to-number (substring string
;; (1+ (match-beginning 0=
))
;; (match-end 0))))
;; (max (let ((comma (string-match "," string (match-beginn=
ing 0))))
;; (if (not (and comma (< comma (match-end 0))))
;; min
;; (if (=3D comma (- (match-end 0) 2))
;; nil
;; (string-to-number (substring string (1+ comma=
))))))))
;; (if (null res) (error "Non-prefixed repeat operator")
;; (setq res (cons `(repeat ,min ,max ,(car res)) (cdr res))))=
))
;; ((or ")" eob) (setq op 'stop))
;; ("\\'" (push 'eob res))
;; ("\\`" (push 'bob res))
;; ("^" (push 'bol res))
;; ("$" (push 'eol res))
;; ("." (push 'dot res))
;; ((or "(" "\\<" "\\>" "\\_<" "\\_>" "\\c" "\\s" "\\C" "\\S" "\\w"=
"\\W"
;; "\\b" "\\B" "\\=3D" (seq "\\" (char (?1 . ?9))))
;; (error "Unsupported construct `%s'" (match-string 0 string)))
;; ((or (seq ?\\ anything) anything)
;; (push (aref string (1- (match-end 0))) res))
;; ("" (error "This should not be reachable"))))
;; (let ((re `(seq ,@(nreverse res))))
;; (while stack (setq re (nconc (pop stack) (list re))))
;; (cons i re))))
(provide 'lex)
;;; lex.el ends here
--=-=-=--
Stefan Monnier <monnier <at> iro.umontreal.ca>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level: *
X-Spam-Status: No, score=1.6 required=4.0 tests=HTML_MESSAGE,SPF_HELO_PASS
autolearn=no version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 19:20:01 +0000
Received: from mail.42inc.com (mail.42inc.com [205.149.0.25])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BJJtVP025946
for <192 <at> emacsbugs.donarmstrong.com>; Sun, 11 May 2008 12:19:56 -0700
X-TFF-CGPSA-Version: 1.5
X-TFF-CGPSA-Filter-42inc: Scanned
X-42-Virus-Scanned: by 42 Antivirus -- Found to be clean.
Received: from [69.236.114.9] (account lord <at> emf.net HELO [192.168.1.64])
by mail.42inc.com (CommuniGate Pro SMTP 5.0.13)
with ESMTPA id 30292298; Sun, 11 May 2008 12:19:49 -0700
Message-ID: <482750F4.2050102 <at> emf.net>
Date: Sun, 11 May 2008 13:03:00 -0700
From: Thomas Lord <lord <at> emf.net>
User-Agent: Thunderbird 1.5.0.5 (X11/20060808)
MIME-Version: 1.0
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
CC: Chong Yidong <cyd <at> stupidchicken.com>, martin rudalics <rudalics <at> gmx.at>,
David Koppelman <koppel <at> ece.lsu.edu>, 192 <at> debbugs.gnu.org,
Bruno Haible <bruno <at> clisp.org>, emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com> <200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at> <yg5skwqc6ho.fsf <at> nested.ece.lsu.edu> <yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at> <87abiwoqzd.fsf <at> stupidchicken.com> <jwv8wygrbss.fsf-monnier+emacsbugreports <at> gnu.org>
In-Reply-To: <jwv8wygrbss.fsf-monnier+emacsbugreports <at> gnu.org>
Content-Type: multipart/alternative;
boundary="------------070006010001000508030704"
This is a multi-part message in MIME format.
--------------070006010001000508030704
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
>> As for making hi-lock-mode detect whether or not a regexp is multi-line,
>> isn't that a computationally non-trivial problem?
>>
>
> Well, you can turn the regexp into a DFA, then take the ".*\n.+" regexp,
> turn it into another DFA, take the intersection of the two DFAs, and if
> it's empty you know your regexp can never match a multiline element.
>
If you are going to go that that trouble, perhaps there is a better
solution:
The Rx pattern matcher found in distributions of GNU Arch has these
relevant capabilities (relevant at least so far as I understand the
problem you
are trying to solve):
1. It does on-the-fly regexp->DFA conversion, degrading gracefully into
mixed NFA/DFA mode or pure NFA mode if the DFA would be too
large. The calling program gets to say what "too large" is.
2. Although it is a C library, you can capture what is (in essence) the
continuation of an on-going match. That is, you can suspend a
match (or scan) part-way through, then later resume from that point,
perhaps multiple times. (This does not involve abusing the C stack.)
3. It does have some Unicode support in there and, though these capabilities
are under-tested and some features are missing, it is quite flexible
about
encoding forms.
4. The DFA construction is "caching" and, for a given regexp, all uses
will share the DFA construction. E.g., multiple, suspended regexp
continuations can be space efficient because they will share state.
5. Because of the caching and structure sharing, you can tell if two
continuations
from a single regexp have arrived at the same state with a C EQ test
("==").
How can this help?
Well, instead of using heuristics to decide where to re-scan from and
too, you
can cache a record of where the DFA scan arrived at for periodic
positions in the
buffer. Then begin scanning from just before any modification for as
far as it
takes to arrive at a DFA state that is the same as last time, updating
any highlighting
in the region between those two points.
I don't mean to imply that this is a trivial thing to implement in Emacs but
if you start getting up to building DFAs (very expensive in the worst
case) and
taking intersections (very expensive in the worst case) -- both also not
all that
simple to implement (nor obviously possible for Emacs' extended regexp
language) --
then the effort may be comparable and (re-)visiting the option to adapt
Rx to Emacs
should be worth considering.
As a point of amusement and credit where due, I think it was Jim Blandy
who first noticed this
possibility in the early 1990s when I was explaining to him the
capabilities I
was then just beginning to add to Rx.
This is a very old problem, long recognized, with some work already done on
a (purportedly) Right Thing solution.
-t
--------------070006010001000508030704
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
<title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
<br>
<blockquote cite="midjwv8wygrbss.fsf-monnier+emacsbugreports <at> gnu.org"
type="cite">
<blockquote type="cite">
<pre wrap="">As for making hi-lock-mode detect whether or not a regexp is multi-line,
isn't that a computationally non-trivial problem?
</pre>
</blockquote>
<pre wrap=""><!---->
Well, you can turn the regexp into a DFA, then take the ".*\n.+" regexp,
turn it into another DFA, take the intersection of the two DFAs, and if
it's empty you know your regexp can never match a multiline element.
</pre>
</blockquote>
<br>
If you are going to go that that trouble, perhaps there is a better
solution:<br>
<br>
The Rx pattern matcher found in distributions of GNU Arch has these <br>
relevant capabilities (relevant at least so far as I understand the
problem you<br>
are trying to solve):<br>
<br>
1. It does on-the-fly regexp->DFA conversion, degrading gracefully
into<br>
mixed NFA/DFA mode or pure NFA mode if the DFA would be too<br>
large. The calling program gets to say what "too large" is.<br>
<br>
2. Although it is a C library, you can capture what is (in essence) the<br>
continuation of an on-going match. That is, you can suspend a <br>
match (or scan) part-way through, then later resume from that point,<br>
perhaps multiple times. (This does not involve abusing the C
stack.)<br>
<br>
3. It does have some Unicode support in there and, though these
capabilities<br>
are under-tested and some features are missing, it is quite
flexible about<br>
encoding forms.<br>
<br>
4. The DFA construction is "caching" and, for a given regexp, all uses<br>
will share the DFA construction. E.g., multiple, suspended regexp
<br>
continuations can be space efficient because they will share state.<br>
<br>
5. Because of the caching and structure sharing, you can tell if two
continuations<br>
from a single regexp have arrived at the same state with a C EQ
test ("==").<br>
<br>
How can this help?<br>
<br>
Well, instead of using heuristics to decide where to re-scan from and
too, you<br>
can cache a record of where the DFA scan arrived at for periodic
positions in the<br>
buffer. Then begin scanning from just before any modification for as
far as it<br>
takes to arrive at a DFA state that is the same as last time, updating
any highlighting<br>
in the region between those two points.<br>
<br>
I don't mean to imply that this is a trivial thing to implement in
Emacs but<br>
if you start getting up to building DFAs (very expensive in the worst
case) and<br>
taking intersections (very expensive in the worst case) -- both also
not all that <br>
simple to implement (nor obviously possible for Emacs' extended regexp
language) --<br>
then the effort may be comparable and (re-)visiting the option to adapt
Rx to Emacs<br>
should be worth considering.<br>
<br>
As a point of amusement and credit where due, I think it was Jim Blandy
who first noticed this <br>
possibility in the early 1990s when I was explaining to him the
capabilities I<br>
was then just beginning to add to Rx.<br>
<br>
This is a very old problem, long recognized, with some work already
done on<br>
a (purportedly) Right Thing solution.<br>
<br>
-t<br>
<br>
<br>
</body>
</html>
--------------070006010001000508030704--
Thomas Lord <lord <at> emf.net>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.5 required=4.0 tests=AWL,FOURLA autolearn=no
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 19:09:37 +0000
Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BJ9Wuu024698
for <192 <at> emacsbugs.donarmstrong.com>; Sun, 11 May 2008 12:09:34 -0700
Received: from localhost (unknown [127.0.0.1])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id A955E28350;
Sun, 11 May 2008 19:09:32 +0000 (UTC)
X-Virus-Scanned: amavisd-new at ece.lsu.edu
Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1])
by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id fr7PlMx0JlAw; Sun, 11 May 2008 14:09:32 -0500 (CDT)
Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id C5F1D2833B;
Sun, 11 May 2008 14:09:31 -0500 (CDT)
From: David Koppelman <koppel <at> ece.lsu.edu>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: Chong Yidong <cyd <at> stupidchicken.com>, martin rudalics <rudalics <at> gmx.at>,
192 <at> debbugs.gnu.org, Bruno Haible <bruno <at> clisp.org>,
emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
<yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at>
<87abiwoqzd.fsf <at> stupidchicken.com>
<yg57ie0df8u.fsf <at> nested.ece.lsu.edu>
<jwv4p94r8vp.fsf-monnier+emacsbugreports <at> gnu.org>
Date: Sun, 11 May 2008 14:09:31 -0500
In-Reply-To: <jwv4p94r8vp.fsf-monnier+emacsbugreports <at> gnu.org> (Stefan
Monnier's message of "Sun, 11 May 2008 14:44:12 -0400")
Message-ID: <yg5tzh4bqtw.fsf <at> nested.ece.lsu.edu>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
I've decided against having hi-lock turn on font-lock-multiline or
even apply font-lock-multiline text properties, too much potential to
slow things down to a crawl when an unsuspecting user enters a regexp.
If I understand things correctly, the font-lock-multiline property is
used to extend a region to be fontified, a region to be used for *all*
keywords. This would have disastrous effects when multi-line patterns
span, say, 100's of lines for modes with hundreds of keywords. I had
been toying with the idea of limiting extended regions to something
like 100 lines, but that still seems wasteful when most keywords are
single line (I haven't benchmarked anything yet).
A better solution would be to have font-lock use multi-line extended
regions selectively. Perhaps a hint in the current keyword syntax
(say, explicitly applying the font-lock-multiline property), or a
separate method for providing multi-line keywords to font-lock.
Such keywords would get the multi-line extended regions, the other
just the whole-line extensions (or whatever the hooks do).
Is this something the font-lock maintainers would consider?
What I'll do now is just document the limitations for hi-lock and
perhaps provide a warning when a multiline pattern is used.
> That may not be enough. You'll probably want to do something like what
> smerge does:
>
> (while (re-search-forward <RE> nil t)
> (font-lock-fontify-region (match-beginning 0) (match-end 0)))
I wouldn't do that without suppressing other keywords.
> If someone wants that, I have a parser that takes a regexp and turns it
> into something like `rx' syntax. It uses my lex.el library (which
> takes an `rx'-like input syntax).
That sounds useful, either E-mail it to me or let me know
where to find it.
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:
>> My latest plan is to do what Chong Yidong suggests, setting up text
>> properties so that font-lock DTRT, though it doesn't seem as hard as he
>> suggests (I'm still in the naive enthusiasm stage).
>
> Indeed, it shouldn't be that hard.
>
>> I tried adding the font-lock-multiline property to the face property
>> list passed to font lock and that did the trick, even with the
>> font-lock-multiline variable nil.
>
> That may not be enough. You'll probably want to do something like what
> smerge does:
>
> (while (re-search-forward <RE> nil t)
> (font-lock-fontify-region (match-beginning 0) (match-end 0)))
>
> this will find all the multiline elements. And the font-lock-multiline
> property you add will make sure that those that were found will not
> disappear accidentally because of some later refontification.
>
>> I rather do that than turn on font-lock-multiline because I'm assuming
>> that font-lock-multiline is set to nil in most cases for
>> a good reason.
>
> Setting the `font-lock-multiline' variable to t has a performance cost.
>
>> I actually thought about properly parsing the regexp, but the effort to
>> do that could be spent on making multi-line patterns work properly, at
>> least if they don't span too many lines.
>
> If someone wants that, I have a parser that takes a regexp and turns it
> into something like `rx' syntax. It uses my lex.el library (which
> takes an `rx'-like input syntax).
>
>> One more thing, multi-line regexp matches don't work properly even
>> with font-lock-multiline t when jit-lock is being used in a buffer
>> without syntactic fontification and using the default setting of
>> jit-lock-contextually, setting it to t gets multi-line fontification
>> to work.
>
> The `font-lock-multiline' variable only tells font-lock that if it ever
> bumps into a multiline element, it should mark it (with the
> font-lock-multiline property) so that it will not re-fontify it as
> a whole if it ever needs to refontify it.
>
> So it doesn't solve the problem of "how do I make sure that font-lock
> indeed finds the multiline element". Multiline elements can only be
> found when font-locking a large enough piece of text, which tends to
> only happen during the initial fontification, or during background or
> contextual refontification, or during an explicit call such as in the
> above while loop.
>
>
> Stefan
David Koppelman <koppel <at> ece.lsu.edu>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.4 required=4.0 tests=AWL autolearn=ham
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 18:45:04 +0000
Received: from ironport2-out.teksavvy.com (ironport2-out.teksavvy.com [206.248.154.182])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BIj0MB020866
for <192 <at> emacsbugs.donarmstrong.com>; Sun, 11 May 2008 11:45:02 -0700
X-IronPort-Anti-Spam-Filtered: true
X-IronPort-Anti-Spam-Result: AmoCABPbJkjO+JgrdGdsb2JhbACBU5A5ASeXBA
X-IronPort-AV: E=Sophos;i="4.27,469,1204520400";
d="scan'208";a="20288327"
Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238])
by ironport2-out.teksavvy.com with ESMTP; 11 May 2008 14:44:55 -0400
Received: from pastel.home ([206.248.152.43])
by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id RXD67155;
Sun, 11 May 2008 14:44:55 -0400
Received: by pastel.home (Postfix, from userid 20848)
id 32B438265; Sun, 11 May 2008 14:44:55 -0400 (EDT)
From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Chong Yidong <cyd <at> stupidchicken.com>
Cc: martin rudalics <rudalics <at> gmx.at>, David Koppelman <koppel <at> ece.lsu.edu>,
192 <at> debbugs.gnu.org, Bruno Haible <bruno <at> clisp.org>,
emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
Message-ID: <jwv8wygrbss.fsf-monnier+emacsbugreports <at> gnu.org>
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
<yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at>
<87abiwoqzd.fsf <at> stupidchicken.com>
Date: Sun, 11 May 2008 14:44:55 -0400
In-Reply-To: <87abiwoqzd.fsf <at> stupidchicken.com> (Chong Yidong's message of
"Sun, 11 May 2008 10:27:50 -0400")
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
> As for making hi-lock-mode detect whether or not a regexp is multi-line,
> isn't that a computationally non-trivial problem?
Well, you can turn the regexp into a DFA, then take the ".*\n.+" regexp,
turn it into another DFA, take the intersection of the two DFAs, and if
it's empty you know your regexp can never match a multiline element.
Stefan
Stefan Monnier <monnier <at> iro.umontreal.ca>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.5 required=4.0 tests=AWL,FOURLA autolearn=no
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 18:44:22 +0000
Received: from ironport2-out.teksavvy.com (ironport2-out.pppoe.ca [206.248.154.182])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BIiINA020859
for <192 <at> emacsbugs.donarmstrong.com>; Sun, 11 May 2008 11:44:20 -0700
X-IronPort-Anti-Spam-Filtered: true
X-IronPort-Anti-Spam-Result: AmoCABPbJkjO+JgrdGdsb2JhbACBU5A5ASeXBA
X-IronPort-AV: E=Sophos;i="4.27,469,1204520400";
d="scan'208";a="20288304"
Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238])
by ironport2-out.teksavvy.com with ESMTP; 11 May 2008 14:44:12 -0400
Received: from pastel.home ([206.248.152.43])
by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id RXD65612;
Sun, 11 May 2008 14:44:12 -0400
Received: by pastel.home (Postfix, from userid 20848)
id 25DDD8265; Sun, 11 May 2008 14:44:12 -0400 (EDT)
From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: David Koppelman <koppel <at> ece.lsu.edu>
Cc: Chong Yidong <cyd <at> stupidchicken.com>, martin rudalics <rudalics <at> gmx.at>,
192 <at> debbugs.gnu.org, Bruno Haible <bruno <at> clisp.org>,
emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
Message-ID: <jwv4p94r8vp.fsf-monnier+emacsbugreports <at> gnu.org>
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
<yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at>
<87abiwoqzd.fsf <at> stupidchicken.com>
<yg57ie0df8u.fsf <at> nested.ece.lsu.edu>
Date: Sun, 11 May 2008 14:44:12 -0400
In-Reply-To: <yg57ie0df8u.fsf <at> nested.ece.lsu.edu> (David Koppelman's message
of "Sun, 11 May 2008 10:36:49 -0500")
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
> My latest plan is to do what Chong Yidong suggests, setting up text
> properties so that font-lock DTRT, though it doesn't seem as hard as he
> suggests (I'm still in the naive enthusiasm stage).
Indeed, it shouldn't be that hard.
> I tried adding the font-lock-multiline property to the face property
> list passed to font lock and that did the trick, even with the
> font-lock-multiline variable nil.
That may not be enough. You'll probably want to do something like what
smerge does:
(while (re-search-forward <RE> nil t)
(font-lock-fontify-region (match-beginning 0) (match-end 0)))
this will find all the multiline elements. And the font-lock-multiline
property you add will make sure that those that were found will not
disappear accidentally because of some later refontification.
> I rather do that than turn on font-lock-multiline because I'm assuming
> that font-lock-multiline is set to nil in most cases for
> a good reason.
Setting the `font-lock-multiline' variable to t has a performance cost.
> I actually thought about properly parsing the regexp, but the effort to
> do that could be spent on making multi-line patterns work properly, at
> least if they don't span too many lines.
If someone wants that, I have a parser that takes a regexp and turns it
into something like `rx' syntax. It uses my lex.el library (which
takes an `rx'-like input syntax).
> One more thing, multi-line regexp matches don't work properly even
> with font-lock-multiline t when jit-lock is being used in a buffer
> without syntactic fontification and using the default setting of
> jit-lock-contextually, setting it to t gets multi-line fontification
> to work.
The `font-lock-multiline' variable only tells font-lock that if it ever
bumps into a multiline element, it should mark it (with the
font-lock-multiline property) so that it will not re-fontify it as
a whole if it ever needs to refontify it.
So it doesn't solve the problem of "how do I make sure that font-lock
indeed finds the multiline element". Multiline elements can only be
found when font-locking a large enough piece of text, which tends to
only happen during the initial fontification, or during background or
contextual refontification, or during an explicit call such as in the
above while loop.
Stefan
Stefan Monnier <monnier <at> iro.umontreal.ca>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.7 required=4.0 tests=AWL,FOURLA autolearn=no
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 15:36:54 +0000
Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BFao0n028407
for <192 <at> emacsbugs.donarmstrong.com>; Sun, 11 May 2008 08:36:51 -0700
Received: from localhost (unknown [127.0.0.1])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 6B1DB2833D;
Sun, 11 May 2008 15:36:50 +0000 (UTC)
X-Virus-Scanned: amavisd-new at ece.lsu.edu
Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1])
by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id wJjrDJ2jbWh7; Sun, 11 May 2008 10:36:49 -0500 (CDT)
Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id BDC2428316;
Sun, 11 May 2008 10:36:49 -0500 (CDT)
From: David Koppelman <koppel <at> ece.lsu.edu>
To: Chong Yidong <cyd <at> stupidchicken.com>
Cc: martin rudalics <rudalics <at> gmx.at>, 192 <at> debbugs.gnu.org,
Bruno Haible <bruno <at> clisp.org>, emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
<yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at>
<87abiwoqzd.fsf <at> stupidchicken.com>
Date: Sun, 11 May 2008 10:36:49 -0500
In-Reply-To: <87abiwoqzd.fsf <at> stupidchicken.com> (Chong Yidong's message of
"Sun, 11 May 2008 10:27:50 -0400")
Message-ID: <yg57ie0df8u.fsf <at> nested.ece.lsu.edu>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
I agree pretty much with everything Chong Yidong writes.
I rather not bother the user with an additional question if I don't
have to, the alternative would be a warning.
My latest plan is to do what Chong Yidong suggests, setting up text
properties so that font-lock DTRT, though it doesn't seem as hard as he
suggests (I'm still in the naive enthusiasm stage). I tried adding the
font-lock-multiline property to the face property list passed to font
lock and that did the trick, even with the font-lock-multiline variable
nil. I rather do that than turn on font-lock-multiline because I'm
assuming that font-lock-multiline is set to nil in most cases for a good
reason.
Rather than perfectly distinguishing multi-line from single line
patterns guessing would be good enough for hi-lock. I'm using the
following regexp,
"\\(\n.\\|\\\\W[*+]\\|\\\\[SC].[*+]\\|\\[\\^[^]]+\\][+*]\\)", which
hopefully isn't too far from covering a large majority of interactively
entered patterns.
I actually thought about properly parsing the regexp, but the effort to
do that could be spent on making multi-line patterns work properly, at
least if they don't span too many lines.
One more thing, multi-line regexp matches don't work properly even with
font-lock-multiline t when jit-lock is being used in a buffer without
syntactic fontification and using the default setting of
jit-lock-contextually, setting it to t gets multi-line fontification to
work.
I plan to play around a bit more and come up with something,
maybe today, maybe early this week.
Chong Yidong <cyd <at> stupidchicken.com> writes:
> Ideally, highlight-regexp should work automagically, instead of forcing
> users to do something extra to make their multi-line regexp work
> properly. The right way to do this is probably for hi-lock-mode to
> process the buffer initially, setting up text properties to make
> font-lock DTRT even for multi-line expressions. But that's a big job.
>
> As for making hi-lock-mode detect whether or not a regexp is multi-line,
> isn't that a computationally non-trivial problem?
>
> Maybe making hi-lock-mode turn on font-lock-multiline, while not
> foolproof, works often enough to be satisfactory.
David Koppelman <koppel <at> ece.lsu.edu>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level: **
X-Spam-Status: No, score=2.5 required=4.0 tests=AWL,FOURLA,RCVD_IN_PBL,
RCVD_IN_SORBS_DUL,RDNS_DYNAMIC autolearn=no
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 14:27:59 +0000
Received: from furry (c-98-216-111-182.hsd1.ma.comcast.net [98.216.111.182])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4BERuAW018939
for <192 <at> emacsbugs.donarmstrong.com>; Sun, 11 May 2008 07:27:57 -0700
Received: by furry (Postfix, from userid 1000)
id AF917C049; Sun, 11 May 2008 10:27:50 -0400 (EDT)
From: Chong Yidong <cyd <at> stupidchicken.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: David Koppelman <koppel <at> ece.lsu.edu>, 192 <at> debbugs.gnu.org,
Bruno Haible <bruno <at> clisp.org>, emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
<yg5bq3ddij2.fsf <at> nested.ece.lsu.edu> <4826A303.3030002 <at> gmx.at>
Date: Sun, 11 May 2008 10:27:50 -0400
In-Reply-To: <4826A303.3030002 <at> gmx.at> (martin rudalics's message of "Sun, 11
May 2008 09:40:51 +0200")
Message-ID: <87abiwoqzd.fsf <at> stupidchicken.com>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
martin rudalics <rudalics <at> gmx.at> writes:
>> First I'll work on the hi-lock warning as I described below, then I'll
>> see about detecting and doing something helpful for additional
>> situations where multi-line won't work.
>
> Think of the following pathological case: Devise a regexp to highlight
> the first line of a buffer provided the buffer does not end with a
> newline. Doing this with `font-lock-multiline' hardly makes any sense.
Ideally, highlight-regexp should work automagically, instead of forcing
users to do something extra to make their multi-line regexp work
properly. The right way to do this is probably for hi-lock-mode to
process the buffer initially, setting up text properties to make
font-lock DTRT even for multi-line expressions. But that's a big job.
As for making hi-lock-mode detect whether or not a regexp is multi-line,
isn't that a computationally non-trivial problem?
Maybe making hi-lock-mode turn on font-lock-multiline, while not
foolproof, works often enough to be satisfactory.
Chong Yidong <cyd <at> stupidchicken.com>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=-0.3 required=4.0 tests=AWL autolearn=ham
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 11 May 2008 07:51:47 +0000
Received: from mail.gmx.net (mail.gmx.net [213.165.64.20])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with SMTP id m4B7phk5029151
for <192 <at> emacsbugs.donarmstrong.com>; Sun, 11 May 2008 00:51:44 -0700
Received: (qmail invoked by alias); 11 May 2008 07:51:37 -0000
Received: from 62-47-54-236.adsl.highway.telekom.at (EHLO [62.47.54.236]) [62.47.54.236]
by mail.gmx.net (mp009) with SMTP; 11 May 2008 09:51:37 +0200
X-Authenticated: #14592706
X-Provags-ID: V01U2FsdGVkX1/M86d9vM3MXw7/M9IHRmbR1f3AF9VIIiYJzNfGw9
uwHW00ggCpiGAW
Message-ID: <4826A303.3030002 <at> gmx.at>
Date: Sun, 11 May 2008 09:40:51 +0200
From: martin rudalics <rudalics <at> gmx.at>
User-Agent: Mozilla Thunderbird 1.0 (Windows/20041206)
X-Accept-Language: de-DE, de, en-us, en
MIME-Version: 1.0
To: David Koppelman <koppel <at> ece.lsu.edu>
CC: Chong Yidong <cyd <at> stupidchicken.com>, 192 <at> debbugs.gnu.org,
Bruno Haible <bruno <at> clisp.org>, emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com> <200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at> <yg5skwqc6ho.fsf <at> nested.ece.lsu.edu> <yg5bq3ddij2.fsf <at> nested.ece.lsu.edu>
In-Reply-To: <yg5bq3ddij2.fsf <at> nested.ece.lsu.edu>
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
X-Y-GMX-Trusted: 0
> First I'll work on the hi-lock warning as I described below, then I'll
> see about detecting and doing something helpful for additional
> situations where multi-line won't work.
Think of the following pathological case: Devise a regexp to highlight
the first line of a buffer provided the buffer does not end with a
newline. Doing this with `font-lock-multiline' hardly makes any sense.
Maybe users should classify whether a regexp they use
(1) doesn't match newlines - no `font-lock-multiline' needed,
(2) match at most n newlines in which case you should tell font-lock to
rescan from n lines before each buffer change (with large n the display
engine will suffer noticeably, mainly because font-lock has to search
for all other keywords as well), or
(3) may match more than n newlines in which case you should use an idle
timer to scan the entire buffer for any matches of such regexps and
highlight them separately.
martin rudalics <rudalics <at> gmx.at>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level: *
X-Spam-Status: No, score=1.2 required=4.0 tests=AWL,IMPRONONCABLE_1,
MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 10 May 2008 20:13:41 +0000
Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4AKDbNZ031175
for <192 <at> emacsbugs.donarmstrong.com>; Sat, 10 May 2008 13:13:39 -0700
Received: from localhost (unknown [127.0.0.1])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id B7D0E2839E;
Sat, 10 May 2008 20:13:37 +0000 (UTC)
X-Virus-Scanned: amavisd-new at ece.lsu.edu
Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1])
by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id fh7l+otWzISs; Sat, 10 May 2008 15:13:37 -0500 (CDT)
Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 186F728018;
Sat, 10 May 2008 15:13:37 -0500 (CDT)
From: David Koppelman <koppel <at> ece.lsu.edu>
To: martin rudalics <rudalics <at> gmx.at>
Cc: Chong Yidong <cyd <at> stupidchicken.com>, 192 <at> debbugs.gnu.org,
Bruno Haible <bruno <at> clisp.org>, emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
<yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
Date: Sat, 10 May 2008 15:13:37 -0500
In-Reply-To: <yg5skwqc6ho.fsf <at> nested.ece.lsu.edu> (David Koppelman's message
of "Sat, 10 May 2008 14:18:59 -0500")
Message-ID: <yg5bq3ddij2.fsf <at> nested.ece.lsu.edu>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
I *am* able to reproduce the font-lock-multiline limitation martin
described if the buffer is in text mode. I had tried to reproduce it
in emacs-lisp mode.
First I'll work on the hi-lock warning as I described below, then I'll
see about detecting and doing something helpful for additional
situations where multi-line won't work.
David Koppelman <koppel <at> ece.lsu.edu> writes:
> I was able to reproduce the problem with Bruno Haible's testcase and
> font-lock-multiline t does "fix" it. However martin rudalics warns that
> font-lock-multiline won't work for all cases and provides an example
> idea (below). I can't get that to fail. That is, with
> font-lock-multiline t the text was correctly fontified (though after a
> pause). My realization of the example was to remove and then add the
> first quotation mark from one of the interior lines below (also
> tried with more quoted lines):
>
> msgstr ""
> "Project-Id-Version: GNU gettext-tools 0.16.2-pre5\n"
> "Report-Msgid-Bugs-To: bug-gnu-gettext <at> gnu.org\n"
> "POT-Creation-Date: 2007-11-02 03:23+0100\n"
> "PO-Revision-Date: 2007-10-27 13:35+0200\n"
> "Last-Translator: Christophe Combelles <ccomb <at> free.fr>\n"
> "Last-Translator: Christophe Combelles <ccomb <at> free.fr>\n"
> x
>
> The fix I'm contemplating would be to warn the user when a multi-line
> regexp was added interactively and font-lock-multiline was nil, and then
> perhaps to offer to set font-lock-multiline to t (or to not set it, or
> to stop asking).
David Koppelman <koppel <at> ece.lsu.edu>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.5 required=4.0 tests=AWL,HS_INDEX_PARAM
autolearn=ham version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 10 May 2008 20:05:12 +0000
Received: from mo-p07-ob.rzone.de (mo-p07-ob.rzone.de [81.169.146.190])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4AK51wB029219
for <192 <at> emacsbugs.donarmstrong.com>; Sat, 10 May 2008 13:05:03 -0700
X-RZG-CLASS-ID: mo07
X-RZG-AUTH: gMysVb8JT2gB+rFDu0PuvnvUUGmhfq1rhHRG5dSek381RH36MmDLfffX7Q==
Received: from linuix.haible.de
(dslb-084-058-084-213.pools.arcor-ip.net [84.58.84.213])
by post.webmailer.de (klopstock mo57) (RZmta 16.34)
with ESMTP id w04302k4AHYv6T ; Sat, 10 May 2008 22:04:59 +0200 (MEST)
(envelope-from: <bruno <at> clisp.org>)
From: Bruno Haible <bruno <at> clisp.org>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: regexp does not work as documented
Date: Sat, 10 May 2008 22:04:56 +0200
User-Agent: KMail/1.5.4
Cc: Chong Yidong <cyd <at> stupidchicken.com>, emacs-devel <at> gnu.org,
koppel <at> ece.lsu.edu, 192 <at> debbugs.gnu.org
References: <87k5i8ukq8.fsf <at> stupidchicken.com> <200805061335.11379.bruno <at> clisp.org> <jwvfxsvbgg5.fsf-monnier+emacs <at> gnu.org>
In-Reply-To: <jwvfxsvbgg5.fsf-monnier+emacs <at> gnu.org>
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Message-Id: <200805102204.56980.bruno <at> clisp.org>
Stefan Monnier wrote:
> > - I originally observed the bug in po-mode (part of GNU gettext), in
> > a function po-find-span-of-entry which essentially only calls
> > re-search-backward and re-search-forward.
>
> Please try and reproduce the problem there and send us a recipe.
After deeper investigation, the bug in po-mode was not directly related:
I had used a regexp which was not designed for use with re-search-backward.
This bug is closed now. <https://savannah.gnu.org/bugs/?23177>
Thank you Stefan for bringing me on the right track.
Bruno
Bruno Haible <bruno <at> clisp.org>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level: *
X-Spam-Status: No, score=1.3 required=4.0 tests=FOURLA,IMPRONONCABLE_1,
MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 10 May 2008 19:19:04 +0000
Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4AJJ0xp023742
for <192 <at> emacsbugs.donarmstrong.com>; Sat, 10 May 2008 12:19:02 -0700
Received: from localhost (unknown [127.0.0.1])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 676AF2839E;
Sat, 10 May 2008 19:19:00 +0000 (UTC)
X-Virus-Scanned: amavisd-new at ece.lsu.edu
Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1])
by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id D1Vpz2MRw8ec; Sat, 10 May 2008 14:18:59 -0500 (CDT)
Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id B248A28336;
Sat, 10 May 2008 14:18:59 -0500 (CDT)
From: David Koppelman <koppel <at> ece.lsu.edu>
To: martin rudalics <rudalics <at> gmx.at>
Cc: Bruno Haible <bruno <at> clisp.org>, Chong Yidong <cyd <at> stupidchicken.com>,
192 <at> debbugs.gnu.org, emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org> <48204B3D.6000500 <at> gmx.at>
Date: Sat, 10 May 2008 14:18:59 -0500
In-Reply-To: <48204B3D.6000500 <at> gmx.at> (martin rudalics's message of "Tue, 06
May 2008 14:12:45 +0200")
Message-ID: <yg5skwqc6ho.fsf <at> nested.ece.lsu.edu>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
I was able to reproduce the problem with Bruno Haible's testcase and
font-lock-multiline t does "fix" it. However martin rudalics warns that
font-lock-multiline won't work for all cases and provides an example
idea (below). I can't get that to fail. That is, with
font-lock-multiline t the text was correctly fontified (though after a
pause). My realization of the example was to remove and then add the
first quotation mark from one of the interior lines below (also
tried with more quoted lines):
msgstr ""
"Project-Id-Version: GNU gettext-tools 0.16.2-pre5\n"
"Report-Msgid-Bugs-To: bug-gnu-gettext <at> gnu.org\n"
"POT-Creation-Date: 2007-11-02 03:23+0100\n"
"PO-Revision-Date: 2007-10-27 13:35+0200\n"
"Last-Translator: Christophe Combelles <ccomb <at> free.fr>\n"
"Last-Translator: Christophe Combelles <ccomb <at> free.fr>\n"
x
The fix I'm contemplating would be to warn the user when a multi-line
regexp was added interactively and font-lock-multiline was nil, and then
perhaps to offer to set font-lock-multiline to t (or to not set it, or
to stop asking).
martin rudalics <rudalics <at> gmx.at> writes:
>> Can someone help me find a workaround, then? If not, I would have to give up
>> maintaining po-mode as part of GNU gettext. Said function is central in
>> Emacs po-mode (everything else relies on it), and if multi-line regular
>> expressions don't work, I don't know how this function could be rewritten.
>
> Don't worry, Stefan will find the solution. First of all you will
> probably have to
>
> (setq font-lock-multiline t)
>
> in the respective buffer. This will _not_ always DTRT after a buffer
> modification, as, for example, in
>
> AAAA
>
> CCCC
>
> BBBB
>
> where AAAA stands for some old text previously matched by your regexp,
> CCCC for some new text inserted (or old text removed), and BBBB for some
> text which, after the change, is now matched by the regexp (or not
> matched any more): In this case BBBB will be wrongly highlighted now.
> Alan uses the notorious
>
> `font-lock-extend-jit-lock-region-after-change'
>
> function to handle this, but it's not immediately clear how to apply
> this here. If everything else fails you will have to refontify till
> `window-end' (I prefer using a timer for such refontifications).
David Koppelman <koppel <at> ece.lsu.edu>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.3 required=4.0 tests=AWL autolearn=ham
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 7 May 2008 01:04:43 +0000
Received: from ironport2-out.teksavvy.com (ironport2-out.pppoe.ca [206.248.154.182])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m4714bMg015831
for <192 <at> emacsbugs.donarmstrong.com>; Tue, 6 May 2008 18:04:39 -0700
X-IronPort-Anti-Spam-Filtered: true
X-IronPort-Anti-Spam-Result: AgoFAJudIEhMCqqd/2dsb2JhbACBU6tP
X-IronPort-AV: E=Sophos;i="4.27,445,1204520400";
d="scan'208";a="20001743"
Received: from smtp.pppoe.ca (HELO smtp.teksavvy.com) ([65.39.196.238])
by ironport2-out.teksavvy.com with ESMTP; 06 May 2008 21:04:19 -0400
Received: from pastel.home ([76.10.170.157])
by smtp.teksavvy.com (Internet Mail Server v1.0) with ESMTP id NGL75019;
Tue, 06 May 2008 21:04:19 -0400
Received: by pastel.home (Postfix, from userid 20848)
id 688597FFC; Tue, 6 May 2008 21:04:19 -0400 (EDT)
From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Bruno Haible <bruno <at> clisp.org>
Cc: David Koppelman <koppel <at> ece.lsu.edu>, Chong Yidong <cyd <at> stupidchicken.com>,
192 <at> debbugs.gnu.org, emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
Message-ID: <jwviqxrj5ap.fsf-monnier+emacsbugreports <at> gnu.org>
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<yg563trfpfn.fsf <at> nested.ece.lsu.edu>
<200805062335.59206.bruno <at> clisp.org>
Date: Tue, 06 May 2008 21:04:19 -0400
In-Reply-To: <200805062335.59206.bruno <at> clisp.org> (Bruno Haible's message of
"Tue, 6 May 2008 23:35:59 +0200")
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
> As an end user, for testing the effect of a regexp on a buffer interactively,
> I would prefer to have a "volatile" coloring (i.e. one that disappears at the
> next buffer modification) but is correct, rather than a documented-to-be-wrong
> coloring that updates itself correctly during buffer modifications. Less
> functionality but implemented correctly.
Actually, we can get the combination of the two. hilight-changes
(c|sh)ould use its own loop with re-search-forward, even when font-lock
is enabled. This way the highlighting would be initially correct, and
in some cases it would also be correctly preserved/discovered later on.
This would only be used for regexp that can span multiple lines, so
highlight-changes (c|sh)ould analyse the regexp to see if there's
a possibility for it to match multiple lines.
Stefan
Stefan Monnier <monnier <at> iro.umontreal.ca>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.Received: (at unknown) by unknown; unknown X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02 (2007-08-08) on rzlab.ucr.edu X-Spam-Level: X-Spam-Status: No, score=0.7 required=4.0 tests=AWL,FOURLA autolearn=no version=3.2.3-bugs.debian.org_2005_01_02 Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 21:36:10 +0000 Received: from mo-p07-ob.rzone.de (mo-p07-ob.rzone.de [81.169.146.190]) by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m46La3Nk008122 for <192 <at> emacsbugs.donarmstrong.com>; Tue, 6 May 2008 14:36:05 -0700 X-RZG-CLASS-ID: mo07 X-RZG-AUTH: gMysVb8JT2gB+rFDu0PuvnvUUGmhfq1rhHRG5dSek381RH36PlIq8YOI Received: from linuix.haible.de (dslb-084-058-049-074.pools.arcor-ip.net [84.58.49.74]) by post.webmailer.de (mrclete mo25) (RZmta 16.34) with ESMTP id 200896k46K3sKd ; Tue, 6 May 2008 23:36:02 +0200 (MEST) (envelope-from: <bruno <at> clisp.org>) From: Bruno Haible <bruno <at> clisp.org> To: David Koppelman <koppel <at> ece.lsu.edu>, Chong Yidong <cyd <at> stupidchicken.com> Subject: Re: regexp does not work as documented Date: Tue, 6 May 2008 23:35:59 +0200 User-Agent: KMail/1.5.4 Cc: emacs-devel <at> gnu.org, 192 <at> debbugs.gnu.org References: <87k5i8ukq8.fsf <at> stupidchicken.com> <yg563trfpfn.fsf <at> nested.ece.lsu.edu> In-Reply-To: <yg563trfpfn.fsf <at> nested.ece.lsu.edu> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <200805062335.59206.bruno <at> clisp.org> David Koppelman wrote: > Later in the week I'll look into it and provide either a fix > or document the limitation. Thank you! Chong Yidong wrote: > > OTOH, I don't see what we can do about this problem. Maybe we could add > > a note to the docstring of highlight-regexp saying that multi-line > > regular expressions are problematic? Does anyone have a suggestion? As an end user, for testing the effect of a regexp on a buffer interactively, I would prefer to have a "volatile" coloring (i.e. one that disappears at the next buffer modification) but is correct, rather than a documented-to-be-wrong coloring that updates itself correctly during buffer modifications. Less functionality but implemented correctly. OTOH, third-party packages may prefer the current behaviour if their regexps match only portions of a line. Bruno
Bruno Haible <bruno <at> clisp.org>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.9 required=4.0 tests=AWL autolearn=ham
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 21:29:16 +0000
Received: from mo-p07-ob.rzone.de (mo-p07-ob.rzone.de [81.169.146.188])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m46LTAsg005137
for <192 <at> emacsbugs.donarmstrong.com>; Tue, 6 May 2008 14:29:12 -0700
X-RZG-CLASS-ID: mo07
X-RZG-AUTH: gMysVb8JT2gB+rFDu0PuvnvUUGmhfq1rhHRG5dSek381RH36PlIq8YOI
Received: from linuix.haible.de
(dslb-084-058-049-074.pools.arcor-ip.net [84.58.49.74])
by post.webmailer.de (mrclete mo31) (RZmta 16.34)
with ESMTP id e00c19k46Jj1i6 ; Tue, 6 May 2008 23:29:08 +0200 (MEST)
(envelope-from: <bruno <at> clisp.org>)
From: Bruno Haible <bruno <at> clisp.org>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Subject: Re: regexp does not work as documented
Date: Tue, 6 May 2008 23:29:05 +0200
User-Agent: KMail/1.5.4
Cc: Chong Yidong <cyd <at> stupidchicken.com>, emacs-devel <at> gnu.org,
koppel <at> ece.lsu.edu, 192 <at> debbugs.gnu.org
References: <87k5i8ukq8.fsf <at> stupidchicken.com> <200805061335.11379.bruno <at> clisp.org> <jwvfxsvbgg5.fsf-monnier+emacs <at> gnu.org>
In-Reply-To: <jwvfxsvbgg5.fsf-monnier+emacs <at> gnu.org>
MIME-Version: 1.0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
Message-Id: <200805062329.05484.bruno <at> clisp.org>
Stefan Monnier wrote:
> Actually, font-lock-fontified is most likely set to t, so
> hi-lock-set-pattern doesn't call re-sarch-forward at all and only calls
> font-lock-fontify-buffer instead.
You're right: If I do a
M-x evaluate-expression (setq font-lock-fontify-buffer nil)
before
M-x highlight-regexp
the result is correct. So the problem is indeed with the font-locking.
Bruno
Bruno Haible <bruno <at> clisp.org>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=-0.5 required=4.0 tests=AWL autolearn=ham
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 15:35:20 +0000
Received: from mercure.iro.umontreal.ca (mercure.iro.umontreal.ca [132.204.24.67])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m46FZGQm011376
for <192 <at> emacsbugs.donarmstrong.com>; Tue, 6 May 2008 08:35:18 -0700
Received: from hidalgo.iro.umontreal.ca (hidalgo.iro.umontreal.ca [132.204.27.50])
by mercure.iro.umontreal.ca (Postfix) with ESMTP id 374782CF324;
Tue, 6 May 2008 11:35:14 -0400 (EDT)
Received: from faina.iro.umontreal.ca (faina.iro.umontreal.ca [132.204.26.177])
by hidalgo.iro.umontreal.ca (Postfix) with ESMTP id 3BAE73FE0;
Tue, 6 May 2008 11:35:01 -0400 (EDT)
Received: by faina.iro.umontreal.ca (Postfix, from userid 20848)
id 268DC41BEC; Tue, 6 May 2008 11:35:01 -0400 (EDT)
From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Bruno Haible <bruno <at> clisp.org>
Cc: Chong Yidong <cyd <at> stupidchicken.com>, emacs-devel <at> gnu.org,
koppel <at> ece.lsu.edu, 192 <at> debbugs.gnu.org
Subject: Re: regexp does not work as documented
Message-ID: <jwvfxsvbgg5.fsf-monnier+emacs <at> gnu.org>
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
<200805061335.11379.bruno <at> clisp.org>
Date: Tue, 06 May 2008 11:35:01 -0400
In-Reply-To: <200805061335.11379.bruno <at> clisp.org> (Bruno Haible's message of
"Tue, 6 May 2008 13:35:11 +0200")
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
X-DIRO-MailScanner-Information: Please contact the ISP for more information
X-DIRO-MailScanner: Found to be clean
X-DIRO-MailScanner-SpamCheck: n'est pas un polluriel,
SpamAssassin (score=-2.82, requis 5, autolearn=not spam,
ALL_TRUSTED -2.82)
X-DIRO-MailScanner-From: monnier <at> iro.umontreal.ca
> You are right that there is a limit, but it is set to 200000:
> highlight-regexp is aliased to hi-lock-face-buffer, which asks for the
> arguments and calls hi-lock-set-pattern. hi-lock-set-pattern does little
> more than applying a margin of 100000 and calling re-search-forward.
Actually, font-lock-fontified is most likely set to t, so
hi-lock-set-pattern doesn't call re-sarch-forward at all and only calls
font-lock-fontify-buffer instead.
> - I originally observed the bug in po-mode (part of GNU gettext), in
> a function po-find-span-of-entry which essentially only calls
> re-search-backward and re-search-forward.
Please try and reproduce the problem there and send us a recipe.
Stefan
Stefan Monnier <monnier <at> iro.umontreal.ca>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level: *
X-Spam-Status: No, score=1.3 required=4.0 tests=FOURLA,IMPRONONCABLE_1,
MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 15:00:17 +0000
Received: from ecelsrv1.ece.lsu.edu (ecelsrv1.ece.lsu.edu [130.39.223.98])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m46F0Dev031055
for <192 <at> emacsbugs.donarmstrong.com>; Tue, 6 May 2008 08:00:15 -0700
Received: from localhost (unknown [127.0.0.1])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 607E228397;
Tue, 6 May 2008 15:00:13 +0000 (UTC)
X-Virus-Scanned: amavisd-new at ece.lsu.edu
Received: from ecelsrv1.ece.lsu.edu ([127.0.0.1])
by localhost (ecelsrv1.ece.lsu.edu [127.0.0.1]) (amavisd-new, port 10024)
with ESMTP id 6YS7lXjwke2y; Tue, 6 May 2008 10:00:12 -0500 (CDT)
Received: from nested.ece.lsu.edu (nested.ece.lsu.edu [130.39.222.143])
by ecelsrv1.ece.lsu.edu (Postfix) with ESMTP id 951EC2838E;
Tue, 6 May 2008 10:00:12 -0500 (CDT)
From: David Koppelman <koppel <at> ece.lsu.edu>
To: Chong Yidong <cyd <at> stupidchicken.com>
Cc: emacs-devel <at> gnu.org, 192 <at> debbugs.gnu.org,
Bruno Haible <bruno <at> clisp.org>
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
Date: Tue, 06 May 2008 10:00:12 -0500
In-Reply-To: <87k5i8ukq8.fsf <at> stupidchicken.com> (Chong Yidong's message of
"Tue, 06 May 2008 00:20:31 -0400")
Message-ID: <yg563trfpfn.fsf <at> nested.ece.lsu.edu>
User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.0.60 (gnu/linux)
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
Later in the week I'll look into it and provide either a fix
or document the limitation.
Chong Yidong <cyd <at> stupidchicken.com> writes:
> OTOH, I don't see what we can do about this problem. Maybe we could add
> a note to the docstring of highlight-regexp saying that multi-line
> regular expressions are problematic? Does anyone have a suggestion?
Chong Yidong <cyd <at> stupidchicken.com> writes:
>> $ emacs fr.po
>> M-x highlight-regexp
>>
>> Regexp to highlight (enter this with Ctrl-Q Ctrl-J for each of the two
>> newlines):
>>
>> ^msgstr\(\[[0-9]\]\)?.*
>> \(".*
>> \)*
>>
>> Highlight using face: hi-yellow
>>
>> Then move around in the buffer and look which lines are highlighted.
>> In the first match already, only 5 out of 11 lines are highlighted.
>
> I believe this bug arises because highlight-regexp uses font-lock to
> highlight the regular expression, and the font-lock engine is
> intentionally limiting the region to search for the multi-line regular
> expression.
>
> OTOH, I don't see what we can do about this problem. Maybe we could add
> a note to the docstring of highlight-regexp saying that multi-line
> regular expressions are problematic? Does anyone have a suggestion?
>
>
> BTW, here is a simplified recipe, for those who didn't download the
> attached file:
>
> 1. Copy the following text, between the "---...----" lines, into a
> buffer
>
> ------------------
> # Messages fran=C3=A7ais pour GNU gettext.
> # Copyright =C2=A9 2006 Free Software Foundation, Inc.
> # Fran=C3=A7ois Pinard <pinard <at> iro.umontreal.ca>, 1996.
> #
> #
> msgid ""
> msgstr ""
> "Project-Id-Version: GNU gettext-tools 0.16.2-pre5\n"
> "Report-Msgid-Bugs-To: bug-gnu-gettext <at> gnu.org\n"
> "POT-Creation-Date: 2007-11-02 03:23+0100\n"
> "PO-Revision-Date: 2007-10-27 13:35+0200\n"
> "Last-Translator: Christophe Combelles <ccomb <at> free.fr>\n"
> "Language-Team: French <traduc <at> traduc.org>\n"
> "MIME-Version: 1.0\n"
> "Content-Type: text/plain; charset=3DUTF-8\n"
> "Content-Transfer-Encoding: 8bit\n"
> "Plural-Forms: nplurals=3D2; plural=3D(n > 1);\n"
> ------------------
>
> 2. M-: (highlight-regexp "^m.*\n\\(\".*\n\\)+") RET
>
> Note that the last two lines remain unhighlighted.
David Koppelman <koppel <at> ece.lsu.edu>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.4 required=4.0 tests=AWL,FOURLA autolearn=no
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 12:14:14 +0000
Received: from mail.gmx.net (mail.gmx.net [213.165.64.20])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with SMTP id m46CE9Q1005478
for <192 <at> emacsbugs.donarmstrong.com>; Tue, 6 May 2008 05:14:11 -0700
Received: (qmail invoked by alias); 06 May 2008 12:14:03 -0000
Received: from 62-47-32-217.adsl.highway.telekom.at (EHLO [62.47.32.217]) [62.47.32.217]
by mail.gmx.net (mp002) with SMTP; 06 May 2008 14:14:03 +0200
X-Authenticated: #14592706
X-Provags-ID: V01U2FsdGVkX18yCGpUJqUywHXxTMpxBrZUdNdOsjT/PbSQ0STmlB
02EWWJ2vUsvJrO
Message-ID: <48204B3D.6000500 <at> gmx.at>
Date: Tue, 06 May 2008 14:12:45 +0200
From: martin rudalics <rudalics <at> gmx.at>
User-Agent: Mozilla Thunderbird 1.0 (Windows/20041206)
X-Accept-Language: de-DE, de, en-us, en
MIME-Version: 1.0
To: Bruno Haible <bruno <at> clisp.org>
CC: Chong Yidong <cyd <at> stupidchicken.com>, emacs-devel <at> gnu.org,
koppel <at> ece.lsu.edu, 192 <at> debbugs.gnu.org
Subject: Re: regexp does not work as documented
References: <87k5i8ukq8.fsf <at> stupidchicken.com> <200805061335.11379.bruno <at> clisp.org>
In-Reply-To: <200805061335.11379.bruno <at> clisp.org>
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
X-Y-GMX-Trusted: 0
> Can someone help me find a workaround, then? If not, I would have to give up
> maintaining po-mode as part of GNU gettext. Said function is central in
> Emacs po-mode (everything else relies on it), and if multi-line regular
> expressions don't work, I don't know how this function could be rewritten.
Don't worry, Stefan will find the solution. First of all you will
probably have to
(setq font-lock-multiline t)
in the respective buffer. This will _not_ always DTRT after a buffer
modification, as, for example, in
AAAA
CCCC
BBBB
where AAAA stands for some old text previously matched by your regexp,
CCCC for some new text inserted (or old text removed), and BBBB for some
text which, after the change, is now matched by the regexp (or not
matched any more): In this case BBBB will be wrongly highlighted now.
Alan uses the notorious
`font-lock-extend-jit-lock-region-after-change'
function to handle this, but it's not immediately clear how to apply
this here. If everything else fails you will have to refontify till
`window-end' (I prefer using a timer for such refontifications).
martin rudalics <rudalics <at> gmx.at>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level: *
X-Spam-Status: No, score=1.8 required=4.0 tests=AWL,FOURLA,IMPRONONCABLE_1,
MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 11:35:23 +0000
Received: from mo-p07-ob.rzone.de (mo-p07-ob.rzone.de [81.169.146.190])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m46BZIrI024780
for <192 <at> emacsbugs.donarmstrong.com>; Tue, 6 May 2008 04:35:20 -0700
X-RZG-CLASS-ID: mo07
X-RZG-AUTH: gMysVb8JT2gB+rFDu0PuvnvUUGmhfq1rhHRG5dSek381RH36PlIq8YOI
Received: from linuix.haible.de
(dslb-084-058-049-074.pools.arcor-ip.net [84.58.49.74])
by post.webmailer.de (fruni mo55) (RZmta 16.34)
with ESMTP id y00dfak469QrFI ; Tue, 6 May 2008 13:35:15 +0200 (MEST)
(envelope-from: <bruno <at> clisp.org>)
From: Bruno Haible <bruno <at> clisp.org>
To: Chong Yidong <cyd <at> stupidchicken.com>, emacs-devel <at> gnu.org
Subject: Re: regexp does not work as documented
Date: Tue, 6 May 2008 13:35:11 +0200
User-Agent: KMail/1.5.4
Cc: 192 <at> debbugs.gnu.org, koppel <at> ece.lsu.edu
References: <87k5i8ukq8.fsf <at> stupidchicken.com>
In-Reply-To: <87k5i8ukq8.fsf <at> stupidchicken.com>
MIME-Version: 1.0
Content-Type: text/plain;
charset="utf-8"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline
Message-Id: <200805061335.11379.bruno <at> clisp.org>
Chong Yidong wrote:
> BTW, here is a simplified recipe, for those who didn't download the
> attached file:
>
> 1. Copy the following text, between the "---...----" lines, into a
> buffer
>
> ------------------
> # Messages français pour GNU gettext.
> # Copyright © 2006 Free Software Foundation, Inc.
> # François Pinard <pinard <at> iro.umontreal.ca>, 1996.
> #
> #
> msgid ""
> msgstr ""
> "Project-Id-Version: GNU gettext-tools 0.16.2-pre5\n"
> "Report-Msgid-Bugs-To: bug-gnu-gettext <at> gnu.org\n"
> "POT-Creation-Date: 2007-11-02 03:23+0100\n"
> "PO-Revision-Date: 2007-10-27 13:35+0200\n"
> "Last-Translator: Christophe Combelles <ccomb <at> free.fr>\n"
> "Language-Team: French <traduc <at> traduc.org>\n"
> "MIME-Version: 1.0\n"
> "Content-Type: text/plain; charset=UTF-8\n"
> "Content-Transfer-Encoding: 8bit\n"
> "Plural-Forms: nplurals=2; plural=(n > 1);\n"
> ------------------
>
> 2. M-: (highlight-regexp "^m.*\n\\(\".*\n\\)+") RET
>
> Note that the last two lines remain unhighlighted.
Yes. I reproduce with this simpler recipe as well. Thank you.
> I believe this bug arises because highlight-regexp uses font-lock to
> highlight the regular expression, and the font-lock engine is
> intentionally limiting the region to search for the multi-line regular
> expression.
You are right that there is a limit, but it is set to 200000:
highlight-regexp is aliased to hi-lock-face-buffer, which asks for the
arguments and calls hi-lock-set-pattern. hi-lock-set-pattern does little
more than applying a margin of 100000 and calling re-search-forward.
I believe the origin of the bug is deeper, because
- the limit of 100000 is way larger than the little snippet you posted,
- I originally observed the bug in po-mode (part of GNU gettext), in
a function po-find-span-of-entry which essentially only calls
re-search-backward and re-search-forward.
> OTOH, I don't see what we can do about this problem. Maybe we could add
> a note to the docstring of highlight-regexp saying that multi-line
> regular expressions are problematic?
Can someone help me find a workaround, then? If not, I would have to give up
maintaining po-mode as part of GNU gettext. Said function is central in
Emacs po-mode (everything else relies on it), and if multi-line regular
expressions don't work, I don't know how this function could be rewritten.
Bruno
Bruno Haible <bruno <at> clisp.org>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level:
X-Spam-Status: No, score=0.6 required=4.0 tests=AWL,FOURLA,IMPRONONCABLE_1,
MURPHY_WRONG_WORD2 autolearn=no version=3.2.3-bugs.debian.org_2005_01_02
Received: (at 192) by emacsbugs.donarmstrong.com; 6 May 2008 04:25:17 +0000
Received: from cyd.mit.edu (CYD.MIT.EDU [18.115.2.24])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m464PDqR005814
for <192 <at> emacsbugs.donarmstrong.com>; Mon, 5 May 2008 21:25:14 -0700
Received: by cyd.mit.edu (Postfix, from userid 1000)
id 7245D4E304; Tue, 6 May 2008 00:20:31 -0400 (EDT)
From: Chong Yidong <cyd <at> stupidchicken.com>
To: emacs-devel <at> gnu.org
Cc: 192 <at> debbugs.gnu.org, koppel <at> ece.lsu.edu,
Bruno Haible <bruno <at> clisp.org>
Subject: Re: regexp does not work as documented
Date: Tue, 06 May 2008 00:20:31 -0400
Message-ID: <87k5i8ukq8.fsf <at> stupidchicken.com>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
> $ emacs fr.po
> M-x highlight-regexp
>
> Regexp to highlight (enter this with Ctrl-Q Ctrl-J for each of the two
> newlines):
>
> ^msgstr\(\[[0-9]\]\)?.*
> \(".*
> \)*
>
> Highlight using face: hi-yellow
>
> Then move around in the buffer and look which lines are highlighted.
> In the first match already, only 5 out of 11 lines are highlighted.
I believe this bug arises because highlight-regexp uses font-lock to
highlight the regular expression, and the font-lock engine is
intentionally limiting the region to search for the multi-line regular
expression.
OTOH, I don't see what we can do about this problem. Maybe we could add
a note to the docstring of highlight-regexp saying that multi-line
regular expressions are problematic? Does anyone have a suggestion?
BTW, here is a simplified recipe, for those who didn't download the
attached file:
1. Copy the following text, between the "---...----" lines, into a
buffer
------------------
# Messages fran=C3=A7ais pour GNU gettext.
# Copyright =C2=A9 2006 Free Software Foundation, Inc.
# Fran=C3=A7ois Pinard <pinard <at> iro.umontreal.ca>, 1996.
#
#
msgid ""
msgstr ""
"Project-Id-Version: GNU gettext-tools 0.16.2-pre5\n"
"Report-Msgid-Bugs-To: bug-gnu-gettext <at> gnu.org\n"
"POT-Creation-Date: 2007-11-02 03:23+0100\n"
"PO-Revision-Date: 2007-10-27 13:35+0200\n"
"Last-Translator: Christophe Combelles <ccomb <at> free.fr>\n"
"Language-Team: French <traduc <at> traduc.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=3DUTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3D2; plural=3D(n > 1);\n"
------------------
2. M-: (highlight-regexp "^m.*\n\\(\".*\n\\)+") RET
Note that the last two lines remain unhighlighted.
Chong Yidong <cyd <at> stupidchicken.com>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
Received: (at unknown) by unknown; unknown
X-Spam-Checker-Version: SpamAssassin 3.2.3-bugs.debian.org_2005_01_02
(2007-08-08) on rzlab.ucr.edu
X-Spam-Level: **
X-Spam-Status: No, score=2.3 required=4.0 tests=CT_IMAGE,FOURLA,
IMPRONONCABLE_1,MURPHY_WRONG_WORD2 autolearn=no
version=3.2.3-bugs.debian.org_2005_01_02
Received: (at submit) by emacsbugs.donarmstrong.com; 6 May 2008 03:29:36 +0000
Received: from mercure.iro.umontreal.ca (mercure.iro.umontreal.ca [132.204.24.67])
by rzlab.ucr.edu (8.13.8/8.13.8/Debian-3) with ESMTP id m463TPjq018358
for <submit <at> emacsbugs.donarmstrong.com>; Mon, 5 May 2008 20:29:27 -0700
Received: by mercure.iro.umontreal.ca (Postfix, from userid 20848)
id 107E52CFA13; Mon, 5 May 2008 23:29:24 -0400 (EDT)
X-Original-To: monnier <at> iro.umontreal.ca
Received: from pinpin.iro.umontreal.ca (pinpin.iro.umontreal.ca [132.204.24.52])
by mercure.iro.umontreal.ca (Postfix) with ESMTP id A4ED22CFA13
for <monnier <at> iro.umontreal.ca>; Mon, 5 May 2008 23:29:24 -0400 (EDT)
Received: from lists.gnu.org (lists.gnu.org [199.232.76.165])
by pinpin.iro.umontreal.ca (Postfix) with ESMTP id 25F193B8B43
for <monnier <at> iro.umontreal.ca>; Mon, 5 May 2008 23:28:45 -0400 (EDT)
Received: from localhost ([127.0.0.1]:34040 helo=lists.gnu.org)
by lists.gnu.org with esmtp (Exim 4.43)
id 1JtDr5-0007C0-9R
for monnier <at> iro.umontreal.ca; Mon, 05 May 2008 23:28:39 -0400
Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43)
id 1JtC1F-0003sm-6f
for bug-gnu-emacs <at> gnu.org; Mon, 05 May 2008 21:31:01 -0400
Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43)
id 1JtC19-0003sa-Im
for bug-gnu-emacs <at> gnu.org; Mon, 05 May 2008 21:30:59 -0400
Received: from [199.232.76.173] (port=60645 helo=monty-python.gnu.org)
by lists.gnu.org with esmtp (Exim 4.43) id 1JtC19-0003sX-B7
for bug-gnu-emacs <at> gnu.org; Mon, 05 May 2008 21:30:55 -0400
Received: from mo-p07-ob.rzone.de ([81.169.146.188])
by monty-python.gnu.org with esmtp (Exim 4.60)
(envelope-from <bruno <at> clisp.org>) id 1JtC17-0005rO-M1
for bug-gnu-emacs <at> gnu.org; Mon, 05 May 2008 21:30:55 -0400
X-RZG-CLASS-ID: mo07
X-RZG-AUTH: gMysVb8JT2gB+rFDu0PuvnvUUGmhfq1rhHRG5dSek381RH36MmEbn1EK
Received: from linuix.haible.de
(dslb-084-058-085-077.pools.arcor-ip.net [84.58.85.77])
by post.webmailer.de (fruni mo7) (RZmta 16.34)
with ESMTP id 6014fak45KXXEt ; Tue, 6 May 2008 03:30:48 +0200 (MEST)
(envelope-from: <bruno <at> clisp.org>)
From: Bruno Haible <bruno <at> clisp.org>
To: bug-gnu-emacs <at> gnu.org
Date: Tue, 6 May 2008 03:30:45 +0200
User-Agent: KMail/1.5.4
MIME-Version: 1.0
Content-Type: Multipart/Mixed;
boundary="Boundary-00=_FT7HID3WnMEP223"
Message-Id: <200805060330.45156.bruno <at> clisp.org>
X-detected-kernel: by monty-python.gnu.org: Solaris 10 (beta)
X-Mailman-Approved-At: Mon, 05 May 2008 23:27:16 -0400
Subject: regexp does not work as documented
X-BeenThere: bug-gnu-emacs <at> gnu.org
X-Mailman-Version: 2.1.5
Precedence: list
List-Id: "Bug reports for GNU Emacs,
the Swiss army knife of text editors" <bug-gnu-emacs.gnu.org>
List-Unsubscribe: <http://lists.gnu.org/mailman/listinfo/bug-gnu-emacs>,
<mailto:bug-gnu-emacs-request <at> gnu.org?subject=unsubscribe>
List-Archive: <http://lists.gnu.org/pipermail/bug-gnu-emacs>
List-Post: <mailto:bug-gnu-emacs <at> gnu.org>
List-Help: <mailto:bug-gnu-emacs-request <at> gnu.org?subject=help>
List-Subscribe: <http://lists.gnu.org/mailman/listinfo/bug-gnu-emacs>,
<mailto:bug-gnu-emacs-request <at> gnu.org?subject=subscribe>
Sender: bug-gnu-emacs-bounces+monnier=iro.umontreal.ca <at> gnu.org
Errors-To: bug-gnu-emacs-bounces+monnier=iro.umontreal.ca <at> gnu.org
X-DIRO-MailScanner-Information: Please contact the ISP for more information
X-DIRO-MailScanner: Found to be clean
X-DIRO-MailScanner-SpamCheck: n'est pas un polluriel,
SpamAssassin (score=0.05, requis 5, BAYES_00 -2.60,
CTYPE_F_IMAGE 1.99, RECEIVED_FROM_NOUNK 0.66, SPF_HELO_PASS -0.00)
X-DIRO-MailScanner-From: bug-gnu-emacs-bounces+monnier=iro.umontreal.ca <at> gnu.org
--Boundary-00=_FT7HID3WnMEP223
Content-Type: text/plain;
charset="us-ascii"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
The regular expression (as an Emacs string)
"^msgstr\\(\\[[0-9]\\]\\)?.*\n\\(\".*\n\\)*"
is supposed to search for a line starting with "msgstr" and an optional
digit inside brackets, followed by as many lines starting with a double-quote
as possible. The Emacs documentation says:
"The matcher processes a `*' construct by matching, immediately, as
many repetitions as can be found."
This is apparently not the case with the above regexp.
----------------------------------------------------------------------------
To reproduce:
$ emacs fr.po or $ emacs -nw fr.po
Leave the cursor at the beginning of the file.
M-x highlight-regexp
Regexp to highlight (enter this with Ctrl-Q Ctrl-J for each of the two
newlines):
^msgstr\(\[[0-9]\]\)?.*
\(".*
\)*
Highlight using face: hi-yellow
Then move around in the buffer and look which lines are highlighted.
In the first match already, only 5 out of 11 lines are highlighted. Then,
line 300 (in emacs 22) or line 335 (in emacs 21) are not highlighted either.
The attached screenshots were produced with emacs-22.2.1
(on i686-pc-linux-gnu) and with emacs-21.2.1 (on powerpc-apple-darwin7.9.0).
----------------------------------------------------------------------------
In GNU Emacs 22.2.1 (i686-pc-linux-gnu, X toolkit, Xaw3d scroll bars)
of 2008-05-01 on linuix
Windowing system distributor `The XFree86 Project, Inc', version 11.0.40300001
configured using `configure '--prefix=/packages/gnu''
Important settings:
value of $LC_ALL: nil
value of $LC_COLLATE: POSIX
value of $LC_CTYPE: nil
value of $LC_MESSAGES: nil
value of $LC_MONETARY: nil
value of $LC_NUMERIC: nil
value of $LC_TIME: nil
value of $LANG: de_DE.UTF-8
locale-coding-system: utf-8
default-enable-multibyte-characters: t
Major mode: Lisp Interaction
Minor modes in effect:
tooltip-mode: t
tool-bar-mode: t
mouse-wheel-mode: t
menu-bar-mode: t
file-name-shadow-mode: t
global-font-lock-mode: t
font-lock-mode: t
blink-cursor-mode: t
unify-8859-on-encoding-mode: t
utf-translate-cjk-mode: t
auto-compression-mode: t
line-number-mode: t
Recent input:
<help-echo> <help-echo> <help-echo> <help-echo> <help-echo>
<help-echo> <help-echo> <help-echo> <help-echo> <help-echo>
<help-echo> <help-echo> <menu-bar> <help-menu> <send-emacs-bug-report>
Recent messages:
("emacs")
Loading cl-indent...done
Loading derived...done
For information about GNU Emacs and the GNU system, type C-h C-a.
Loading emacsbug...
Loading regexp-opt...done
Loading emacsbug...done
PS: Where is the bug tracker? I don't see it at https://savannah.gnu.org/projects/emacs
--Boundary-00=_FT7HID3WnMEP223
Content-Type: image/png;
name="emacs21-1.png"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
filename="emacs21-1.png"
iVBORw0KGgoAAAANSUhEUgAAAf0AAANtCAMAAACt61LQAAAABGdBTUEAALGPC/xhBQAAAQtQTFRF
AAAAAM0ABS9EBgYGBz9bCE9yCl+JDAwMD47NESEoFDNDFjVFFxcXGhoaHh4eHi41Hx8fHy82H05m
IE9nIVBoIiIiIyMjJCQkJSUlJiYmJ1ZuJ2eHKCgoKSkpLDxDLS0tLT1ELj5FLy8vMTExMjIyNDQ0
NlVlNzc3N1ZmOllpPT09Pj4+Pz8/P26GQUFBQWBwRERERUVFSkpKS0tLTExMTU1NTk5OUFBQUWFo
U1NTVVVVVlZWV1dXWlpaXFxcYGBgY2Njbm5ucHBwc3Nzc4OKdnZ2eHh4eXl5fIyToKCgpqamrKys
srKyt7e3ubm5v7+/xsbGzMzMzc0A0tLS2dnZ3Nzc39/f//vt////ubGKGwAAADh0RVh0U29mdHdh
cmUAWFYgVmVyc2lvbiAzLjEwYSAgUmV2OiAxMi8yOS85NCAoUE5HIHBhdGNoIDEuMindFS5JAAAg
AElEQVR4nO19CcM0PVbVLVQE3BFEHRcQQRQ/BBU33MYdGWepYTT//5f4Pl2V5NwlW1Vv1bnnfbue
6tTNTSonJ5Wlu0PkmBm/4PgA/FwYx/e/2P95x/Xxcz8bx87+9wRefSuOYfzcz/6YI7TeZ/b/xa/9
1t+N1P+3P/+3H5XFX/D/j/r/jf3/xBBa7zP73/2NP/r7v76R/9d/9bcfp/0/6/8f9P+LfXik//EX
2/X30PL/zn/9vd//7S/yv/vvfy+2/ETbH8ZfCN1Uf6Vyt3rjqOPG/v9N2Niuvsfn/m/869/6y999
+/tX/mF67lP4Ip6Osr9VsnveoaOMG/t/mrCx/adxXBff/yl9XaTbddbr+/f/8Q9/93vf+19/6ztg
P3y7HDb2v3j89toJTX9+fgsKhtD3GIhXPxw/+P+N/Z8mbGz/NLIP73/60/09Y/+7X/3D3/+DX/mb
t+Z/ky196yd++5fYzyRHWSfegyV0Q/qvfz5+6v8b+z/5yU++uP72Z2P7J7fzr+P+/idbZbhd5yO+
3/lHf+a7f7V1/bYxAWMf5P7tgNJmJ8kWY3jz/3jc2P/xj3/8Re63PxvbP76dfx3393ids/8rv/bb
f+0/f3c73duLrwrw7d/mficxS7/EfmCWGOJ4HG7s/+hHP/ri7dufje0f3c6/jvt7vM5b/v/56//4
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
--Boundary-00=_FT7HID3WnMEP223
Content-Type: image/png;
name="emacs22-2.png"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
filename="emacs22-2.png"
iVBORw0KGgoAAAANSUhEUgAAAf0AAANtCAMAAACt61LQAAAABGdBTUEAALGPC/xhBQAAAQ5QTFRF
AAAAAP//BS9EBgYGBz9bCE9yCl+JDAwMD47NESEoFDNDFjVFFxcXGhoaHh4eHi41Hx8fHy82H05m
IE9nIVBoIiIiIyMjJCQkJSUlJiYmJ1ZuJ2eHKCgoKSkpLDxDLS0tLT1ELj5FLy8vMTExMjIyNDQ0
NlVlNzc3N1ZmOllpPT09Pj4+Pz8/P26GQUFBQWBwRERERUVFSkpKS0tLTExMTU1NTk5OUFBQUWFo
U1NTVVVVVlZWV1dXWlpaXFxcYGBgY2Njbm5ucHBwc3Nzc4OKdnZ2eHh4eXl5fIyToKCgpqamrKys
srKyt7e3ubm5v7+/xsbGzMzMzQAAzQDNzc0A0tLS2dnZ3Nzc39/f////wzvzkAAAADh0RVh0U29m
dHdhcmUAWFYgVmVyc2lvbiAzLjEwYSAgUmV2OiAxMi8yOS85NCAoUE5HIHBhdGNoIDEuMindFS5J
AAAgAElEQVR4nO19iaP9vFbVvqgIOCOIigOIIIofgorz9JwRfI/3tY9n//9/xN9pM6w9JE3anLF7
3Xt7ejLs7GRlpWlyzi2R48r4OccH4GeWfvzgxv7POt4fP/PTfgT2f1Xg2VVxdONnfvqHHMve+8z+
v/iV3/y7kfr//uf/9r1c/Dn/vdfvN/b/M8Oy9z6z/93f+Pd//9c28v/6L//W/bT/Z/33Tr839uGS
/oc3tuvvYeT/7f/2u7/3Wzfyv/sffy+O/ETbC+NvWRqJDsUM7DqOClb2/1/Cxnb1PV73f/1f/+Zf
/u7b61/5h+m6T8uNeHL23wEr+3+asLH9p/G+Lr7/U7pF0hrPZn3/4T/9we/86q/+77/1HbC/fIte
NvZvPH77C4Sml5/dglKEgAh79sXxg39X9n+SsLH9k8g+vP/JT8J7xv53v/wHv/f7v/Q31+F/ky19
myd++0nsZ5KjrBPvBaGrkOdfHz/1d2X/xz/+8Y3rby8b2z9ez2/H8P7HW2dY4/kd32//oz/z3b/a
pn7bPQFjH+T+7ZAHA3GS0mbyffh/BFb2/+RP/uRG7reXje0/Wc9vx/Ae4zn7v/Qrv/XX/st362kY
L24d4NvPZh4YXbL2f1aznweB/Ood4N5Y2f/Rj3504+3by8b2j9bz2zG8x3g+8v+vX/vH//Of/tXv
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
+4X2xF6q0oYdQ+YqVfIa7KOFDXM8mOwry5JN9EoMEFyOslxWC10wl7jFPnpisU+svg3sn9T+Eule
+T7EfiEdNKTBfnJD5LW1L6o52yN/ySsertsdzomnLyvdDGHNc5j9gm/E+lfJE8S+9vOl/4bqyC+q
Vx6jdN1yO6QYYu9EHY2RH7yZ46z/9ggCITnLKxFOi5EmtC1ZdhRMCRbVStyTFvbNVtUjke7iDHXt
R6bZ3M+a9RmzDjVLSSkJ0se8aZ6D5zlW1TG0AJ+tJUThb1N/Ji3bq4XbIatGhIORXW6xpVkdWV1y
rTEjpmfHhYVQNk+Y3fTCWJNpvd+3Rvs3gU3PB4Krz47naL7f/1KDvePV0P1ZSn8m13Xhz+S6MoZp
nz9S0/EWOKh9zbGz/4Y4qH1n/yNQ1358mLL1dNqVauf6rVHXPj4RWz7PenuqsdP/ztjRfnqeunh6
ej443hgt2p/Zs+v5ieOd0aL9pHrCkd8neO+PPe1H3rfU+dyv+Z+A9vv9NOA7PgYd9/vk93efBl/n
fwzW/08+6fPnwvf4HoPXZ9/QPqXJfhlm5NCLhG2sNO88c4EyVrD3rbEUhfSZcaqwf7dLa+EGbUf7
fHGvaNoOK+Qh9tLkuh1auuesWt4p1trA2ANV3kUkxqmmfZW3uzuQfd7Afkn7R9nvSH4ExQWHM+wf
ybDHPoHeb7HbueX+efaLLh7RfvIh3umHnR12LQgLADkkbAKFnQFzh0isHlO2FVcS1rOcyyiXrUDy
YG4T7Qg/xY4VtdWOe0gsl04Pel9D07moNdrX3rJSCv4Ya/JVNM35k/YjN7zNyXhNf5CeDyM5FVrj
6WGPqVBuiX1mE+zIxJb9eimYRu+C2aVnvc/zDOMAr7W2j95mm1T0x/agjD7tw6ova8GZdVPtAaW8
2SlgX+VlbQt5WZ1IhaANZrPAPtQI/dS1Iy5C8LPAvijd1D6yD7VgPmj2tYfEShZ/dbRrX+jC6JUV
9uHIXkgRMmNZeWZnsk917WPCspoY+xhVsJbMUF37rHjjug/kq9azCi63P7ZDbtWx2o/1ZT6gmzXt
Yy6SfuqeY7etTMn2n6u9kVTpsVqUrvtGCxesSe5t9tECGXN+MsootdUaHv0kstOnMeAY+yXt53ka
jPzgeo7ljsLVjM+L8DzHGm2by2J2YkooF8mX8yLuM/Oc9SsrbzFkzhwZ8zG1QlK/32c10G3FPay1
f2nmWcCHrPXtd/PBWUWP28X5tb4TVSzC1/kPtmrnntfrs39M+6+5gu1owXntO/vvi6Z1/iqsdQxA
gwXHs9C0zl+FtY4BcPZfGOe0j3eyt4TG/oWz/8Lout+n7e42ZWarWHDujL8JWub8+d427obE8Kz3
7b1ewXa8Mpq0P8e1Ms6qYJ+s/QvHK6Nd+/mY0LB/4XhltF/38/5CBsz6YM6vdswcL4pW7c9sTwRR
vN/vXAt1PB6t1/0yymt9Tv6ro0P7BfhK7/vCn8tzbfhzea4M1/6V4dq/Mlz7V4Zr/8pw7V8Zrv0r
w7V/Zbj2rwzX/pXh2r8yXPtXhmv/ynDtXxkjtD/d/qaTjkybhSmbdNwdVe1//+2nAVP8rSRosLEa
cfYfiar2A/s7XSAQt5OiwcC0/qwhzv5DUNP+9zesLyn5Oj5PGzthrAb2IXaalpRmmoBNfR5ygaHJ
tf8Y9Gk/KHSKBKU/YDDGJh1HStdEOFBwxuG67+w/CA3aR0wg9AVeEnOZ82mZsFssmNw+hz9n/yFo
0T7D1MO+5rKJfXapcNwPLXN+NfKr8wr7E78jmBr+Ft4xHHdDw/2+MevT5zIk38GJ1QCY6eljUr2z
/xC0rPU13fR3onQFcDwSvs5/Zfg6/5Xh2r8yzmifvIe8Obrv9zPqXcR7xhvgxB5fnV9n/w1Q076x
0ksw2lMOofUqQNuIsYWQXxdeH33aX8ldmaXAbwzJnSekc+7fAH3aJ/UmsB8Ctn6TuoXjxdGvff5G
s7+FOPvvgKb9/dQHArP5jc1+0L53gFdH5zp/cdYXA3Dy9wD3HafQssf3RPccd4Wv818Zvs5/Zbj2
r4xe7X99qddvv2H9Z5hXz5kxFgud19+WlE9Cu+cbXxG92rfZF/eCVedaNg/vtn9UzVuKnNefYsre
2h3DIM9L7Pdd94+z34D77R8dakPVhA8ivFxkc6TyvF37XzdsL/HNeipMpPK39X6+JpB3fFKsmZKF
qP0jlpIKpUDKVAbxWFIlYkq0TPzqE0bQORcIeZknBX+wds/0nKOm/a+A0AEi8UvqBYBIbFrpzaFx
VTB5bKaEEGv/CPo3gWUon1lYsDrQXpCFpyeZlyWeF8E+pNQDgfZc+/Yszzl2tR+YFuwXtB+5A6HG
SNkjjH6yxLyUzwntQFLeH3JKow1TrGjDYmurGeyM7SjzFtkXx1w7RuSDPefY1/4S6V75bmDfjmhj
H96wEKy9Yp+1sNkyKX1LG4rilnD1HMC+qsvjPefY136+9N9QHfmxTYTnJMPWwDxK6JrqlslJVSk4
SsRLoWoZysbRvpkS23COc+dZsa+GZUIfDF6e6bnQ5bKn/cg0m/tVZn2R0xwcp0FZ13j9l9q3Zn1o
J75ZZCms1gQhJErEuZNMyedO2IabfPIEOqUUNrNXuvRcuyd5bnzaqvV+3xrtz4Ip+oVtPsaH+3ve
p32GLzXYD3BH98aXtPkYH57g+f4zuRyfipZncjk+FcO0bz6q1fHaOKh9zbGz/4Y4qH1n/yNQ1354
7DKRONJ2nP1Ju++Nuva35y7LJ7BT0D6RP2v3vbGj/Y1vCpyn8zkfHG+MFu3PSe6JdGf/I9Ci/aR6
wpHfJ3jvjz3tR9631Pncr/mfgPb7/TTgOz4GHff75Pd3nwZf578mfI/vytDsG9qnuTK74+Gl68Kh
6wVmIh0++BJkm7vfvPa5tVg5bdJ+O/uldCy8fZmAqued7baTvNRs9Xtaa6ujPbEI8wAACwVJREFU
z6En1aLA/jntNyc6mA3Dx7ZbMdfdZrlPrUW79rFYnPPjLk/c/ZlFCGbGNNoOHNN6wszTGE2gfEge
EI/FEmmupRT3NbjCubkv6ivapOCVtvzMWmxo0r7wleA1e5CtBw9Yi8FKkTnym7tIck5htRv4wC3A
zhTJSxJPL1OSKovVJQmJjFgMYaUULD+rFhuOaB/ZTzajaKHurJtCXsU+rB7zvCTSGO2W8s7cwvYj
1qV5W9gpRSuRDEl7XlAXITKjJ+cGeI1abOjVPm8H6YOsO68o63/FWmBe3Xft8GK7Yd56uxXqOKc5
D2dfaEnZLrCPbfLUWmzo1T5BTxe1k9rnpUPe9CZHErHrvmhbUa4OjxyEnk9iJEzFKc+NlAWuyQ4x
PZ2N0Uwz8rRa5HI7tB/pAU6BqegxhsiKQhpOpuy37HNEkAbL1XmxHdGHxBDrjKWU3D6lrGTkNf2M
RnYsP60WEP46a32M/cMWzuQfhzOe3L8WR7R/b5xnX9zjPBNnPHlgLVq07/h0+P/ruzJc+1eGa//K
cO1fGa79K8O1f2W49q8M1/6V4dq/Mlz7V4Zr/8pw7V8Zrv0rw7V/ZYzQ/nT7m046Mm0WpiUfx5fY
kQX9mfbKOtcCLRmnaXOirX1a0fcc3oJn8beSoMHGZqSpIY+W2N5q6E9u9dH+LFMt0jDQ2D6taHoO
775ju43TYmBKx8YM3SW2tZr2pzFDtz9t7HPNN7RPM2raD09gx8ewr8PPtHW+OB6Cczl2ir102kYt
boGdh1y5tVl7jCpR2Ym57JQL+MPa+rQ/E9a34FXJc6N9TqFP+9FnyRSvUeyfqWnixXOamO+sLix2
Gl4iplwMm8qfZGbi3A31J4ZbHi7CfkEdp9CgfYSeecAbVEqoe26UBZPr85jH0P6YEiewnVjgpXF/
cnrm0RB/BPsQUvbnvuyXtS9c6Kg71lHXqLF2o0qcMP0u+4qXkf6EfvFC7Jfn/GrkV+eVuoc6TsxC
8W/KlsaWKI5Z+3BnJ/9S4sWydtifeDVfYrjFfmv7nEPD/b4x69PnMiR6q25RcGaljyE1nySNKxHT
cP1KT9j9tZoZnvFH9Gz0Spw3tc8ptKz1Nd30d2IqnD8ak3iV5/cqEceTcip9PhZXX+d/fM9jo82T
4ev8V8bVtX9tnNH+Czz7zHEK3ff7GfUu4j3jDXBij6/Or7P/Bqhp31jpJXyGbA6hheKDYWMI+XXh
9dGn/fzMXwr8xpDceUI65/4N0Kd9Um8C+yFg6zepWzheHP3a5280+1uIs/8OaNrfT30gMJvf2OwH
7XsHeHV0rvMXZ30xACd/D3DfcQote3xPdM9xV/g6/5Xh6/xXhmv/yujV/teXeo2nDHudB+eEo+aH
Y+eZuzWophGT43n9NS2Pc3qzVGLEQq/2B7GPBQzYLYo3nyYj1GJIx5bSE7y2sj+vP7blRvb33FnO
sd933T/PfmPSdmk0tE8PBmt/tuJaytlJNoh9rf2vG7aX+GY91QXElf5wlnd5YA8oJiXZbO27RRjC
j2hn4bHE0oA/3PIi/IzBhbLUJpawrMi6sQ//HznnImkfBkVVC+VVsZ2bUNP+V0DoAJH4JfUCbKUl
rvHiem9uUz5e8rq07hYxm3BcYmPQgu+FhRyO3jLb6hqk6yLti9SG5Q0z/LXUSLYqbwfZPrqd27Cr
/cC0YF9pv8D+thuoUmrtZwupdnq3KA0b0jJoH9uPWYC8wQfDL5N9LLfIfvLHZH8jXUsf0lMcB8xY
g32oHUH6Huxrf4l0r3x3sp9iecoW9o2UKUBattnnFhT7okUr7EO55ZS2fgPidV/QL3OxSu2wj+Hn
2S9pP1/6byiM/NFPMkd+lbKRfbFblDUiebTYlxYk+7ytauynsUKNAawSFe3PadbfNfJjCGsH2T7F
XreDuvYj02zuZ876cv2Ro0UN3nuzPmltUTNGYnbwaIRnC8IfiiHCsqXonJLAjmhn0v0kYz4468PS
jXBRu7HaR+jR/lnoq9/Ycp9V9r3QfL//9fUa5D+PgQ/8pOLzn8nleBZe4ZlcjmdhmPblo1Qdb4CD
2tccO/tviIPad/Y/AnXtxwcKkzgShSe9O9dvjbr29ZOg8/Ogt6cCO/3vjB3ti6d3x/M5HxxvjBbt
z/lB3uHc2f8MtGg/P+EdR36f4L0/9rQfed9S53O/5n8C2u/304Dv+Bh03O+T3999Gnyd/5Wx/k/O
6XwandL3+F4fj2Tf0D5f61P2Dl0KiheQ1itLLVnVhIo8dy2TmcdfGfeZpX72t/u1Fu0T3tkPYr+U
q/ku4ij7JM+pMJclnb6hrLr/xS5fK6HMLKXXYhpleUsZ7uLbtf8Y9ofk77J9iJFisnqu7rKoSdcE
nNYsg7U16ULt133JPu7vMPXAfQGpvSFmjaXM1xe2r4RlQSzbY0LLFLegMMT0BNar47ncw8LwtrJm
kZ7XS3k1q/0ybo2SWq29tuQDcmrUWlnbPNXsl+f8in0Y5eTYqcNJpCGRi+8lkUgfWkfFYjjaLYXw
WIqNp/zJVcvhTWVRbJWcnpTNWdiMUtD2b2dsrNb+z1n7cyorxbESs7UtIn468pj2C+xDh4s+RNGK
2rOU609YSc7nup1lO0g7s8iL+1PRPtRIsJz81+zHuogW4GVxb6O/3Gb2GTmy6iLZZ3ttdfZ1icj+
Gr4E+g9pH95hq1TUofo+9423mOorZfbNlDzQSm+zz1Wj2MdurssqsG8pUZal6zLjyB8tEvok2Cfu
m2oamvl1X7F/TPszV1TuCbEDEvH0zHvZSsbIn9qzxH6hv+UQHJMxj8UyDMiS/XpZFfZxkJd5ya7L
FqpH/jQpSX961oeWS9aWQH+D9tXMTas3pWR1TCFqzmNYA47qsXx4bpj16XJzE8rwObywcO3V3qyP
eZ5tCq9iuFGXFZEvXjqBb+Z9QZzPlKzRbLB/bK1P9gTeGK+A1/GkF5pZ3dp3XOtrgeqx2c/XwOt4
0ouyrqtpGqz5Or/D9/iujLZ1fsdnom2d3/GZcO1fGX7dvzJ8zn9luPavDNf+leHavzJc+1eGa//K
cO1fGXv/u8Pxydj5Dq9jD/tt9MKteEr7C/wGa8v2Hy2Ncu7fCEv8wEr+17WGC0bwImqB4fFdqUyK
/0MXS+Rt8Lr0n9E+Jo8hwagu5gEjCbZ3aP+Fxy4EzrJcRi0wfdH5Jf0h4wthD3gP9nu0H59FQKw9
c0uqYgb7XfQpnHD2bY5YLlULtGPUCJKW2ZcGXw0t2sfaxVZdsFurdrPZxwEg/ofxkVeEZD4TCqO9
6b+Ry1bwIfaxAV8SDf+j22Kf0R6vfby1eSkL/rP5LYTiBXpcXRhT6RRnAgZTPBfkx5gq+4u0IeY/
C7bPax0PaR+byRjiitrnTA1mP/uafCiM/JLPxayF7u1mcagB4cV7az+koSL7OTClxFcoJh5SwHjt
h5KNa1IT+6oW12K/ov1t/E/H3JbmnH+H/cB5uvQPqwtl9sF1GStHaagJeo/pywQuMj07V4Pji6Fp
zi+43wbt2LQ4aoba6rkcsr/A9X/orI/gYpuuvIuITdE8nNUC5gmBxaKfqHB1v1+YBb0Ojt7vn6nR
+PH+idivxwvX9Fnr/B/D/luj/xncjk/C0WdwOz4Brv0rw7V/Zbj2rwzX/pXh2r8yXPtXhmv/ynDt
Xxmu/SvDtX9luPavDNf+lQHsczj7F0Bi33FFbOwb3eLhHdFxZ1iUruz/X4UfLD91fBZ+YNHs7F8E
zv6V4exfGSX2nz31dDwNL/2Zc8edsfx/XjASv3k3jPcAAAAHdElNRQfYBQYBHAQ/6hc9AAAAAElF
TkSuQmCC
--Boundary-00=_FT7HID3WnMEP223
Content-Type: image/png;
name="emacs21-2.png"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
filename="emacs21-2.png"
iVBORw0KGgoAAAANSUhEUgAAAf0AAANtCAMAAACt61LQAAAABGdBTUEAALGPC/xhBQAAAQtQTFRF
AAAAAM0ABS9EBgYGBz9bCE9yCl+JDAwMD47NESEoFDNDFjVFFxcXGhoaHh4eHi41Hx8fHy82H05m
IE9nIVBoIiIiIyMjJCQkJSUlJiYmJ1ZuJ2eHKCgoKSkpLDxDLS0tLT1ELj5FLy8vMTExMjIyNDQ0
NlVlNzc3N1ZmOllpPT09Pj4+Pz8/P26GQUFBQWBwRERERUVFSkpKS0tLTExMTU1NTk5OUFBQUWFo
U1NTVVVVVlZWV1dXWlpaXFxcYGBgY2Njbm5ucHBwc3Nzc4OKdnZ2eHh4eXl5fIyToKCgpqamrKys
srKyt7e3ubm5v7+/xsbGzMzMzc0A0tLS2dnZ3Nzc39/f//vt////ubGKGwAAADh0RVh0U29mdHdh
cmUAWFYgVmVyc2lvbiAzLjEwYSAgUmV2OiAxMi8yOS85NCAoUE5HIHBhdGNoIDEuMindFS5JAAAg
AElEQVR4nO19CaPsPHJVOUBIwh4SAgxLQkgIhC8kQNjCNuwhwyyeDPj//xLebVvSqUVSqe3udrfr
vHf7uuVSVamOSpal7muiwJXxC4EPwM8t4/j+F/s/H3h//NzPxrGx/z2BVzclMIyf+9kfcyy994X9
f/Frv/V3E/X/7c//7Ue5+Avx/1H/v7H/nxiW3vvC/nd/44/+/q+v5P/1X/3tx+X+n43/D/r/xT5c
0v/4i+32exj5f+e//t7v//YX+d/997+XRn6i9Rfjb1ncVH9ZOazfBNq4sf9/M1a2m+/xuv8b//q3
/vJ3337/lX+Yr/u0fBFP97K/drIjWxio48b+n2asbP9puq9L7/+Uvk7S7Tyb9f37//iHv/u97/2v
v/UdsL98O72s7H/x+O1nIzT/+vm1aDESfauBePXF8YP/39j/acbK9k8T+/D+pz/d3jP2v/vVP/z9
P/iVv3kb/te0pW/zxG//MvuF5JTWmffFSnQj9V9/ffzU/zf2f/KTn3xx/e3XyvZPbsdfr9v7n6yd
4Xae3/H9zj/6M9/9q3Xqt94TMPYh3b+9YGqzgyyLNWL4fzxu7P/4xz/+Ivfbr5XtH9+Ov16393ie
s/8rv/bbf+0/f3c73MaLrw7w7d+qfiOxpH6N/YVJYkngcbix/6Mf/eiLt2+/VrZ/dDv+et3e43k+
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
--Boundary-00=_FT7HID3WnMEP223
Content-Type: image/png;
name="emacs22-1.png"
Content-Transfer-Encoding: base64
Content-Disposition: inline;
filename="emacs22-1.png"
iVBORw0KGgoAAAANSUhEUgAAAf0AAANtCAMAAACt61LQAAAABGdBTUEAALGPC/xhBQAAAQ5QTFRF
AAAAAP//BS9EBgYGBz9bCE9yCl+JDAwMD47NESEoFDNDFjVFFxcXGhoaHh4eHi41Hx8fHy82H05m
IE9nIVBoIiIiIyMjJCQkJSUlJiYmJ1ZuJ2eHKCgoKSkpLDxDLS0tLT1ELj5FLy8vMTExMjIyNDQ0
NlVlNzc3N1ZmOllpPT09Pj4+Pz8/P26GQUFBQWBwRERERUVFSkpKS0tLTExMTU1NTk5OUFBQUWFo
U1NTVVVVVlZWV1dXWlpaXFxcYGBgY2Njbm5ucHBwc3Nzc4OKdnZ2eHh4eXl5fIyToKCgpqamrKys
srKyt7e3ubm5v7+/xsbGzMzMzQAAzQDNzc0A0tLS2dnZ3Nzc39/f////wzvzkAAAADh0RVh0U29m
dHdhcmUAWFYgVmVyc2lvbiAzLjEwYSAgUmV2OiAxMi8yOS85NCAoUE5HIHBhdGNoIDEuMindFS5J
AAAgAElEQVR4nO19CYP8PnKVZoGQhDskBFiOhJAQCP+QAOG+ljtk2aPtzaLv/0X4dVvHq0OyZLu7
7Va9mXG7pVJJ1lPp7OlyzjAyftHwAfie78cP7uz/guH6+N7P+xHY/z7Dux/F0I3v/fyPKfza+8z+
v/j13/67kfr//uf/9rOK+Iv2+6zfb+z/ZwK/9j6z/93f+Pd//zcW8v/6r/3O82z/z9rvk37v7MOQ
/sd3tuvvoef/3f/2+3/wO3fyv/sffy/2/M4tL4Q/7xuJDtkc2HQMFTzY/38JC9vV9zju/+a//u2/
/N2317/yD9O47/ydeGfsXwEP9v80YWH7T+O6Lr7/U3ePdI94Muv7D//pj37v+9//33/rO2Dff4v2
C/t3Hr/9BULTyy8sQSmCgYW9e3D84N8H+z9LWNj+WWQf3v/sZ+E9Yf+7X/ujP/jDX/2bj+5/MVv3
bZ747Sexn0mOZp14Lxi6CHn/+Pipvw/2f/rTn965/vaysP3Tx/39Gt7/dGkMj3i64vvdf/RnvvtX
y9RvWRMQ9sHcv11yZ8Bukmwm37r/V+DB/k9+8pM7ud9eFrZ/8ri/X8N7jKfs/+qv/85f+y/fPW5D
f3FvAN9+FvXAqM+2/wuS/dwJ5FdrAM/Gg/0f//jHd96+vSxs//hxf7+G9xhPe/7/9Rv/+H/+07/6
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
QmCC
--Boundary-00=_FT7HID3WnMEP223
Content-Type: application/x-gzip;
name="fr.po.gz"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="fr.po.gz"
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
AA==
--Boundary-00=_FT7HID3WnMEP223--
Bruno Haible <bruno <at> clisp.org>:Emacs Bugs <bug-gnu-emacs <at> gnu.org>.
Full text available.bug-submit-list <at> lists.donarmstrong.com, Emacs Bugs <bug-gnu-emacs <at> gnu.org>:bug#192; Package emacs.
Full text available.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997 nCipher Corporation Ltd,
1994-97 Ian Jackson.