From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Newsgroups: gmane.emacs.bugs Subject: bug#34641: rx: (or ...) order unpredictable Date: Sun, 24 Feb 2019 22:18:28 +0100 Message-ID: <065957BB-1332-458B-8757-742A81CED4A5@acm.org> References: <836B8DC2-9358-40AC-83AF-7C4D960D9A53@acm.org> <83bm31ngzp.fsf@gnu.org> Mime-Version: 1.0 (Mac OS X Mail 12.2 \(3445.102.3\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_D5A358D7-0A23-41FF-BD17-E7237413679F" Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="126949"; mail-complaints-to="usenet@blaine.gmane.org" Cc: 34641@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sun Feb 24 22:19:17 2019 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1gy1B4-000Wro-Ih for geb-bug-gnu-emacs@m.gmane.org; Sun, 24 Feb 2019 22:19:14 +0100 Original-Received: from localhost ([127.0.0.1]:56116 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gy1B3-000051-Ih for geb-bug-gnu-emacs@m.gmane.org; Sun, 24 Feb 2019 16:19:13 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:40169) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gy1Av-0008WQ-Fw for bug-gnu-emacs@gnu.org; Sun, 24 Feb 2019 16:19:06 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gy1Av-0006gt-24 for bug-gnu-emacs@gnu.org; Sun, 24 Feb 2019 16:19:05 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:37038) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gy1As-0006fw-81 for bug-gnu-emacs@gnu.org; Sun, 24 Feb 2019 16:19:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1gy1Ar-0002Dj-Nd for bug-gnu-emacs@gnu.org; Sun, 24 Feb 2019 16:19:01 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sun, 24 Feb 2019 21:19:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 34641 X-GNU-PR-Package: emacs Original-Received: via spool by 34641-submit@debbugs.gnu.org id=B34641.15510431178504 (code B ref 34641); Sun, 24 Feb 2019 21:19:01 +0000 Original-Received: (at 34641) by debbugs.gnu.org; 24 Feb 2019 21:18:37 +0000 Original-Received: from localhost ([127.0.0.1]:50582 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gy1AS-0002D5-EM for submit@debbugs.gnu.org; Sun, 24 Feb 2019 16:18:37 -0500 Original-Received: from mail83c50.megamailservers.eu ([91.136.10.93]:48360 helo=mail18c50.megamailservers.eu) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gy1AO-0002Cu-Cd for 34641@debbugs.gnu.org; Sun, 24 Feb 2019 16:18:35 -0500 X-Authenticated-User: mattiase@bredband.net DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=megamailservers.eu; s=maildub; t=1551043110; bh=jcmG0ip79i27746FgmmjAApS1DsS6T57q5A9yr80o0g=; h=From:Subject:Date:In-Reply-To:Cc:To:References:From; b=RehSo6IivdelKFKtyKme5ys85SrT4s1zPHMm8+/Hjw1PfLbfWVKeKOKAPDXCIKfu7 RiMK37DW+gcP4pr5RgGVk3s7eqLQzaWUR3FK3MO4sUYY/8G15opT5J3l7s3gFSKayD E39hivQqrI14Jn9a8y8NVdd9NTN/HxxHtSF6fJmE= Feedback-ID: mattiase@acm.or Original-Received: from [192.168.1.65] (c-e636e253.032-75-73746f71.bbcust.telenor.se [83.226.54.230]) (authenticated bits=0) by mail18c50.megamailservers.eu (8.14.9/8.13.1) with ESMTP id x1OLIShQ001665; Sun, 24 Feb 2019 21:18:30 +0000 In-Reply-To: <83bm31ngzp.fsf@gnu.org> X-Mailer: Apple Mail (2.3445.102.3) X-CTCH-RefID: str=0001.0A0B020F.5C730A26.0031, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0 X-CTCH-VOD: Unknown X-CTCH-Spam: Unknown X-CTCH-Score: 0.000 X-CTCH-Flags: 0 X-CTCH-ScoreCust: 0.000 X-CSC: 0 X-CHA: v=2.3 cv=KOR08mNo c=1 sm=1 tr=0 a=M+GU/qJco4WXjv8D6jB2IA==:117 a=M+GU/qJco4WXjv8D6jB2IA==:17 a=mDV3o1hIAAAA:8 a=VuAzZmDrsQfTbhHelMgA:9 a=CjuIK1q_8ugA:10 a=DU3o0j1wsCfdOjnseeUA:9 a=B2y7HmGcmWMA:10 a=_FVE-zBwftR9WsbkzFJk:22 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.51.188.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:155749 Archived-At: --Apple-Mail=_D5A358D7-0A23-41FF-BD17-E7237413679F Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii 24 feb. 2019 kl. 20.06 skrev Eli Zaretskii : >=20 > Your preferred solution is fine with me, FWIW. Thank you; patch attached. >> (Speaking of regexp-opt, it has another bug that does not affect rx: = it returns the empty string if given an empty list of strings. The = correct return value is a regexp that never matches anything. Fix it, = document it, or turn it into an error?) >=20 > Fix it, I think. I'll prepare another patch. Is there a preferred or particularly clever = never-matching regexp? If not, would \(?:$\)A do? --Apple-Mail=_D5A358D7-0A23-41FF-BD17-E7237413679F Content-Disposition: attachment; filename=0001-rx-fix-or-ordering-by-adding-argument-to-regexp-opt.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0001-rx-fix-or-ordering-by-adding-argument-to-regexp-opt.patch" Content-Transfer-Encoding: quoted-printable =46rom=200ba8d5e51714519d818c519581e699ca82047e66=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= =0ADate:=20Sun,=2024=20Feb=202019=2022:12:52=20+0100=0A= Subject:=20[PATCH]=20rx:=20fix=20`or'=20ordering=20by=20adding=20= argument=20to=20regexp-opt=0A=0AThe=20rx=20`or'=20form=20may=20reorder=20= its=20arguments=20in=20an=20unpredictable=20way,=0Acontrary=20to=20user=20= expectation,=20since=20it=20sometimes=20uses=20`regexp-opt'.=0AAdd=20a=20= NOREORDER=20option=20to=20`regexp-opt'=20for=20preventing=20it=20from=0A= producing=20a=20reordered=20regexp=20(Bug#34641).=0A=0A*=20= doc/lispref/searching.texi=20(Regular=20Expression=20Functions):=0A*=20= etc/NEWS=20(Lisp=20Changes=20in=20Emacs=2027.1):=0ADescribe=20the=20new=20= regexp-opt=20NOREORDER=20argument.=0A*=20lisp/emacs-lisp/regexp-opt.el=20= (regexp-opt):=20Add=20NOREORDER.=0AMake=20no=20attempt=20at=20regexp=20= improvement=20if=20the=20set=20of=20strings=20contains=0Aa=20prefix=20of=20= another=20string.=0A(regexp-opt--contains-prefix):=20New.=0A*=20= lisp/emacs-lisp/rx.el=20(rx-or):=20Call=20regexp-opt=20with=20NOREORDER.=0A= *=20test/lisp/emacs-lisp/rx-tests.el:=20Test=20rx=20`or'=20form=20match=20= order.=0A---=0A=20doc/lispref/searching.texi=20=20=20=20=20=20=20|=2012=20= ++++++++---=0A=20etc/NEWS=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20=207=20++++++=0A=20= lisp/emacs-lisp/regexp-opt.el=20=20=20=20|=2037=20= ++++++++++++++++++++++++++++----=0A=20lisp/emacs-lisp/rx.el=20=20=20=20=20= =20=20=20=20=20=20=20|=20=202=20+-=0A=20test/lisp/emacs-lisp/rx-tests.el=20= |=2013=20+++++++++++=0A=205=20files=20changed,=2063=20insertions(+),=208=20= deletions(-)=0A=0Adiff=20--git=20a/doc/lispref/searching.texi=20= b/doc/lispref/searching.texi=0Aindex=20cfbd2449b1..73a7304a3b=20100644=0A= ---=20a/doc/lispref/searching.texi=0A+++=20b/doc/lispref/searching.texi=0A= @@=20-950,7=20+950,7=20@@=20whitespace:=0A=20@end=20defun=0A=20=0A=20= @cindex=20optimize=20regexp=0A-@defun=20regexp-opt=20strings=20&optional=20= paren=0A+@defun=20regexp-opt=20strings=20&optional=20paren=20noreorder=0A= =20This=20function=20returns=20an=20efficient=20regular=20expression=20= that=20will=20match=0A=20any=20of=20the=20strings=20in=20the=20list=20= @var{strings}.=20=20This=20is=20useful=20when=20you=0A=20need=20to=20= make=20matching=20or=20searching=20as=20fast=20as=20possible---for=20= example,=0A@@=20-985,8=20+985,14=20@@=20if=20it=20is=20necessary=20to=20= ensure=20that=20a=20postfix=20operator=20appended=20to=0A=20it=20will=20= apply=20to=20the=20whole=20expression.=0A=20@end=20table=0A=20=0A-The=20= resulting=20regexp=20of=20@code{regexp-opt}=20is=20equivalent=20to=20but=20= usually=0A-more=20efficient=20than=20that=20of=20a=20simplified=20= version:=0A+The=20optional=20argument=20@var{noreorder},=20if=20= @code{nil},=20allows=20the=0A+returned=20regexp=20to=20match=20the=20= strings=20in=20any=20order.=20=20If=20non-@code{nil},=0A+the=20regexp=20= is=20equivalent=20to=20a=20chain=20of=20alternatives=20(by=20the=20= @samp{\|}=0A+operator)=20of=20the=20strings=20in=20the=20order=20given.=0A= +=0A+Up=20to=20reordering,=20the=20resulting=20regexp=20of=20= @code{regexp-opt}=20is=0A+equivalent=20to=20but=20usually=20more=20= efficient=20than=20that=20of=20a=20simplified=0A+version:=0A=20=0A=20= @example=0A=20(defun=20simplified-regexp-opt=20(strings=20&optional=20= paren)=0Adiff=20--git=20a/etc/NEWS=20b/etc/NEWS=0Aindex=20= 67e376d9b3..de9a8defbd=20100644=0A---=20a/etc/NEWS=0A+++=20b/etc/NEWS=0A= @@=20-1614,6=20+1614,13=20@@=20given=20frame=20supports=20resizing.=0A=20= This=20is=20currently=20supported=20on=20GNUish=20hosts=20and=20on=20= modern=20versions=20of=0A=20MS-Windows.=0A=20=0A++++=0A+**=20The=20= function=20'regexp-opt'=20accepts=20an=20additional=20optional=20= argument.=0A+By=20default,=20the=20regexp=20returned=20by=20'regexp-opt'=20= may=20match=20the=20strings=0A+in=20any=20order.=20=20If=20the=20new=20= third=20argument=20is=20non-nil,=20the=20match=20is=0A+guaranteed=20to=20= be=20performed=20in=20the=20order=20given,=20as=20if=20the=20strings=20= were=0A+made=20into=20a=20regexp=20by=20joining=20them=20with=20'\|'.=0A= +=0A=20=0C=0A=20*=20Changes=20in=20Emacs=2027.1=20on=20Non-Free=20= Operating=20Systems=0A=20=0Adiff=20--git=20= a/lisp/emacs-lisp/regexp-opt.el=20b/lisp/emacs-lisp/regexp-opt.el=0A= index=20152dca2309..33a5b770a0=20100644=0A---=20= a/lisp/emacs-lisp/regexp-opt.el=0A+++=20b/lisp/emacs-lisp/regexp-opt.el=0A= @@=20-84,7=20+84,7=20@@=0A=20;;;=20Code:=0A=20=0A=20;;;###autoload=0A= -(defun=20regexp-opt=20(strings=20&optional=20paren)=0A+(defun=20= regexp-opt=20(strings=20&optional=20paren=20noreorder)=0A=20=20=20= "Return=20a=20regexp=20to=20match=20a=20string=20in=20the=20list=20= STRINGS.=0A=20Each=20string=20should=20be=20unique=20in=20STRINGS=20and=20= should=20not=20contain=0A=20any=20regexps,=20quoted=20or=20not.=20=20= Optional=20PAREN=20specifies=20how=20the=0A@@=20-111,8=20+111,13=20@@=20= nil=0A=20=20=20=20=20necessary=20to=20ensure=20that=20a=20postfix=20= operator=20appended=20to=20it=20will=0A=20=20=20=20=20apply=20to=20the=20= whole=20expression.=0A=20=0A-The=20resulting=20regexp=20is=20equivalent=20= to=20but=20usually=20more=20efficient=0A-than=20that=20of=20a=20= simplified=20version:=0A+The=20optional=20argument=20NOREORDER,=20if=20= nil,=20allows=20the=20returned=0A+regexp=20to=20match=20the=20strings=20= in=20any=20order.=20=20If=20non-nil,=20the=20regexp=0A+is=20equivalent=20= to=20a=20chain=20of=20alternatives=20(by=20the=20`\\|'=20operator)=0A+of=20= the=20strings=20in=20the=20order=20given.=0A+=0A+Up=20to=20reordering,=20= the=20resulting=20regexp=20is=20equivalent=20to=20but=0A+usually=20more=20= efficient=20than=20that=20of=20a=20simplified=20version:=0A=20=0A=20=20= (defun=20simplified-regexp-opt=20(strings=20&optional=20paren)=0A=20=20=20= =20(let=20((parens=0A@@=20-133,7=20+138,15=20@@=20than=20that=20of=20a=20= simplified=20version:=0A=20=09=20=20=20(open=20(cond=20((stringp=20= paren)=20paren)=20(paren=20"\\(")))=0A=20=09=20=20=20(sorted-strings=20= (delete-dups=0A=20=09=09=09=20=20=20=20(sort=20(copy-sequence=20strings)=20= 'string-lessp)))=0A-=09=20=20=20(re=20(regexp-opt-group=20sorted-strings=20= (or=20open=20t)=20(not=20open))))=0A+=09=20=20=20(re=0A+=20=20=20=20=20=20= =20=20=20=20=20=20;;=20If=20NOREORDER=20is=20non-nil=20and=20the=20list=20= contains=20a=20prefix=0A+=20=20=20=20=20=20=20=20=20=20=20=20;;=20of=20= another=20string,=20we=20give=20up=20all=20attempts=20at=20optimisation.=0A= +=20=20=20=20=20=20=20=20=20=20=20=20;;=20There=20is=20plenty=20of=20= room=20for=20improvement=20(Bug#34641).=0A+=20=20=20=20=20=20=20=20=20=20= =20=20(if=20(and=20noreorder=20(regexp-opt--contains-prefix=20= sorted-strings))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (concat=20(or=20open=20"\\(?:")=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(mapconcat=20#'regexp-quote=20strings=20= "\\|")=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20"\\)")=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (regexp-opt-group=20sorted-strings=20(or=20open=20t)=20(not=20open)))))=0A= =20=20=20=20=20=20=20(cond=20((eq=20paren=20'words)=0A=20=09=20=20=20=20=20= (concat=20"\\<"=20re=20"\\>"))=0A=20=09=20=20=20=20((eq=20paren=20= 'symbols)=0A@@=20-313,6=20+326,22=20@@=20CHARS=20should=20be=20a=20list=20= of=20characters."=0A=20=20=20=20=20=20=20=20=20=20=20(concat=20"["=20= dash=20caret=20"]"))=0A=20=20=20=20=20=20=20(concat=20"["=20bracket=20= charset=20caret=20dash=20"]"))))=0A=20=0A+=0A+(defun=20= regexp-opt--contains-prefix=20(strings)=0A+=20=20"Whether=20a=20list=20= of=20strings=20contains=20a=20proper=20prefix=20of=20one=20of=20its=20= elements.=0A+STRINGS=20must=20be=20sorted=20and=20free=20from=20= duplicates."=0A+=20=20(let=20((s=20strings))=0A+=20=20=20=20;;=20In=20a=20= lexicographically=20sorted=20list,=20a=20string=20always=20immediately=0A= +=20=20=20=20;;=20succeeds=20one=20of=20its=20prefixes.=0A+=20=20=20=20= (while=20(and=20(cdr=20s)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(not=20(string-equal=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(car=20s)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(substring=20(cadr=20s)=200=20(min=20(length=20= (car=20s))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(length=20(cadr=20s)))))))=0A+=20=20=20=20=20=20(setq=20s=20= (cdr=20s)))=0A+=20=20=20=20(cdr=20s)))=0A+=0A+=0A=20(provide=20= 'regexp-opt)=0A=20=0A=20;;;=20regexp-opt.el=20ends=20here=0Adiff=20--git=20= a/lisp/emacs-lisp/rx.el=20b/lisp/emacs-lisp/rx.el=0Aindex=20= 715cd608c4..ca756efb49=20100644=0A---=20a/lisp/emacs-lisp/rx.el=0A+++=20= b/lisp/emacs-lisp/rx.el=0A@@=20-393,7=20+393,7=20@@=20FORM=20is=20of=20= the=20form=20`(and=20FORM1=20...)'."=0A=20=20=20(rx-group-if=0A=20=20=20=20= (if=20(memq=20nil=20(mapcar=20'stringp=20(cdr=20form)))=0A=20=20=20=20=20= =20=20=20(mapconcat=20(lambda=20(x)=20(rx-form=20x=20'|))=20(cdr=20form)=20= "\\|")=0A-=20=20=20=20=20(regexp-opt=20(cdr=20form)))=0A+=20=20=20=20=20= (regexp-opt=20(cdr=20form)=20nil=20t))=0A=20=20=20=20(and=20(memq=20= rx-parent=20'(:=20*=20t))=20rx-parent)))=0A=20=0A=20=0Adiff=20--git=20= a/test/lisp/emacs-lisp/rx-tests.el=20b/test/lisp/emacs-lisp/rx-tests.el=0A= index=20e14feda347..fa3d9b0d5e=20100644=0A---=20= a/test/lisp/emacs-lisp/rx-tests.el=0A+++=20= b/test/lisp/emacs-lisp/rx-tests.el=0A@@=20-92,5=20+92,18=20@@=0A=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(*?=20= "e")=20(+?=20"f")=20(\??=20"g")=20(??=20"h"))))=0A=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20"a*b+c?d?e*?f+?g??h??")))=0A=20=0A= +(ert-deftest=20rx-or=20()=0A+=20=20;;=20Test=20or-pattern=20reordering=20= (Bug#34641).=0A+=20=20(let=20((s=20"abc"))=0A+=20=20=20=20(should=20= (equal=20(and=20(string-match=20(rx=20(or=20"abc"=20"ab"=20"a"))=20s)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (match-string=200=20s))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20"abc"))=0A+=20=20=20=20(should=20(equal=20(and=20(string-match=20= (rx=20(or=20"ab"=20"abc"=20"a"))=20s)=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(match-string=200=20s))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"ab"))=0A+=20=20=20=20= (should=20(equal=20(and=20(string-match=20(rx=20(or=20"a"=20"ab"=20= "abc"))=20s)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(match-string=200=20s))=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20"a"))))=0A+=0A=20(provide=20'rx-tests)=0A=20;;=20= rx-tests.el=20ends=20here.=0A--=20=0A2.17.2=20(Apple=20Git-113)=0A=0A= --Apple-Mail=_D5A358D7-0A23-41FF-BD17-E7237413679F--