Correct regexp-opt return value for empty string list

When regexp-opt is called with an empty list of strings, return a regexp
that doesn't match anything instead of the empty string (Bug#20307).

* doc/lispref/searching.texi (Regular Expression Functions):
* etc/NEWS:
Document the new behaviour.
* lisp/emacs-lisp/regexp-opt.el (regexp-opt):
Return a never-match regexp for empty inputs.
This commit is contained in:
Mattias Engdegård 2019-02-25 15:22:02 +01:00
parent da758046da
commit 7bda34af52
3 changed files with 24 additions and 8 deletions

View file

@ -960,6 +960,9 @@ possible. A hand-tuned regular expression can sometimes be slightly
more efficient, but is almost never worth the effort.}.
@c E.g., see https://debbugs.gnu.org/2816
If @var{strings} is the empty list, the return value is a regexp that
never matches anything.
The optional argument @var{paren} can be any of the following:
@table @asis

View file

@ -1649,6 +1649,12 @@ in any order. If the new third argument is non-nil, the match is
guaranteed to be performed in the order given, as if the strings were
made into a regexp by joining them with '\|'.
+++
** The function 'regexp-opt', when given an empty list of strings, now
returns a regexp that never matches anything, which is an identity for
this operation. Previously, the empty string was returned in this
case.
* Changes in Emacs 27.1 on Non-Free Operating Systems

View file

@ -90,6 +90,9 @@ Each string should be unique in STRINGS and should not contain
any regexps, quoted or not. Optional PAREN specifies how the
returned regexp is surrounded by grouping constructs.
If STRINGS is the empty list, the return value is a regexp that
never matches anything.
The optional argument PAREN can be any of the following:
a string
@ -140,14 +143,18 @@ usually more efficient than that of a simplified version:
(sorted-strings (delete-dups
(sort (copy-sequence strings) 'string-lessp)))
(re
;; If NOREORDER is non-nil and the list contains a prefix
;; of another string, we give up all attempts at optimisation.
;; There is plenty of room for improvement (Bug#34641).
(if (and noreorder (regexp-opt--contains-prefix sorted-strings))
(concat (or open "\\(?:")
(mapconcat #'regexp-quote strings "\\|")
"\\)")
(regexp-opt-group sorted-strings (or open t) (not open)))))
(cond
;; No strings: return a\` which cannot match anything.
((null strings)
(concat (or open "\\(?:") "a\\`\\)"))
;; If we cannot reorder, give up all attempts at
;; optimisation. There is room for improvement (Bug#34641).
((and noreorder (regexp-opt--contains-prefix sorted-strings))
(concat (or open "\\(?:")
(mapconcat #'regexp-quote strings "\\|")
"\\)"))
(t
(regexp-opt-group sorted-strings (or open t) (not open))))))
(cond ((eq paren 'words)
(concat "\\<" re "\\>"))
((eq paren 'symbols)