;; Tests for the regular expression builder -*- lexical-binding: t -*- (add-to-list 'load-path ".") (load "init" nil t) (init-rst-ert t) (ert-deftest rst-re () "Tests `rst-re'." (should (equal (rst-re "xy") "xy")) (should (equal (rst-re ?A) "A")) (should (equal (rst-re ?$) "\\$")) (should (equal (rst-re 'exm-tag) "\\.\\.")) (should (equal (rst-re "xy" ?A ?$ 'exm-tag) "xyA\\$\\.\\.")) (should (equal (rst-re '(:seq "xy" ?A ?$ exm-tag)) "xyA\\$\\.\\.")) (should (equal (rst-re '(:shy "xy" ?A ?$ exm-tag)) "\\(?:xyA\\$\\.\\.\\)")) (should (equal (rst-re '(:grp "xy" ?A ?$ exm-tag)) "\\(xyA\\$\\.\\.\\)")) (should (equal (rst-re '(:alt "xy" ?A ?$ exm-tag)) "\\(?:xy\\|A\\|\\$\\|\\.\\.\\)")) (should (equal (rst-re '(:seq (:seq "xy" ?A ?$ exm-tag))) "xyA\\$\\.\\.")) (should (equal (rst-re '(:grp (:alt "xy" ?A ?$ exm-tag))) "\\(\\(?:xy\\|A\\|\\$\\|\\.\\.\\)\\)")) (should (equal (rst-re '(:alt (:grp "xy" ?A ?$ exm-tag))) "\\(?:\\(xyA\\$\\.\\.\\)\\)")) (should (equal (rst-re '(:alt "xy" ?A) '(:grp ?$ exm-tag)) "\\(?:xy\\|A\\)\\(\\$\\.\\.\\)")) (should-error (rst-re '(:unknown "xy"))) (should-error (rst-re [1])) ) (defun re-equal-modify-orig (orig loc refactored repls) (let ((case-fold-search nil)) (while (string-match "\\[ \t]" orig) ;; Transpose horizontal whitespace (setq orig (replace-match "[\t ]" t nil orig))) (while (string-match "\\\\s \\*\\$" orig) ;; Replace symbolic whitespace (setq orig (replace-match "[\t ]*$" t nil orig))) (dolist (regex-repl repls) (if (string-match (car regex-repl) orig) (setq orig (replace-match (cdr regex-repl) t t orig)) (error "Replacement regex /%s/ didn't match in '%s' for location '%s'" (car regex-repl) orig loc))) orig)) (defun re-equal (orig loc refactored &rest repls) "Compare regex ORIG at location LOC to REFACTORED. REPLS starts with a list of cons cells telling where regex in car is replaced by cdr in ORIG." (equal (re-equal-modify-orig orig loc refactored repls) refactored)) (defun re-equal-explain (orig loc refactored &rest repls) (setq orig (re-equal-modify-orig orig loc refactored repls)) (ert--explain-not-equal orig refactored)) (put 're-equal 'ert-explainer 're-equal-explain) (defun re-check-matches (orig loc refactored s pairs) "Check matches and return those pairs which didn't work" (let ((case-fold-search nil) failed) (dolist (pair pairs failed) (let ((orig-mtc (if (string-match orig s) (match-string (car pair) s))) (refa-mtc (if (string-match refactored s) (match-string (cdr pair) s)))) (if (not orig-mtc) (error "Original regex '%s' didn't match string '%s' for location '%s'" orig s loc) (if (not refa-mtc) (error "Refactored regex '%s' didn't match string '%s' for location '%s'" refactored s loc) (if (not (equal orig-mtc refa-mtc)) (push pair failed)))))))) (defun re-equal-matches (orig loc refactored matches &rest repls) "Like `re-equal'. However, if MATCHES is non-nil it must be a list with a string and cons cells each consisting of two numbers. For each cons cell the string is matched with ORIG and REFACTORED and the numbered matches are compared." (and (equal (re-equal-modify-orig orig loc refactored repls) refactored) (not (re-check-matches orig loc refactored (car matches) (cdr matches))))) (defun re-equal-matches-explain (orig loc refactored matches &rest repls) (if (not (equal (re-equal-modify-orig orig loc refactored repls) refactored)) (apply 're-equal-explain orig loc refactored repls) (let (result) (dolist (failed (re-check-matches orig loc refactored (car matches) (cdr matches)) result) (push (list 'matchers-didnt-match (car failed) (cdr failed)) result))))) (put 're-equal-matches 'ert-explainer 're-equal-matches-explain) (ert-deftest rst-re-refactoring () "Test the refactorings done based on rst_el_1_68." ;; Any comment or string "=== rst.el.~rst_el_1_68~:..." gives the line number ;; of the refactored code in the original file for the previous expression. (let* ((rst-bullets '(?- ?* ?+)) ;; === rst.el.~rst_el_1_68~:451 (rst-re-bullets (format "\\([%s][ \t]\\)[^ \t]" (regexp-quote (concat rst-bullets)))) ;; === rst.el.~rst_el_1_68~:1604 ;; More parameters (c ?*) (len 10) (char ?+) (adornment "$$$$") (ado-re (regexp-quote adornment)) (fromchar ?.) ) (should (re-equal "^\\.\\. " "=== rst.el.~rst_el_1_68~:398" (rst-re "^" 'exm-sta) (cons " $" "[ ]+") ;; Any whitespace may follow )) (should (re-equal "^[ \t]*\\S *\\w\\S *" "=== rst.el.~rst_el_1_68~:567" (rst-re 'lin-beg "\\S *\\w\\S *") )) (should (re-equal "::[ \t]*$" "=== rst.el.~rst_el_1_68~:591" (rst-re 'dcl-tag 'lin-end) )) (should (re-equal "\\.\\.\\.[ \t]*$" "=== rst.el.~rst_el_1_68~:592" (rst-re 'ell-tag 'lin-end) )) (should (re-equal ".[ \t]*$" "=== rst.el.~rst_el_1_68~:594" (rst-re "." 'lin-end) )) (should (re-equal "^[ \t]+" "=== rst.el.~rst_el_1_68~:605" (rst-re 'hws-sta) (cons "^^" "") ;; No need to anchor for looking-at )) (should (re-equal "^[ \t]*$" "=== rst.el.~rst_el_1_68~:744" (rst-re 'lin-end) (cons "^^" "") ;; No need to anchor for looking-at )) (should (re-equal "^[ \t]*$" "=== rst.el.~rst_el_1_68~:1517" (rst-re 'lin-end) (cons "^^" "") ;; No need to anchor for looking-at )) (should (re-equal "^[ \t]*$" "=== rst.el.~rst_el_1_68~:1545" (rst-re 'lin-end) (cons "^^" "") ;; No need to anchor for looking-at )) (should (re-equal "^[ \t]*$" "=== rst.el.~rst_el_1_68~:1548" (rst-re 'lin-end) (cons "^^" "") ;; No need to anchor for looking-at )) (should (re-equal "[0-9]+" "=== rst.el.~rst_el_1_68~:1657" (rst-re 'num-tag) )) (should (re-equal "[IVXLCDMivxlcdm]+" "=== rst.el.~rst_el_1_68~:1661" (rst-re 'rom-tag) )) (should (re-equal "[IVXLCDMivxlcdm]+" "=== rst.el.~rst_el_1_68~:1677" (rst-re 'rom-tag) )) (should (re-equal "[a-zA-Z]" "=== rst.el.~rst_el_1_68~:1685" (rst-re 'ltr-tag) )) (should (re-equal "[ \t\n]*\\'" "=== rst.el.~rst_el_1_68~:1762" (rst-re "[ \t\n]*\\'") )) (should (re-equal "\\S .*\\S " "=== rst.el.~rst_el_1_68~:1767" (rst-re "\\S .*\\S ") )) (should (re-equal "[ \t]*$" "=== rst.el.~rst_el_1_68~:2066" (rst-re 'lin-end) )) (should (re-equal "[ \t]*$" "=== rst.el.~rst_el_1_68~:2366" (rst-re 'lin-end) )) (should (re-equal "^[ \t]*$" "=== rst.el.~rst_el_1_68~:2414" (rst-re 'lin-end) (cons "^^" "") ;; No need to anchor for looking-at )) (should (re-equal "[ \t]*$" "=== rst.el.~rst_el_1_68~:2610" (rst-re 'lin-end) )) (should (re-equal "[ \t]*$" "=== rst.el.~rst_el_1_68~:2612" (rst-re 'lin-end) )) (should (re-equal "[ \t]*$" "=== rst.el.~rst_el_1_68~:2645" (rst-re 'lin-end) )) (should (re-equal "[^ \t]\\|[ \t]*\\.\\.[^ \t]\\|.*::$" "=== rst.el.~rst_el_1_68~:3177" (rst-re '(:alt "[^ \t]" (:seq hws-tag exm-tag "[^ \t]") (:seq ".*" dcl-tag lin-end))) (cons "^" "\\(?:") (cons "$" "\\)") ;; Add outermost shy group (cons "::\\$" "::[ ]*$") ;; Allow trailing space after double ;; colon )) (should (re-equal "\\s *$" "=== rst.el.~rst_el_1_68~:3209" (rst-re 'lin-end) )) (should (re-equal "^\\s *$" "=== rst.el.~rst_el_1_68~:3215" (rst-re 'linemp-tag) )) (should (re-equal "\\s *$" "=== rst.el.~rst_el_1_68~:3253" (rst-re 'lin-end) )) (should (re-equal "\\s *" "=== rst.el.~rst_el_1_68~:3256" (rst-re 'hws-tag) (cons "\\\\s \\*" "[\t ]*") ;; Replace symbolic by real whitespace )) (should (re-equal "\\s *$" "=== rst.el.~rst_el_1_68~:3261" (rst-re 'lin-end) )) (should (re-equal "\\s *" "=== rst.el.~rst_el_1_68~:3268" (rst-re 'hws-tag) (cons "\\\\s \\*" "[\t ]*") ;; Replace symbolic by real whitespace )) (should (re-equal (regexp-quote adornment) "=== rst.el.~rst_el_1_68~:3346" (rst-re (regexp-quote adornment)) )) (should (re-equal "\\s *$" "=== rst.el.~rst_el_1_68~:3354" (rst-re 'lin-end) )) (should (re-equal "\\s *$" "=== rst.el.~rst_el_1_68~:3358" (rst-re 'lin-end) )) (should (re-equal "\\s *$" "=== rst.el.~rst_el_1_68~:3374" (rst-re 'lin-end) )) (should (re-equal (concat "\\(" ado-re "\\)\\s *$") "=== rst.el.~rst_el_1_68~:3377" (rst-re (list :grp ado-re) 'lin-end) )) (should (re-equal (concat "\\(" ado-re "\\)\\s *$") "=== rst.el.~rst_el_1_68~:3393" (rst-re (list :grp ado-re) 'lin-end) )) (should (re-equal (concat "^" (regexp-quote (string fromchar)) "+\\( *\\)$") "=== rst.el.~rst_el_1_68~:3590" (rst-re "^" fromchar "+\\( *\\)$") )) (should (re-equal "\f\\|>*[ \t]*$\\|>*[ \t]*[-+*] \\|>*[ \t]*[0-9#]+\\. " "=== rst.el.~rst_el_1_68~:391" (rst-re '(:alt "\f" lin-end (:seq hws-tag itmany-sta-1))) (cons "^" "\\(?:") (cons "$" "\\)") ;; Add outermost shy group (cons (regexp-quote "[-+*] \\|>*[ ]*[0-9#]+\\. ") "\\(\\(?:\\(?:\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\)\\.\\|(?\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\))\\)\\|[-*+\u2022\u2023\u2043]\\)\\)[ ]+" ) ;; Now matches all items (cons ">\\*" "") ;; Remove ">" prefix (cons ">\\*" "") ;; Remove another ">" prefix (cons "\\[\t ]\\+" "\\(?:[\t ]+\\|$\\)") ;; Item tag needs no ;; trailing whitespace )) (should (re-equal (format "[%s]+[ \t]*$" (char-to-string c)) "=== rst.el.~rst_el_1_68~:587" (rst-re c "+" 'lin-end) (cons "\\[\\*]" "\\*") ;; Use quoting instead of char class )) (should (re-equal (concat "^" (regexp-quote (make-string len char)) "$") "=== rst.el.~rst_el_1_68~:941" (rst-re "^" char (format "\\{%d\\}" len) "$") (cons "\\(\\\\\\+\\)\\{9\\}\\$" "\\{10\\}$") ;; Use regex repeat instead of explicit repeat )) (should (re-equal (format "#.\\|[%s]" (regexp-quote (concat rst-bullets))) "=== rst.el.~rst_el_1_68~:1653" (rst-re '(:alt enmaut-tag bul-tag)) (cons "^" "\\(?:") (cons "$" "\\)") ;; Add outermost shy group (cons (regexp-quote "[-\\*\\+]") "[-*+\u2022\u2023\u2043]") ;; Wrongly quoted characters in ;; class and more bullets (cons "#\\." "\\(?:#\\.\\|(?#)\\)") ;; Use all auto enumerators )) (should (re-equal "[a-zA-Z]+" "=== rst.el.~rst_el_1_68~:1672" (rst-re 'ltr-tag) (cons "\\+$" "") ;; Wrong in source )) (should (re-equal rst-re-bullets "=== rst.el.~rst_el_1_68~:1735" (rst-re 'bul-sta) (cons (regexp-quote "[-\\*\\+]") "[-*+\u2022\u2023\u2043]") ;; Wrongly quoted characters in ;; class and more bullets (cons "\\[^ \t]" "") ;; Accept bullets without content (cons "^\\\\(" "") (cons "\\\\)" "") ;; Remove superfluous group (cons "$" "+") ;; Allow more whitespace (cons "\\[\t ]\\+" "\\(?:[\t ]+\\|$\\)") ;; Item tag needs no ;; trailing whitespace )) (should (re-equal "^\\.\\. contents[ \t]*::\\(.*\\)\n\\([ \t]+:\\w+:.*\n\\)*\\.\\." "=== rst.el.~rst_el_1_68~:2056" (rst-re "^" 'exm-sta "contents" 'dcl-tag ".*\n" "\\(?:" 'hws-sta 'fld-tag ".*\n\\)*" 'exm-tag) (cons " contents\\[\t ]\\*" "[\t ]+contents") ;; Any whitespace before but no after (cons "\\\\(\\.\\*\\\\)" ".*") ;; Remove superfluous group (cons "\\\\(" "\\(?:") ;; Make group shy (cons ":\\\\w\\+:" ":\\(?:[^:\n]\\|\\\\:\\)+:") ;; Use improved ;; field tag )) (should (re-equal "[ \t]+[^ \t]" "=== rst.el.~rst_el_1_68~:2065" (rst-re 'hws-sta "\\S ") (cons "\\[^ \t]" "\\S ") ;; Require non-whitespace instead ;; of only non-horizontal whitespace )) )) (ert-deftest rst-re-refactoring-complicated () "Try to test complicated refactorings done based on rst_el_1_68." :expected-result :failed ;; These have been reviewed logically and are ok (let* ((rst-bullets '(?- ?* ?+)) ;; === rst.el.~rst_el_1_68~:451 (rst-re-enumerator "\\(?:[a-zA-Z]\\|[0-9IVXLCDMivxlcdm]+\\)") ;; === rst.el.~rst_el_1_68~:1608 (rst-re-enumerations (format "^[ \t]*\\(%s.\\|(?%s)\\)[ \t]" rst-re-enumerator rst-re-enumerator)) ;; === rst.el.~rst_el_1_68~:1610 (rst-re-items (format "^[ \t]*\\([%s]\\|\\(#\\|%s\\)\\.\\|(?%s)\\)[ \t]" (regexp-quote (concat rst-bullets)) rst-re-enumerator rst-re-enumerator)) ;; === rst.el.~rst_el_1_68~:1616 ;; More parameters (char ?+) ) (should (re-equal rst-re-items "=== rst.el.~rst_el_1_68~:2718" (rst-re 'itmany-sta-1) (cons "^^\\[\t ]\\*" "") ;; Wrongly anchored at the beginning of ;; the line (cons (regexp-quote "\\(#\\|\\(?:[a-zA-Z]\\|[0-9IVXLCDMivxlcdm]+\\)\\)") "\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\)" ) ;; Replace counter for "\\." (cons (regexp-quote "\\(?:[a-zA-Z]\\|[0-9IVXLCDMivxlcdm]+\\)") "\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\)" ) ;; Replace counter for "(?)" (cons "$" "+") ;; Allow more whitespace (cons "^\\\\(" "\\(\\(?:") (cons "\\[\t ]\\+$" "\\)[\t ]+" ) ;; Add superfluous shy group (cons (regexp-quote "[-\\*\\+]\\|") "") ;; Remove wrongly quoted ;; characters (cons (regexp-quote "\\)\\)[\t ]+") "\\|[-*+\u2022\u2023\u2043]\\)\\)[\t ]+" ) ;; Re-add bullets )) (should (re-equal rst-re-items "=== rst.el.~rst_el_1_68~:2724" (rst-re 'itmany-beg-1) )) (should (re-equal rst-re-items "=== rst.el.~rst_el_1_68~:1649" (rst-re 'itmany-beg-1) )) (should (re-equal rst-re-enumerations "=== rst.el.~rst_el_1_68~:1671" (rst-re 'enmexp-beg) )) (should (re-equal rst-re-items "=== rst.el.~rst_el_1_68~:1719" (rst-re 'itmany-beg-1) )) (should (re-equal (concat "\\(?:" "\\(\\(?:[0-9a-zA-Z#]\\{1,3\\}[.):-]\\|[*+-]\\)[ \t]+\\)[^ \t\n]" "\\|" (format "\\(%s%s+[ \t]+\\)[^ \t\n]" (regexp-quote (char-to-string char)) (regexp-quote (char-to-string char))) "\\)") "=== rst.el.~rst_el_1_68~:2430" (rst-re `(:grp (:alt itmany-tag (:seq ,(char-after) "\\{2,\\}")) hws-sta) "\\S ") (cons "^\\\\(\\?:" "") (cons "\\\\)$" "") ;; Remove superfluous ;; shy group (cons (regexp-quote "[0-9a-zA-Z#]\\{1,3\\}[.):-]\\|[*+-]") "\\(\\(?:\\(?:\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\)\\.\\|(?\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\))\\)\\|[-*+\u2022\u2023\u2043]\\)\\)" ) ;; Replace wrong item tag by correct one (cons (regexp-quote "\\+\\++") "\\+\\{2,\\}") ;; Use regex repeat instead of explicit repeat (cons "\\[^ \t\n]" "\\S ") ;; Use symbolic non-whitespace (cons "\\[^ \t\n]" "\\S ") ;; Use symbolic non-whitespace again (cons "\\\\S " "") ;; Factor out symbolic non-whitespace )) )) (ert-deftest rst-re-refactoring-font-lock () "Test the refactorings in font-lock done based on rst_el_1_68." ;; Any comment or string "=== rst.el.~rst_el_1_68~:..." gives the line number ;; of the refactored code in the original file for the previous expression. (let* ((rst-use-char-classes t) (rst-use-unicode t) ;; horizontal white space (re-hws "[\t ]") ;; beginning of line with possible indentation (re-bol (concat "^" re-hws "*")) ;; Separates block lead-ins from their content (re-blksep1 (concat "\\(" re-hws "+\\|$\\)")) ;; explicit markup tag (re-emt "\\.\\.") ;; explicit markup start (re-ems (concat re-emt re-hws "+")) ;; inline markup prefix (re-imp1 (concat "\\(^\\|" re-hws "\\|[-'\"([{<" (if rst-use-unicode "\u2018\u201c\u00ab\u2019" "") "/:]\\)")) ;; inline markup suffix (re-ims1 (concat "\\(" re-hws "\\|[]-'\")}>" (if rst-use-unicode "\u2019\u201d\u00bb" "") "/:.,;!?\\]\\|$\\)")) ;; symbol character (re-sym1 "\\(\\sw\\|\\s_\\)") ;; inline markup content begin (re-imbeg2 "\\(\\S \\|\\S \\([^") ;; There seems to be a bug leading to error "Stack overflow in regexp ;; matcher" when "|" or "\\*" are the characters searched for (re-imendbegbeg (if (< emacs-major-version 21) "]" "\\]\\|\\\\.")) ;; inline markup content end (re-imendbeg (concat re-imendbegbeg "\\)\\{0," (format "%d" rst-max-inline-length) "\\}[^\t ")) (re-imendend "\\\\]\\)") ;; inline markup content without asterisk (re-ima2 (concat re-imbeg2 "*" re-imendbeg "*" re-imendend)) ;; inline markup content without backquote (re-imb2 (concat re-imbeg2 "`" re-imendbeg "`" re-imendend)) ;; inline markup content without vertical bar (re-imv2 (concat re-imbeg2 "|" re-imendbeg "|" re-imendend)) ;; Supported URI schemes (re-uris1 "\\(acap\\|cid\\|data\\|dav\\|fax\\|file\\|ftp\\|gopher\\|http\\|https\\|imap\\|ldap\\|mailto\\|mid\\|modem\\|news\\|nfs\\|nntp\\|pop\\|prospero\\|rtsp\\|service\\|sip\\|tel\\|telnet\\|tip\\|urn\\|vemmi\\|wais\\)") ;; Line starting with adornment and optional whitespace; complete ;; adornment is in (match-string 1); there must be at least 3 ;; characters because otherwise explicit markup start would be ;; recognized (re-ado2 (concat "^\\(\\([" (if rst-use-char-classes "^[:word:][:space:][:cntrl:]" "^\\w \t\x00-\x1F") "]\\)\\2\\2+\\)" re-hws "*$")) ) (should (re-equal-matches ;; `Bullet Lists`_ (concat re-bol "\\([-*+]" re-blksep1 "\\)") "=== rst.el.~rst_el_1_68~:3011" (rst-re 'lin-beg '(:grp bul-sta)) (list "*" (cons 1 1)) (cons (regexp-quote "[-*+]") "[-*+\u2022\u2023\u2043]") ;; More bullets (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy )) (should (re-equal-matches ;; `Enumerated Lists`_ (concat re-bol "\\((?\\(#\\|[0-9]+\\|[A-Za-z]\\|[IVXLCMivxlcm]+\\)[.)]" re-blksep1 "\\)") "=== rst.el.~rst_el_1_68~:3015" (rst-re 'lin-beg '(:grp enmany-sta)) (list " (#) Item" (cons 1 1)) (cons (regexp-quote "(?\\(#\\|[0-9]+\\|[A-Za-z]\\|[IVXLCMivxlcm]+\\)[.)]") "\\(?:\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\)\\.\\|(?\\(?:[a-zA-Z]\\|[0-9]+\\|[IVXLCDMivxlcdm]+\\|#\\))\\)" ) ;; Enumeration tags are more sophisticated (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy )) (should (re-equal-matches ;; `Field Lists`_ (concat re-bol "\\(:[^:\n]+:\\)" re-blksep1) "=== rst.el.~rst_el_1_68~:3021" (rst-re 'lin-beg '(:grp fld-tag) 'bli-sfx) (list " :some field: " (cons 1 1)) (cons "\\[^:\n]" "\\(?:[^:\n]\\|\\\\:\\)") ;; Field name more ;; sophisticated (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy )) (should (re-equal-matches ;; `Option Lists`_ (concat re-bol "\\(\\(\\(\\([-+/]\\|--\\)\\sw\\(-\\|\\sw\\)*" "\\([ =]\\S +\\)?\\)\\(,[\t ]\\)?\\)+\\)\\($\\|[\t ]\\{2\\}\\)") "=== rst.el.~rst_el_1_68~:3025" (rst-re 'lin-beg '(:grp opt-tag (:shy optsep-tag opt-tag) "*") '(:alt "$" (:seq hws-prt "\\{2\\}"))) (list " --len=length, -l length Explanation" (cons 1 1)) (cons (regexp-quote "\\(\\(\\(\\([-+/]\\|--\\)\\sw\\(-\\|\\sw\\)*\\([ =]\\S +\\)?\\)\\(,[ ]\\)?\\)+\\)") "\\(\\(?:\\(?:[-+/]\\|--\\)\\sw\\(?:-\\|\\sw\\)*\\(?:[ =]\\S +\\)?\\)\\(?:\\(?:,[ ]\\)\\(?:\\(?:[-+/]\\|--\\)\\sw\\(?:-\\|\\sw\\)*\\(?:[ =]\\S +\\)?\\)\\)*\\)" ) ;; Option recognition more sophisticated (cons "\\\\(\\$" "\\(?:$") ;; Make a group shy )) (should (re-equal-matches ;; `Line Blocks`_ (concat re-bol "\\(|" re-blksep1 "\\)[^|\n]*$") "=== rst.el.~rst_el_1_68~:3030" (rst-re 'lin-beg '(:grp "|" bli-sfx) "[^|\n]*$") (list " | Some text" (cons 1 1)) (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy )) (should (re-equal-matches ;; `Footnotes`_ / `Citations`_ (concat re-bol "\\(" re-ems "\\[[^[\n]+\\]\\)" re-blksep1) "=== rst.el.~rst_el_1_68~:3038" (rst-re 'lin-beg '(:grp exm-sta fnc-tag) 'bli-sfx) (list ".. [#]" (cons 1 1)) (cons "\\[^\\[" "[^]") ;; Error correction in old code (cons "\\\\]" "]") ;; Remove superfluous quote (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy )) (should (re-equal-matches ;; `Directives`_ / `Substitution Definitions`_ (concat re-bol "\\(" re-ems "\\)\\(\\(|[^|\n]+|[\t ]+\\)?\\)\\(" re-sym1 "+::\\)" re-blksep1) "=== rst.el.~rst_el_1_68~:3042" (rst-re 'lin-beg '(:grp exm-sta) '(:grp (:shy subdef-tag hws-sta) "?") '(:grp sym-tag dcl-tag) 'bli-sfx) (list ".. |attr| replace:: val" (cons 1 1) (cons 2 2) (cons 4 3)) (cons "\\\\(|" "\\(?:|") ;; Make a group shy (cons "\\[^|\n]\\+" "\\(?:\\S \\|\\S \\(?:[^|\\\n]\\|\\\\.\\)\\{0,1000\\}[^ |\\]\\)" ) ;; Symbol name more sophisticated (cons (regexp-quote "\\(\\sw\\|\\s_\\)+") "\\(?:\\sw+\\(?:[-+.:_]\\sw+\\)*\\)") ;; New syntax for ;; symbols (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy )) (should (re-equal-matches ;; `Hyperlink Targets`_ (concat re-bol "\\(" re-ems "_\\([^:\\`\n]\\|\\\\.\\|`[^`\n]+`\\)+:\\)" re-blksep1) "=== rst.el.~rst_el_1_68~:3049" (rst-re 'lin-beg '(:grp exm-sta "_" (:alt (:seq "`" ilcbkqdef-tag "`") (:seq (:alt "[^:\\\n]" "\\\\.") "+")) ":") 'bli-sfx) (list ".. _`some\\: target`:" (cons 1 1)) (cons (regexp-quote "\\([^:\\`\n]\\|\\\\.\\|`[^`\n]+`\\)+") "\\(?:`\\(?:\\S \\|\\S \\(?:[^`\\\n]\\|\\\\.\\)\\{0,1000\\}[^ `\\]\\)`\\|\\(?:[^:\\\n]\\|\\\\.\\)+\\)" ) ;; Hyperlink name recognition more sophisticated (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy )) (should (re-equal-matches ;; `Hyperlink Targets`_ (concat re-bol "\\(__\\)" re-blksep1) "=== rst.el.~rst_el_1_68~:3053" (rst-re 'lin-beg '(:grp "__") 'bli-sfx) (list " __" (cons 1 1)) (cons "\\\\(\\[\t " "\\(?:[\t ") ;; Make a group shy )) (should (re-equal-matches ;; `Strong Emphasis`_ (concat re-imp1 "\\(\\*\\*" re-ima2 "\\*\\*\\)" re-ims1) "=== rst.el.~rst_el_1_68~:3062" (rst-re 'ilm-pfx '(:grp "\\*\\*" ilcast-tag "\\*\\*") 'ilm-sfx) (list "abc **def** ghi" (cons 2 1)) (cons "^\\\\(" "\\(?:") ;; Make a group shy (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote (cons (regexp-quote "\\|$") "") (cons (regexp-quote "\\([\t ]") "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy )) (should (re-equal-matches ;; `Emphasis`_ (concat re-imp1 "\\(\\*" re-ima2 "\\*\\)" re-ims1) "=== rst.el.~rst_el_1_68~:3066" (rst-re 'ilm-pfx '(:grp "\\*" ilcast-tag "\\*") 'ilm-sfx) (list "*x*" (cons 2 1)) (cons "^\\\\(" "\\(?:") ;; Make a group shy (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote (cons (regexp-quote "\\|$") "") (cons (regexp-quote "\\([\t ]") "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy )) (should (re-equal-matches ;; `Inline Literals`_ (concat re-imp1 "\\(``" re-imb2 "``\\)" re-ims1) "=== rst.el.~rst_el_1_68~:3070" (rst-re 'ilm-pfx '(:grp "``" ilcbkq-tag "``") 'ilm-sfx) (list "``co de``" (cons 2 1)) (cons "^\\\\(" "\\(?:") ;; Make a group shy (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote (cons (regexp-quote "\\|$") "") (cons (regexp-quote "\\([\t ]") "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy )) (should (re-equal-matches ;; `Inline Internal Targets`_ (concat re-imp1 "\\(_`" re-imb2 "`\\)" re-ims1) "=== rst.el.~rst_el_1_68~:3074" (rst-re 'ilm-pfx '(:grp "_`" ilcbkq-tag "`") 'ilm-sfx) (list "_`Inline\ntarget`" (cons 2 1)) (cons "^\\\\(" "\\(?:") ;; Make a group shy (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote (cons (regexp-quote "\\|$") "") (cons (regexp-quote "\\([\t ]") "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy )) (should (re-equal-matches ;; `Hyperlink References`_ (concat re-imp1 "\\(\\(`" re-imb2 "`\\|\\(\\sw\\(\\sw\\|-\\)+\\sw\\)\\)__?\\)" re-ims1) "=== rst.el.~rst_el_1_68~:3079" (rst-re 'ilm-pfx '(:grp (:alt (:seq "`" ilcbkq-tag "`") (:seq "\\sw" (:alt "\\sw" "-") "+\\sw")) "__?") 'ilm-sfx) (list "<`xxx`__>" (cons 2 1)) (cons "^\\\\(" "\\(?:") ;; Make a group shy (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote (cons (regexp-quote "\\|$") "") (cons (regexp-quote "\\([\t ]") "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy (cons "\\\\(`" "\\(?:`") ;; Make a group shy (cons "\\\\(\\\\sw" "\\sw") (cons "\\\\sw\\\\)" "\\sw") ;; Remove a group (cons "sw\\\\(\\\\sw" "sw\\(?:\\sw") ;; Make a group shy )) (should (re-equal-matches ;; `Interpreted Text`_ (concat re-imp1 "\\(\\(:" re-sym1 "+:\\)?\\)\\(`" re-imb2 "`\\)\\(\\(:" re-sym1 "+:\\)?\\)" re-ims1) "=== rst.el.~rst_el_1_68~:3083" (rst-re 'ilm-pfx '(:grp (:shy ":" sym-tag ":") "?") '(:grp "`" ilcbkq-tag "`") '(:grp (:shy ":" sym-tag ":") "?") 'ilm-sfx) (list "`Interpreted`" (cons 2 1) (cons 5 2) (cons 8 3)) (cons "^\\\\(" "\\(?:") ;; Make a group shy (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy (cons "\\\\(\\[^" "\\(?:[^") ;; Make a group shy (cons "\\\\(:" "\\(?::") ;; Make a group shy (cons "\\\\(:" "\\(?::") ;; Make a group shy (cons (regexp-quote "\\(\\sw\\|\\s_\\)+") "\\(?:\\sw+\\(?:[-+.:_]\\sw+\\)*\\)") ;; New syntax for ;; symbols (cons (regexp-quote "\\(\\sw\\|\\s_\\)+") "\\(?:\\sw+\\(?:[-+.:_]\\sw+\\)*\\)") ;; New syntax for ;; symbols (cons (regexp-quote "\\\\]") "\\]") ;; Remove superfluous quote (cons (regexp-quote "\\|$") "") (cons (regexp-quote "\\([\t ]") "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy )) (should (re-equal-matches ;; `Footnote References`_ / `Citation References`_ (concat re-imp1 "\\(\\[[^]]+\\]_\\)" re-ims1) "=== rst.el.~rst_el_1_68~:3090" (rst-re 'ilm-pfx '(:grp fnc-tag "_") 'ilm-sfx) (list "[1]_" (cons 2 1)) (cons "^\\\\(" "\\(?:") ;; Make a group shy (cons "]]" "]\n]") ;; A reference may not contain \n (cons "\\\\]" "]") ;; Remove superfluous quote (cons (regexp-quote "\\|$") "") (cons (regexp-quote "\\([\t ]") "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy )) (should (re-equal-matches ;; `Substitution References`_ (concat re-imp1 "\\(|" re-imv2 "|\\)" re-ims1) "=== rst.el.~rst_el_1_68~:3094" (rst-re 'ilm-pfx '(:grp sub-tag) 'ilm-sfx) (list "|attr|" (cons 2 1)) (cons "^\\\\(" "\\(?:") ;; Make a group shy (cons "\\\\(\\\\S" "\\(?:\\S") ;; Make a group shy (cons (regexp-quote "\\([^|") "\\(?:[^|") ;; Make a group shy (cons "\\\\]" "]") ;; Remove superfluous quote (cons "\\\\]" "]") ;; Remove superfluous quote (cons "\\[^|]" "[^|\\]") ;; Improve recognition (cons (regexp-quote "\\|$") "") (cons (regexp-quote "\\([\t ]") "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy )) (should (re-equal-matches ;; `Standalone Hyperlinks`_ (concat re-imp1 "\\(" re-uris1 ":\\S +\\)" re-ims1) "=== rst.el.~rst_el_1_68~:3099" (rst-re 'ilm-pfx '(:grp uri-tag ":\\S +") 'ilm-sfx) (list "http://example.com/" (cons 2 1)) (cons "^\\\\(" "\\(?:") ;; Make a group shy (cons "\\\\(acap" "\\(?:acap") ;; Make a group shy (cons (regexp-quote "\\|$") "") (cons (regexp-quote "\\([\t ]") "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy )) (should (re-equal-matches ;; `Standalone Hyperlinks`_ (concat re-imp1 "\\(" re-sym1 "+@" re-sym1 "+\\)" re-ims1) "=== rst.el.~rst_el_1_68~:3102" (rst-re 'ilm-pfx '(:grp sym-tag "@" sym-tag ) 'ilm-sfx) (list "someone@example" (cons 2 1)) (cons "^\\\\(" "\\(?:") ;; Make a group shy (cons (regexp-quote "\\(\\sw\\|\\s_\\)+") "\\(?:\\sw+\\(?:[-+.:_]\\sw+\\)*\\)") ;; New syntax for ;; symbols (cons (regexp-quote "\\(\\sw\\|\\s_\\)+") "\\(?:\\sw+\\(?:[-+.:_]\\sw+\\)*\\)") ;; New syntax for ;; symbols (cons (regexp-quote "\\|$") "") (cons (regexp-quote "\\([\t ]") "\\(?:$\\|[\t ]") ;; Move "$" in regex and make a group shy )) (should (re-equal ;; Sections_ / Transitions_ re-ado2 "=== rst.el.~rst_el_1_68~:3109" (rst-re 'ado-beg-2-1) (cons "\\^\\[:word:]\\[:space:]\\[:cntrl:]" "]!\"#$%&'()*+,./:;<=>?@[\\^_`{|}~-") ;; Use real adornment ;; characters (cons "2\\+" "{2,\\}") ;; Use repeat count )) (should (re-equal ;; `Comments`_ (concat re-bol "\\(" re-ems "\\)\[^[|_\n]\\([^:\n]\\|:\\([^:\n]\\|$\\)\\)*$") "=== rst.el.~rst_el_1_68~:3128" (rst-re 'lin-beg '(:grp exm-sta) "[^\[|_\n]" '(:alt "[^:\n]" (:seq ":" (:alt "[^:\n]" "$"))) "*$") (cons "\\\\(\\[^:" "\\(?:[^:") ;; Make a group shy (cons "\\\\(\\[^:" "\\(?:[^:") ;; Make a group shy )) (should (re-equal-matches ;; `Comments`_ (concat re-bol "\\(" re-emt "\\)\\(\\s *\\)$") "=== rst.el.~rst_el_1_68~:3135" (rst-re 'lin-beg '(:grp exm-tag) '(:grp hws-tag) "$") (list ".. " (cons 1 1) (cons 2 2)) (cons "\\\\s " "[\t ]") ;; Only horizontal space )) (should (re-equal-matches ;; `Literal Blocks`_ (concat re-bol "\\(\\([^.\n]\\|\\.[^.\n]\\).*\\)?\\(::\\)$") "=== rst.el.~rst_el_1_68~:3145" (rst-re 'lin-beg '(:shy (:alt "[^.\n]" "\\.[^.\n]") ".*") "?" '(:grp dcl-tag) "$") (list "Some text ::" (cons 3 1)) (cons "\\\\(\\\\(" "\\(?:\\(?:") ;; Make two groups shy )) (should (re-equal-matches ;; `Doctest Blocks`_ (concat re-bol "\\(>>>\\|\\.\\.\\.\\)\\(.+\\)") "=== rst.el.~rst_el_1_68~:3154" (rst-re 'lin-beg '(:grp (:alt ">>>" ell-tag)) '(:grp ".+")) (list ">>> content" (cons 1 1) (cons 2 2)) (cons ">>>" "\\(?:>>>") (cons "\\.\\\\)" ".\\)\\)") ;; Add a shy ;; group )) ))