]> git.eshelyaron.com Git - emacs.git/commitdiff
Add standard unmatchable regexp
authorMattias Engdegård <mattiase@acm.org>
Tue, 14 May 2019 09:43:49 +0000 (11:43 +0200)
committerMattias Engdegård <mattiase@acm.org>
Wed, 15 May 2019 16:55:27 +0000 (18:55 +0200)
Add `regexp-unmatchable' as a standard unmatchable regexp, defined as
"\\`a\\`".  Use it where such a regexp is needed, replacing slower
expressions in several places.
From a suggestion by Philippe Schnoebelen.

* lisp/subr.el (regexp-unmatchable): New defconst.
* etc/NEWS (Lisp Changes): Mention `regexp-unmatchable'.
* doc/lispref/searching.texi (Regexp Functions): Document it.
* lisp/emacs-lisp/regexp-opt.el (regexp-opt)
* lisp/progmodes/cc-defs.el (cc-conditional-require-after-load)
(c-make-keywords-re)
* lisp/progmodes/cc-engine.el (c-beginning-of-statement-1)
(c-forward-<>-arglist-recur, c-forward-decl-or-cast-1)
(c-looking-at-decl-block)
* lisp/progmodes/cc-fonts.el (c-doc-line-join-re)
(c-doc-bright-comment-start-re)
* lisp/progmodes/cc-langs.el (c-populate-syntax-table)
(c-assignment-op-regexp)
(c-block-comment-ender-regexp, c-font-lock-comment-end-skip)
(c-block-comment-start-regexp, c-line-comment-start-regexp)
(c-doc-comment-start-regexp, c-decl-start-colon-kwd-re)
(c-type-decl-prefix-key, c-type-decl-operator-prefix-key)
(c-pre-id-bracelist-key, c-enum-clause-introduction-re)
(c-nonlabel-token-2-key)
* lisp/progmodes/cc-mode.el (c-doc-fl-decl-start, c-doc-fl-decl-end)
* lisp/progmodes/cc-vars.el (c-noise-macro-with-parens-name-re)
(c-noise-macro-name-re, c-make-noise-macro-regexps)
* lisp/progmodes/octave.el (octave-help-mode)
* lisp/vc/vc-bzr.el (vc-bzr-log-view-mode, vc-bzr-revision-completion-table)
* lisp/vc/vc-git.el (vc-git-log-view-mode)
* lisp/vc/vc-hg.el (vc-hg-log-view-mode)
* lisp/vc/vc-mtn.el (vc-mtn-log-view-mode):
Use `regexp-unmatchable'.
* lisp/textmodes/ispell.el (ispell-non-empty-string):
Use `regexp-unmatchable', fixing a broken never-match regexp.

18 files changed:
doc/lispref/searching.texi
etc/NEWS
lisp/emacs-lisp/regexp-opt.el
lisp/net/ange-ftp.el
lisp/progmodes/cc-defs.el
lisp/progmodes/cc-engine.el
lisp/progmodes/cc-fonts.el
lisp/progmodes/cc-langs.el
lisp/progmodes/cc-mode.el
lisp/progmodes/cc-vars.el
lisp/progmodes/grep.el
lisp/progmodes/octave.el
lisp/subr.el
lisp/textmodes/ispell.el
lisp/vc/vc-bzr.el
lisp/vc/vc-git.el
lisp/vc/vc-hg.el
lisp/vc/vc-mtn.el

index 8775254dd07b3617ec776911a5eff295bad737fc..24f30b4dac618620b6219a649bdc11ced1658c5b 100644 (file)
@@ -1070,6 +1070,13 @@ list of characters @var{chars}.
 
 @c Internal functions: regexp-opt-group
 
+@defvar regexp-unmatchable
+This variable contains a regexp that is guaranteed not to match any
+string at all.  It is particularly useful as default value for
+variables that may be set to a pattern that actually matches
+something.
+@end defvar
+
 @node Regexp Search
 @section Regular Expression Searching
 @cindex regular expression searching
index fc3ca1ea928c64bf57c9e54598b9724b65a5a280..699a04b524688825307941848a407943d01e1786 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1990,6 +1990,10 @@ returns a regexp that never matches anything, which is an identity for
 this operation.  Previously, the empty string was returned in this
 case.
 
