aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2019-10-27 09:54:54 +0100
committerMattias EngdegÄrd2019-10-27 09:54:54 +0100
commitcbd439e785cd1e72c3eae39ed987fda357014bf8 (patch)
tree4a10729f3ce701b2d4827259d2bedcb1bcb21cd8
parent6e66d9a95c49f867da26ca897635f5e57561d0c7 (diff)
downloademacs-cbd439e785cd1e72c3eae39ed987fda357014bf8.tar.gz
emacs-cbd439e785cd1e72c3eae39ed987fda357014bf8.zip
Expand rx definitions inside (not ...)
* lisp/emacs-lisp/rx.el (rx--translate-not): * test/lisp/emacs-lisp/rx-tests.el (rx-not, rx-def-in-not): * doc/lispref/searching.texi (Rx Constructs, Extending Rx): Allow user-defined rx constructs to be expanded inside (not ...) forms, for better composability (bug#37849).
-rw-r--r--doc/lispref/searching.texi4
-rw-r--r--lisp/emacs-lisp/rx.el3
-rw-r--r--test/lisp/emacs-lisp/rx-tests.el17
3 files changed, 21 insertions, 3 deletions
diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi
index 5178575a3bb..74b15cfc7fd 100644
--- a/doc/lispref/searching.texi
+++ b/doc/lispref/searching.texi
@@ -1214,7 +1214,7 @@ Corresponding string regexp: @samp{[@dots{}]}
1214@item @code{(not @var{charspec})} 1214@item @code{(not @var{charspec})}
1215@cindex @code{not} in rx 1215@cindex @code{not} in rx
1216Match a character not included in @var{charspec}. @var{charspec} can 1216Match a character not included in @var{charspec}. @var{charspec} can
1217be an @code{any}, @code{syntax} or @code{category} form, or a 1217be an @code{any}, @code{not}, @code{syntax} or @code{category} form, or a
1218character class.@* 1218character class.@*
1219Corresponding string regexp: @samp{[^@dots{}]}, @samp{\S@var{code}}, 1219Corresponding string regexp: @samp{[^@dots{}]}, @samp{\S@var{code}},
1220@samp{\C@var{code}} 1220@samp{\C@var{code}}
@@ -1581,7 +1581,7 @@ when they are used, not when they are defined.
1581User-defined forms are allowed wherever arbitrary @code{rx} 1581User-defined forms are allowed wherever arbitrary @code{rx}
1582expressions are expected; for example, in the body of a 1582expressions are expected; for example, in the body of a
1583@code{zero-or-one} form, but not inside @code{any} or @code{category} 1583@code{zero-or-one} form, but not inside @code{any} or @code{category}
1584forms. 1584forms. They are also allowed inside @code{not} forms.
1585@end itemize 1585@end itemize
1586 1586
1587@defmac rx-define name [arglist] rx-form 1587@defmac rx-define name [arglist] rx-form
diff --git a/lisp/emacs-lisp/rx.el b/lisp/emacs-lisp/rx.el
index d7677f14443..52a35ffa2a7 100644
--- a/lisp/emacs-lisp/rx.el
+++ b/lisp/emacs-lisp/rx.el
@@ -477,6 +477,9 @@ If NEGATED, negate the sense (thus making it positive)."
477 ((eq arg 'word-boundary) 477 ((eq arg 'word-boundary)
478 (rx--translate-symbol 478 (rx--translate-symbol
479 (if negated 'word-boundary 'not-word-boundary))) 479 (if negated 'word-boundary 'not-word-boundary)))
480 ((let ((expanded (rx--expand-def arg)))
481 (and expanded
482 (rx--translate-not negated (list expanded)))))
480 (t (error "Illegal argument to rx `not': %S" arg))))) 483 (t (error "Illegal argument to rx `not': %S" arg)))))
481 484
482(defun rx--atomic-regexp (item) 485(defun rx--atomic-regexp (item)
diff --git a/test/lisp/emacs-lisp/rx-tests.el b/test/lisp/emacs-lisp/rx-tests.el
index ef2541d83af..4ecc805aead 100644
--- a/test/lisp/emacs-lisp/rx-tests.el
+++ b/test/lisp/emacs-lisp/rx-tests.el
@@ -268,7 +268,9 @@
268 (should (equal (rx (not (syntax punctuation)) (not (syntax escape))) 268 (should (equal (rx (not (syntax punctuation)) (not (syntax escape)))
269 "\\S.\\S\\")) 269 "\\S.\\S\\"))
270 (should (equal (rx (not (category tone-mark)) (not (category lao))) 270 (should (equal (rx (not (category tone-mark)) (not (category lao)))
271 "\\C4\\Co"))) 271 "\\C4\\Co"))
272 (should (equal (rx (not (not ascii)) (not (not (not (any "a-z")))))
273 "[[:ascii:]][^a-z]")))
272 274
273(ert-deftest rx-group () 275(ert-deftest rx-group ()
274 (should (equal (rx (group nonl) (submatch "x") 276 (should (equal (rx (group nonl) (submatch "x")
@@ -404,6 +406,19 @@
404 (should-error (rx-let-eval '((not-char () "x")) nil)) 406 (should-error (rx-let-eval '((not-char () "x")) nil))
405 (should-error (rx-let-eval '((not-char "x")) nil))) 407 (should-error (rx-let-eval '((not-char "x")) nil)))
406 408
409(ert-deftest rx-def-in-not ()
410 "Test definition expansion inside (not ...)."
411 (rx-let ((a alpha)
412 (b (not hex))
413 (c (not (category base)))
414 (d (x) (any ?a x ?z))
415 (e (x) (syntax x))
416 (f (not b)))
417 (should (equal (rx (not a) (not b) (not c) (not f))
418 "[^[:alpha:]][[:xdigit:]]\\c.[^[:xdigit:]]"))
419 (should (equal (rx (not (d ?m)) (not (e symbol)))
420 "[^amz]\\S_"))))
421
407(ert-deftest rx-constituents () 422(ert-deftest rx-constituents ()
408 (let ((rx-constituents 423 (let ((rx-constituents
409 (append '((beta . gamma) 424 (append '((beta . gamma)