diff options
| author | Mattias EngdegÄrd | 2019-10-27 09:54:54 +0100 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2019-10-27 09:54:54 +0100 |
| commit | cbd439e785cd1e72c3eae39ed987fda357014bf8 (patch) | |
| tree | 4a10729f3ce701b2d4827259d2bedcb1bcb21cd8 | |
| parent | 6e66d9a95c49f867da26ca897635f5e57561d0c7 (diff) | |
| download | emacs-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.texi | 4 | ||||
| -rw-r--r-- | lisp/emacs-lisp/rx.el | 3 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/rx-tests.el | 17 |
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 |
| 1216 | Match a character not included in @var{charspec}. @var{charspec} can | 1216 | Match a character not included in @var{charspec}. @var{charspec} can |
| 1217 | be an @code{any}, @code{syntax} or @code{category} form, or a | 1217 | be an @code{any}, @code{not}, @code{syntax} or @code{category} form, or a |
| 1218 | character class.@* | 1218 | character class.@* |
| 1219 | Corresponding string regexp: @samp{[^@dots{}]}, @samp{\S@var{code}}, | 1219 | Corresponding 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. | |||
| 1581 | User-defined forms are allowed wherever arbitrary @code{rx} | 1581 | User-defined forms are allowed wherever arbitrary @code{rx} |
| 1582 | expressions are expected; for example, in the body of a | 1582 | expressions 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} |
| 1584 | forms. | 1584 | forms. 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) |