+** New constant 'regexp-unmatchable' contains a never-matching regexp.
+It is a convenient and readable way to specify a regexp that should
+not match anything, and is as fast as any such regexp can be.
+
 \f
 * Changes in Emacs 27.1 on Non-Free Operating Systems
 
index d883752d7123752f0d5a1050529eb01cf9d1e5f7..00f72e284adcad472ff7181b2574b037f93d29c1 100644 (file)
@@ -144,9 +144,9 @@ usually more efficient than that of a simplified version:
                            (sort (copy-sequence strings) 'string-lessp)))
           (re
             (cond
-             ;; No strings: return a\` which cannot match anything.
+             ;; No strings: return an unmatchable regexp.
              ((null strings)
-              (concat (or open "\\(?:") "a\\`\\)"))
+              (concat (or open "\\(?:") regexp-unmatchable "\\)"))
              ;; If we cannot reorder, give up all attempts at
              ;; optimisation.  There is room for improvement (Bug#34641).
              ((and keep-order (regexp-opt--contains-prefix sorted-strings))
index 5af9ea75ed16292bad1ec3638a4d9f20b586258c..b0a1e1799f5ba24d7a9f53b71030b33ea7ad98b3 100644 (file)
@@ -1989,7 +1989,7 @@ on the gateway machine to do the FTP instead."
   (make-local-variable 'comint-password-prompt-regexp)
   ;; This is a regexp that can't match anything.
   ;; ange-ftp has its own ways of handling passwords.
-  (setq comint-password-prompt-regexp "\\`a\\`")
+  (setq comint-password-prompt-regexp regexp-unmatchable)
   (make-local-variable 'paragraph-start)
   (setq paragraph-start comint-prompt-regexp))
 
index cd4ed6b352eb3924d9106a74fe43ae51254d6be0..d20e3ef32d918b80aea4d1cfc58cabd45b2d32c8 100644 (file)
@@ -81,7 +81,7 @@
   (progn
     (require 'font-lock)
     (let (font-lock-keywords)
-      (font-lock-compile-keywords '("a\\`")) ; doesn't match anything.
+      (font-lock-compile-keywords (list regexp-unmatchable))
       font-lock-keywords))))
 
 \f
@@ -1890,8 +1890,8 @@ when it's needed.  The default is the current language taken from
 
     ;; Produce a regexp that doesn't match anything.
     (if adorn
-       "\\(a\\`\\)"
-      "a\\`")))
+       (concat "\\(" regexp-unmatchable "\\)")
+      regexp-unmatchable)))
 
 (put 'c-make-keywords-re 'lisp-indent-function 1)
 
index ed8310d0e67fb11729251112397a43274cb12572..41bab270daac6e7bff598eac2d542498b904a1e3 100644 (file)
@@ -907,7 +907,7 @@ comment at the start of cc-engine.el for more info."
        stack
        ;; Regexp which matches "for", "if", etc.
        (cond-key (or c-opt-block-stmt-key
-                     "a\\`"))  ; Doesn't match anything.
+                     regexp-unmatchable))
        ;; Return value.
        (ret 'same)
        ;; Positions of the last three sexps or bounds we've stopped at.
@@ -7646,7 +7646,9 @@ comment at the start of cc-engine.el for more info."
                (progn
                  (c-forward-syntactic-ws)
                  (when (or (and c-record-type-identifiers all-types)
-                           (not (equal c-inside-<>-type-key "\\(a\\`\\)")))
+                           (not (equal c-inside-<>-type-key
+                                       (concat
+                                        "\\(" regexp-unmatchable "\\)"))))
                    (c-forward-syntactic-ws)
                    (cond
                     ((eq (char-after) ??)
@@ -9253,7 +9255,7 @@ This function might do hidden buffer changes."
       ;; Skip over type decl prefix operators.  (Note similar code in
       ;; `c-forward-declarator'.)
       (if (and c-recognize-typeless-decls
-              (equal c-type-decl-prefix-key "a\\`")) ; Regexp which doesn't match
+              (equal c-type-decl-prefix-key regexp-unmatchable))
          (when (eq (char-after) ?\()
            (progn
              (setq paren-depth (1+ paren-depth))
@@ -10886,7 +10888,7 @@ comment at the start of cc-engine.el for more info."
              ;; legal because it's part of a "compound keyword" like
              ;; "enum class".  Of course, if c-after-brace-list-key
              ;; is nil, we can skip the test.
-             (or (equal c-after-brace-list-key "a\\`") ; Regexp which doesn't match
+             (or (equal c-after-brace-list-key regexp-unmatchable)
                  (save-match-data
                    (save-excursion
                      (not
index 5f09be60a67283be57e7f80d899a50aa81caa810..b3a9dd480b8e2eeb94447c39638c7a8d3b6510fc 100644 (file)
@@ -2580,14 +2580,14 @@ need for `pike-font-lock-extra-types'.")
 \f
 ;;; Doc comments.
 
-(defvar c-doc-line-join-re "a\\`")
+(defvar c-doc-line-join-re regexp-unmatchable)
 ;; Matches a join of two lines in a doc comment.
 ;; This should not be changed directly, but instead set by
 ;; `c-setup-doc-comment-style'.  This variable is used in `c-find-decl-spots'
 ;; in (e.g.) autodoc style comments to bridge the gap between a "@\n" at an
 ;; EOL and the token following "//!" on the next line.
 
-(defvar c-doc-bright-comment-start-re "a\\`")
+(defvar c-doc-bright-comment-start-re regexp-unmatchable)
 ;; Matches the start of a "bright" comment, one whose contents may be
 ;; fontified by, e.g., `c-font-lock-declarations'.
 
index 30da10a6c03bb0f4f624a991d5e3f779fb226bb7..9d2f689e58421e21e3eb4af6bba0f6cbad83d5ef 100644 (file)
@@ -945,7 +945,7 @@ file name in angle brackets or quotes."
         (c-make-keywords-re 'appendable
           (c-lang-const c-cpp-include-directives))
         "[ \t]*")
-      "a\\`"))                         ; Doesn't match anything
+      regexp-unmatchable))
 (c-lang-defvar c-cpp-include-key (c-lang-const c-cpp-include-key))
 
 (c-lang-defconst c-opt-cpp-macro-define
@@ -1331,7 +1331,7 @@ operators."
           (c--set-difference (c-lang-const c-assignment-operators)
                              '("=")
                              :test 'string-equal)))
-      "a\\`"))                         ; Doesn't match anything.
+      regexp-unmatchable))
 (c-lang-defvar c-assignment-op-regexp
   (c-lang-const c-assignment-op-regexp))
 
@@ -1554,7 +1554,7 @@ properly."
   ;; language)
   t (if (c-lang-const c-block-comment-ender)
        (regexp-quote (c-lang-const c-block-comment-ender))
-      "a\\`"))                         ; Doesn't match anything.
+      regexp-unmatchable))
 (c-lang-defvar c-block-comment-ender-regexp
               (c-lang-const c-block-comment-ender-regexp))
 
@@ -1565,7 +1565,7 @@ properly."
   ;; `font-lock-comment-delimiter-face'.
   t (if (c-lang-const c-block-comment-ender)
        (concat "[ \t]*" (c-lang-const c-block-comment-ender-regexp))
-      "a\\`"))                         ; Doesn't match anything.
+      regexp-unmatchable))
 (c-lang-setvar font-lock-comment-end-skip
               (c-lang-const c-font-lock-comment-end-skip))
 
@@ -1584,7 +1584,7 @@ properly."
   ;; language)
   t (if (c-lang-const c-block-comment-starter)
        (regexp-quote (c-lang-const c-block-comment-starter))
-      "a\\`"))                         ; Doesn't match anything.
+      regexp-unmatchable))
 (c-lang-defvar c-block-comment-start-regexp
   (c-lang-const c-block-comment-start-regexp))
 
@@ -1593,7 +1593,7 @@ properly."
   ;; language; it does in all 7 CC Mode languages).
   t (if (c-lang-const c-line-comment-starter)
        (regexp-quote (c-lang-const c-line-comment-starter))
-      "a\\`"))                         ; Doesn't match anything.
+      regexp-unmatchable))
 (c-lang-defvar c-line-comment-start-regexp
               (c-lang-const c-line-comment-start-regexp))
 
@@ -1628,7 +1628,7 @@ starter."
 
 (c-lang-defconst c-doc-comment-start-regexp
   "Regexp to match the start of documentation comments."
-  t    "a\\`"  ; Doesn't match anything.
+  t    regexp-unmatchable
   ;; From font-lock.el: `doxygen' uses /*! while others use /**.
   (c c++ objc) "/\\*[*!]"
   java "/\\*\\*"
@@ -3112,7 +3112,7 @@ Note that Java specific rules are currently applied to tell this from
   "Regexp matching a keyword that is followed by a colon, where
   the whole construct can precede a declaration.
   E.g. \"public:\" in C++."
-  t "a\\`"                             ; Doesn't match anything.
+  t regexp-unmatchable
   c++ (c-make-keywords-re t (c-lang-const c-protection-kwds)))
 (c-lang-defvar c-decl-start-colon-kwd-re
   (c-lang-const c-decl-start-colon-kwd-re))
@@ -3309,7 +3309,7 @@ Identifier syntax is in effect when this is matched \(see
   t (if (c-lang-const c-type-modifier-kwds)
        (concat (regexp-opt (c-lang-const c-type-modifier-kwds) t) "\\>")
       ;; Default to a regexp that never matches.
-      "a\\`")
+      regexp-unmatchable)
   ;; Check that there's no "=" afterwards to avoid matching tokens
   ;; like "*=".
   (c objc) (concat "\\("
@@ -3347,7 +3347,7 @@ that might precede the identifier in a declaration, e.g. the
 as the end of the operator.  Identifier syntax is in effect when
 this is matched \(see `c-identifier-syntax-table')."
   t ;; Default to a regexp that never matches.
-    "a\\`"
+    regexp-unmatchable
   ;; Check that there's no "=" afterwards to avoid matching tokens
   ;; like "*=".
   (c objc) (concat "\\(\\*\\)"
@@ -3506,7 +3506,7 @@ list."
 (c-lang-defconst c-pre-id-bracelist-key
   "A regexp matching tokens which, preceding an identifier, signify a bracelist.
 "
-  t "a\\`"                             ; Doesn't match anything.
+  t regexp-unmatchable
   c++ "new\\([^[:alnum:]_$]\\|$\\)\\|&&?\\(\\S.\\|$\\)")
 (c-lang-defvar c-pre-id-bracelist-key (c-lang-const c-pre-id-bracelist-key))
 
@@ -3562,7 +3562,7 @@ the invalidity of the putative template construct."
         ;; before the '{' of the enum list, to avoid searching too far.
         "[^][{};/#=]*"
         "{")
-      "a\\`"))                         ; Doesn't match anything.
+      regexp-unmatchable))
 (c-lang-defvar c-enum-clause-introduction-re
               (c-lang-const c-enum-clause-introduction-re))
 
@@ -3703,7 +3703,7 @@ Only used if `c-recognize-colon-labels' is set."
   "Regexp matching things that can't occur two symbols before a colon in
 a label construct.  This catches C++'s inheritance construct \"class foo
 : bar\".  Only used if `c-recognize-colon-labels' is set."
-  t "a\\`"                             ; Doesn't match anything.
+  t regexp-unmatchable
   c++ (c-make-keywords-re t '("class")))
 (c-lang-defvar c-nonlabel-token-2-key (c-lang-const c-nonlabel-token-2-key))
 
index bd62fc754ab3fc6045c181ee6e62f8f0a8f8b5aa..e4ff9f019d3ad133b78f5674ccaefad4e7a074a5 100644 (file)
@@ -1825,7 +1825,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
   ;; by `c-doc-line-join-re'), return the position of the first line of the
   ;; sequence.  Otherwise, return nil.  Point has no significance at entry to
   ;; and exit from this function.
-  (when (not (equal c-doc-line-join-re "a\\`"))
+  (when (not (equal c-doc-line-join-re regexp-unmatchable))
     (goto-char pos)
     (back-to-indentation)
     (and (or (looking-at c-comment-start-regexp)
@@ -1842,7 +1842,7 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".")
   ;; marker (as defined by `c-doc-line-join-re), return the position of
   ;; the BOL at the end of the sequence.  Otherwise, return nil.  Point has no
   ;; significance at entry to and exit from this function.
-  (when (not (equal c-doc-line-join-re "a\\`"))
+  (when (not (equal c-doc-line-join-re regexp-unmatchable))
     (goto-char pos)
     (back-to-indentation)
     (let ((here (point)))
index 6e8acd4c0dda334b99392a437fbddf81ff6c438f..b818bced7306ab1a7a8c1d24ca4b0e7eda229d29 100644 (file)
@@ -1648,9 +1648,9 @@ white space either before or after the operator, but not both."
   :group 'c)
 
 ;; Initialize the next two to a regexp which never matches.
-(defvar c-noise-macro-with-parens-name-re "a\\`")
+(defvar c-noise-macro-with-parens-name-re regexp-unmatchable)
 (make-variable-buffer-local 'c-noise-macro-with-parens-name-re)
-(defvar c-noise-macro-name-re "a\\`")
+(defvar c-noise-macro-name-re regexp-unmatchable)
 (make-variable-buffer-local 'c-noise-macro-name-re)
 
 (defcustom c-noise-macro-names nil
@@ -1682,7 +1682,7 @@ These are recognized by CC Mode only in declarations."
   ;; Convert `c-noise-macro-names' and `c-noise-macro-with-parens-names' into
   ;; `c-noise-macro-name-re' and `c-noise-macro-with-parens-name-re'.
   (setq c-noise-macro-with-parens-name-re
-       (cond ((null c-noise-macro-with-parens-names) "a\\`") ; Never matches.
+       (cond ((null c-noise-macro-with-parens-names) regexp-unmatchable)
              ((consp c-noise-macro-with-parens-names)
               (concat (regexp-opt c-noise-macro-with-parens-names t)
                       "\\([^[:alnum:]_$]\\|$\\)"))
@@ -1691,7 +1691,7 @@ These are recognized by CC Mode only in declarations."
              (t (error "c-make-noise-macro-regexps: \
 c-noise-macro-with-parens-names is invalid: %s" c-noise-macro-with-parens-names))))
   (setq c-noise-macro-name-re
-       (cond ((null c-noise-macro-names) "a\\`") ; Never matches anything.
+       (cond ((null c-noise-macro-names) regexp-unmatchable)
              ((consp c-noise-macro-names)
               (concat (regexp-opt c-noise-macro-names t)
                       "\\([^[:alnum:]_$]\\|$\\)"))
index 85f9078d46dbb2e5f181f6d309af04d9b90c319b..79178c4346ed4006d1ebdcbdddcf73727ee89a68 100644 (file)
@@ -837,7 +837,8 @@ This function is called from `compilation-filter-hook'."
        grep-mode-line-matches)
   ;; compilation-directory-matcher can't be nil, so we set it to a regexp that
   ;; can never match.
-  (set (make-local-variable 'compilation-directory-matcher) '("\\`a\\`"))
+  (set (make-local-variable 'compilation-directory-matcher)
+       (list regexp-unmatchable))
   (set (make-local-variable 'compilation-process-setup-function)
        'grep-process-setup)
   (set (make-local-variable 'compilation-disable-input) t)
index 52e5fd477f42f5ce15e13fb77ba6ee93c22a1946..8a7e24e5ada209a40243a3fff15dd1027e12af63 100644 (file)
@@ -1691,7 +1691,7 @@ code line."
   (eval-and-compile (require 'help-mode))
   ;; Don't highlight `EXAMPLE' as elisp symbols by using a regexp that
   ;; can never match.
-  (setq-local help-xref-symbol-regexp "x\\`"))
+  (setq-local help-xref-symbol-regexp regexp-unmatchable))
 
 (defun octave-help (fn)
   "Display the documentation of FN."
index be21dc67a0d4ef7907d918d90091fdcccbe33263..05fb9fea68f1dbf24858a36fd0de5ddf190bc761 100644 (file)
@@ -5544,4 +5544,8 @@ returned list are in the same order as in TREE.
 ;; for discoverability:
 (defalias 'flatten-list 'flatten-tree)
 
+;; The initial anchoring is for better performance in searching matches.
+(defconst regexp-unmatchable "\\`a\\`"
+  "Standard regexp guaranteed not to match any string at all.")
+
 ;;; subr.el ends here
index 6553a2799bb45af234ab583d18cbbdc77e88f7d1..0c5e6a183b5310567354563de1ffc7cb315be827 100644 (file)
@@ -4016,7 +4016,7 @@ You can bind this to the key C-c i in GNUS or mail by adding to
 
 (defun ispell-non-empty-string (string)
   (if (or (not string) (string-equal string ""))
-      "\\'\\`" ; An unmatchable string if string is null.
+      regexp-unmatchable
     (regexp-quote string)))
 
 
index ab5a449cd3de9856dc1a2c9d13fbcfdda9c52fa2..ee1646cae5a0c6308855bcd5eb65cab654322771 100644 (file)
@@ -702,7 +702,7 @@ or a superior directory.")
   (remove-hook 'log-view-mode-hook 'vc-bzr-log-view-mode) ;Deactivate the hack.
   (require 'add-log)
   (set (make-local-variable 'log-view-per-file-logs) nil)
-  (set (make-local-variable 'log-view-file-re) "\\`a\\`")
+  (set (make-local-variable 'log-view-file-re) regexp-unmatchable)
   (set (make-local-variable 'log-view-message-re)
        (if (eq vc-log-view-type 'short)
           "^ *\\([0-9.]+\\): \\(.*?\\)[ \t]+\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\)\\( \\[merge\\]\\)?"
@@ -1319,7 +1319,8 @@ stream.  Standard error output is discarded."
      ((string-match "\\`annotate:" string)
       (completion-table-with-context
        (substring string 0 (match-end 0))
-       (apply-partially #'completion-table-with-terminator '(":" . "\\`a\\`")
+       (apply-partially #'completion-table-with-terminator
+                        (cons ":" regexp-unmatchable)
                         #'completion-file-name-table)
        (substring string (match-end 0)) pred action))
 
index 192e6cf68f643b1047d53d223ee7c188cca47e52..61c13026cc56e50d76a47224d7c260179e759281 100644 (file)
@@ -1087,7 +1087,7 @@ If LIMIT is a revision string, use it as an end-revision."
 (define-derived-mode vc-git-log-view-mode log-view-mode "Git-Log-View"
   (require 'add-log) ;; We need the faces add-log.
   ;; Don't have file markers, so use impossible regexp.
-  (set (make-local-variable 'log-view-file-re) "\\`a\\`")
+  (set (make-local-variable 'log-view-file-re) regexp-unmatchable)
   (set (make-local-variable 'log-view-per-file-logs) nil)
   (set (make-local-variable 'log-view-message-re)
        (if (not (eq vc-log-view-type 'long))
index d3f132dae70bb7b1b3c08ce8649329009c3d63a0..876d824ceacd63f60d98f374b4cfbaf2a03a1aac 100644 (file)
@@ -444,7 +444,7 @@ If LIMIT is non-nil, show no more than this many entries."
 
 (define-derived-mode vc-hg-log-view-mode log-view-mode "Hg-Log-View"
   (require 'add-log) ;; we need the add-log faces
-  (set (make-local-variable 'log-view-file-re) "\\`a\\`")
+  (set (make-local-variable 'log-view-file-re) regexp-unmatchable)
   (set (make-local-variable 'log-view-per-file-logs) nil)
   (set (make-local-variable 'log-view-message-re)
        (if (eq vc-log-view-type 'short)
index f0b12489c1b89b55587810d2d2f88818b93431fe..91cc28021cf3fc91960b95b086af518b2e8cd316 100644 (file)
@@ -240,7 +240,7 @@ If LIMIT is non-nil, show no more than this many entries."
 
 (define-derived-mode vc-mtn-log-view-mode log-view-mode "Mtn-Log-View"
   ;; Don't match anything.
-  (set (make-local-variable 'log-view-file-re) "\\`a\\`")
+  (set (make-local-variable 'log-view-file-re) regexp-unmatchable)
   (set (make-local-variable 'log-view-per-file-logs) nil)
   ;; TODO: Use a more precise regexp than "[ |/]+" to avoid false positives
   ;; in the ChangeLog text.