comparison lisp/emacs-lisp/re-builder.el @ 88155:d7ddb3e565de

sync with trunk
author Henrik Enberg <henrik.enberg@telia.com>
date Mon, 16 Jan 2006 00:03:54 +0000
parents 0d8b17d428b5
children
comparison
equal deleted inserted replaced
88154:8ce476d3ba36 88155:d7ddb3e565de
1 ;;; re-builder.el --- building Regexps with visual feedback 1 ;;; re-builder.el --- building Regexps with visual feedback
2 2
3 ;; Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. 3 ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
4 ;; 2005 Free Software Foundation, Inc.
4 5
5 ;; Author: Detlev Zundel <dzu@gnu.org> 6 ;; Author: Detlev Zundel <dzu@gnu.org>
6 ;; Keywords: matching, lisp, tools 7 ;; Keywords: matching, lisp, tools
7 8
8 ;; This file is part of GNU Emacs. 9 ;; This file is part of GNU Emacs.
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details. 19 ;; GNU General Public License for more details.
19 20
20 ;; You should have received a copy of the GNU General Public License 21 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the 22 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 23 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02111-1307, USA. 24 ;; Boston, MA 02110-1301, USA.
24 25
25 ;;; Commentary: 26 ;;; Commentary:
26 27
27 ;; When I have to come up with regular expressions that are more 28 ;; When I have to come up with regular expressions that are more
28 ;; complex than simple string matchers, especially if they contain sub 29 ;; complex than simple string matchers, especially if they contain sub
43 ;; shown only in the modeline without throwing the errors at you. If 44 ;; shown only in the modeline without throwing the errors at you. If
44 ;; you want to know the reason why RE Builder considers it as invalid 45 ;; you want to know the reason why RE Builder considers it as invalid
45 ;; call `reb-force-update' ("\C-c\C-u") which should reveal the error. 46 ;; call `reb-force-update' ("\C-c\C-u") which should reveal the error.
46 47
47 ;; The target buffer can be changed with `reb-change-target-buffer' 48 ;; The target buffer can be changed with `reb-change-target-buffer'
48 ;; ("\C-c\C-b"). Changing the target buffer automatically removes 49 ;; ("\C-c\C-b"). Changing the target buffer automatically removes
49 ;; the overlays from the old buffer and displays the new one in the 50 ;; the overlays from the old buffer and displays the new one in the
50 ;; target window. 51 ;; target window.
51 52
52 ;; The `re-builder' keeps the focus while updating the matches in the 53 ;; The `re-builder' keeps the focus while updating the matches in the
53 ;; target buffer so corrections are easy to incorporate. If you are 54 ;; target buffer so corrections are easy to incorporate. If you are
59 ;; can be limited by `reb-auto-match-limit' so that they should not 60 ;; can be limited by `reb-auto-match-limit' so that they should not
60 ;; have a negative impact on the editing. Setting it to nil makes 61 ;; have a negative impact on the editing. Setting it to nil makes
61 ;; even the auto updates go all the way. Forcing an update overrides 62 ;; even the auto updates go all the way. Forcing an update overrides
62 ;; this limit allowing an easy way to see all matches. 63 ;; this limit allowing an easy way to see all matches.
63 64
64 ;; Currently `re-builder' understands four different forms of input, 65 ;; Currently `re-builder' understands five different forms of input,
65 ;; namely `read', `string', `sregex' and `lisp-re' syntax. Read 66 ;; namely `read', `string', `rx', `sregex' and `lisp-re' syntax. Read
66 ;; syntax and string syntax are both delimited by `"'s and behave 67 ;; syntax and string syntax are both delimited by `"'s and behave
67 ;; according to their name. With the `string' syntax there's no need 68 ;; according to their name. With the `string' syntax there's no need
68 ;; to escape the backslashes and double quotes simplifying the editing 69 ;; to escape the backslashes and double quotes simplifying the editing
69 ;; somewhat. The other two allow editing of symbolic regular 70 ;; somewhat. The other three allow editing of symbolic regular
70 ;; expressions supported by the packages of the same name. (`lisp-re' 71 ;; expressions supported by the packages of the same name. (`lisp-re'
71 ;; is a package by me and its support may go away as it is nearly the 72 ;; is a package by me and its support may go away as it is nearly the
72 ;; same as the `sregex' package in Emacs) 73 ;; same as the `sregex' package in Emacs)
73 74
74 ;; Editing symbolic expressions is done through a major mode derived 75 ;; Editing symbolic expressions is done through a major mode derived
133 :group 're-builder 134 :group 're-builder
134 :type '(choice (const :tag "Read syntax" read) 135 :type '(choice (const :tag "Read syntax" read)
135 (const :tag "String syntax" string) 136 (const :tag "String syntax" string)
136 (const :tag "`sregex' syntax" sregex) 137 (const :tag "`sregex' syntax" sregex)
137 (const :tag "`lisp-re' syntax" lisp-re) 138 (const :tag "`lisp-re' syntax" lisp-re)
139 (const :tag "`rx' syntax" rx)
138 (value: string))) 140 (value: string)))
139 141
140 (defcustom reb-auto-match-limit 200 142 (defcustom reb-auto-match-limit 200
141 "*Positive integer limiting the matches for RE Builder auto updates. 143 "*Positive integer limiting the matches for RE Builder auto updates.
142 Set it to nil if you don't want limits here." 144 Set it to nil if you don't want limits here."
174 :inverse-video t)) 176 :inverse-video t))
175 "Used for displaying the second matching subexpression." 177 "Used for displaying the second matching subexpression."
176 :group 're-builder) 178 :group 're-builder)
177 179
178 (defface reb-match-3 180 (defface reb-match-3
179 '((((class color) (background light)) 181 '((((min-colors 88) (class color) (background light))
182 :background "yellow1")
183 (((class color) (background light))
180 :background "yellow") 184 :background "yellow")
181 (((class color) (background dark)) 185 (((class color) (background dark))
182 :background "sienna4") 186 :background "sienna4")
183 (t 187 (t
184 :inverse-video t)) 188 :inverse-video t))
226 230
227 (defconst reb-buffer "*RE-Builder*" 231 (defconst reb-buffer "*RE-Builder*"
228 "Buffer to use for the RE Builder.") 232 "Buffer to use for the RE Builder.")
229 233
230 ;; Define the local "\C-c" keymap 234 ;; Define the local "\C-c" keymap
231 (defvar reb-mode-map nil 235 (defvar reb-mode-map
236 (let ((map (make-sparse-keymap)))
237 (define-key map "\C-c\C-c" 'reb-toggle-case)
238 (define-key map "\C-c\C-q" 'reb-quit)
239 (define-key map "\C-c\C-w" 'reb-copy)
240 (define-key map "\C-c\C-s" 'reb-next-match)
241 (define-key map "\C-c\C-r" 'reb-prev-match)
242 (define-key map "\C-c\C-i" 'reb-change-syntax)
243 (define-key map "\C-c\C-e" 'reb-enter-subexp-mode)
244 (define-key map "\C-c\C-b" 'reb-change-target-buffer)
245 (define-key map "\C-c\C-u" 'reb-force-update)
246 map)
232 "Keymap used by the RE Builder.") 247 "Keymap used by the RE Builder.")
233
234 (if (not reb-mode-map)
235 (progn
236 (setq reb-mode-map (make-sparse-keymap))
237 (define-key reb-mode-map "\C-c\C-c" 'reb-toggle-case)
238 (define-key reb-mode-map "\C-c\C-q" 'reb-quit)
239 (define-key reb-mode-map "\C-c\C-w" 'reb-copy)
240 (define-key reb-mode-map "\C-c\C-s" 'reb-next-match)
241 (define-key reb-mode-map "\C-c\C-r" 'reb-prev-match)
242 (define-key reb-mode-map "\C-c\C-i" 'reb-change-syntax)
243 (define-key reb-mode-map "\C-c\C-e" 'reb-enter-subexp-mode)
244 (define-key reb-mode-map "\C-c\C-b" 'reb-change-target-buffer)
245 (define-key reb-mode-map "\C-c\C-u" 'reb-force-update)))
246 248
247 (defun reb-mode () 249 (defun reb-mode ()
248 "Major mode for interactively building Regular Expressions. 250 "Major mode for interactively building Regular Expressions.
249 \\{reb-mode-map}" 251 \\{reb-mode-map}"
250 (interactive) 252 (interactive)
251 (kill-all-local-variables) 253 (kill-all-local-variables)
252 (setq major-mode 'reb-mode 254 (setq major-mode 'reb-mode
253 mode-name "RE Builder") 255 mode-name "RE Builder")
254 (use-local-map reb-mode-map) 256 (use-local-map reb-mode-map)
255 (reb-mode-common) 257 (reb-mode-common)
256 (run-hooks 'reb-mode-hook)) 258 (run-mode-hooks 'reb-mode-hook))
257 259
258 (define-derived-mode reb-lisp-mode 260 (define-derived-mode reb-lisp-mode
259 emacs-lisp-mode "RE Builder Lisp" 261 emacs-lisp-mode "RE Builder Lisp"
260 "Major mode for interactively building symbolic Regular Expressions." 262 "Major mode for interactively building symbolic Regular Expressions."
261 (cond ((eq reb-re-syntax 'lisp-re) ; Pull in packages 263 (cond ((eq reb-re-syntax 'lisp-re) ; Pull in packages
262 (require 'lisp-re)) ; as needed 264 (require 'lisp-re)) ; as needed
263 ((eq reb-re-syntax 'sregex) ; sregex is not autoloaded 265 ((eq reb-re-syntax 'sregex) ; sregex is not autoloaded
264 (require 'sregex))) ; right now.. 266 (require 'sregex)) ; right now..
267 ((eq reb-re-syntax 'rx) ; rx-to-string is autoloaded
268 (require 'rx))) ; require rx anyway
265 (reb-mode-common)) 269 (reb-mode-common))
266 270
267 ;; Use the same "\C-c" keymap as `reb-mode' and use font-locking from 271 ;; Use the same "\C-c" keymap as `reb-mode' and use font-locking from
268 ;; `emacs-lisp-mode' 272 ;; `emacs-lisp-mode'
269 (define-key reb-lisp-mode-map "\C-c" 273 (define-key reb-lisp-mode-map "\C-c"
294 ;; At least make the overlays go away if the buffer is killed 298 ;; At least make the overlays go away if the buffer is killed
295 (make-local-variable 'reb-kill-buffer) 299 (make-local-variable 'reb-kill-buffer)
296 (add-hook 'kill-buffer-hook 'reb-kill-buffer) 300 (add-hook 'kill-buffer-hook 'reb-kill-buffer)
297 (reb-auto-update nil nil nil)) 301 (reb-auto-update nil nil nil))
298 302
299
300 ;; Handy macro for doing things in other windows
301 (defmacro reb-with-current-window (window &rest body)
302 "With WINDOW selected evaluate BODY forms and reselect previous window."
303
304 (let ((oldwindow (make-symbol "*oldwindow*")))
305 `(let ((,oldwindow (selected-window)))
306 (select-window ,window)
307 (unwind-protect
308 (progn
309 ,@body)
310 (select-window ,oldwindow)))))
311 (put 'reb-with-current-window 'lisp-indent-function 0)
312
313 (defun reb-color-display-p () 303 (defun reb-color-display-p ()
314 "Return t if display is capable of displaying colors." 304 "Return t if display is capable of displaying colors."
315 (eq 'color 305 (eq 'color
316 ;; emacs/xemacs compatibility 306 ;; emacs/xemacs compatibility
317 (if (fboundp 'frame-parameter) 307 (if (fboundp 'frame-parameter)
318 (frame-parameter (selected-frame) 'display-type) 308 (frame-parameter (selected-frame) 'display-type)
319 (frame-property (selected-frame) 'display-type)))) 309 (if (fboundp 'frame-property)
310 (frame-property (selected-frame) 'display-type)))))
320 311
321 (defsubst reb-lisp-syntax-p () 312 (defsubst reb-lisp-syntax-p ()
322 "Return non-nil if RE Builder uses a Lisp syntax." 313 "Return non-nil if RE Builder uses a Lisp syntax."
323 (memq reb-re-syntax '(lisp-re sregex))) 314 (memq reb-re-syntax '(lisp-re sregex rx)))
324 315
325 (defmacro reb-target-binding (symbol) 316 (defmacro reb-target-binding (symbol)
326 "Return binding for SYMBOL in the RE Builder target buffer." 317 "Return binding for SYMBOL in the RE Builder target buffer."
327 `(with-current-buffer reb-target-buffer ,symbol)) 318 `(with-current-buffer reb-target-buffer ,symbol))
328 319
320 (defun reb-initialize-buffer ()
321 "Initialize the current buffer as a RE Builder buffer."
322 (erase-buffer)
323 (reb-insert-regexp)
324 (goto-char (+ 2 (point-min)))
325 (cond ((reb-lisp-syntax-p)
326 (reb-lisp-mode))
327 (t (reb-mode))))
328
329 ;;; This is to help people find this in Apropos.
330 ;;;###autoload
331 (defalias 'regexp-builder 're-builder)
329 332
330 ;;;###autoload 333 ;;;###autoload
331 (defun re-builder () 334 (defun re-builder ()
332 "Call up the RE Builder for the current window." 335 "Construct a regexp interactively."
333 (interactive) 336 (interactive)
334 337
335 (if (and (string= (buffer-name) reb-buffer) 338 (if (and (string= (buffer-name) reb-buffer)
336 (memq major-mode '(reb-mode reb-lisp-mode))) 339 (memq major-mode '(reb-mode reb-lisp-mode)))
337 (message "Already in the RE Builder") 340 (message "Already in the RE Builder")
340 (setq reb-target-buffer (current-buffer) 343 (setq reb-target-buffer (current-buffer)
341 reb-target-window (selected-window) 344 reb-target-window (selected-window)
342 reb-window-config (current-window-configuration)) 345 reb-window-config (current-window-configuration))
343 (select-window (split-window (selected-window) (- (window-height) 4))) 346 (select-window (split-window (selected-window) (- (window-height) 4)))
344 (switch-to-buffer (get-buffer-create reb-buffer)) 347 (switch-to-buffer (get-buffer-create reb-buffer))
345 (erase-buffer) 348 (reb-initialize-buffer)))
346 (reb-insert-regexp)
347 (goto-char (+ 2 (point-min)))
348 (cond
349 ((reb-lisp-syntax-p)
350 (reb-lisp-mode))
351 (t (reb-mode)))))
352 349
353 (defun reb-change-target-buffer (buf) 350 (defun reb-change-target-buffer (buf)
354 "Change the target buffer and display it in the target window." 351 "Change the target buffer and display it in the target window."
355 (interactive "bSet target buffer to: ") 352 (interactive "bSet target buffer to: ")
356 353
362 (reb-do-update 359 (reb-do-update
363 (if reb-subexp-mode reb-subexp-displayed nil)) 360 (if reb-subexp-mode reb-subexp-displayed nil))
364 (reb-update-modestring)))) 361 (reb-update-modestring))))
365 362
366 (defun reb-force-update () 363 (defun reb-force-update ()
367 "Forces an update in the RE Builder target window without a match limit." 364 "Force an update in the RE Builder target window without a match limit."
368 (interactive) 365 (interactive)
369 366
370 (let ((reb-auto-match-limit nil)) 367 (let ((reb-auto-match-limit nil))
371 (reb-update-overlays 368 (reb-update-overlays
372 (if reb-subexp-mode reb-subexp-displayed nil)))) 369 (if reb-subexp-mode reb-subexp-displayed nil))))
384 (defun reb-next-match () 381 (defun reb-next-match ()
385 "Go to next match in the RE Builder target window." 382 "Go to next match in the RE Builder target window."
386 (interactive) 383 (interactive)
387 384
388 (reb-assert-buffer-in-window) 385 (reb-assert-buffer-in-window)
389 (reb-with-current-window 386 (with-selected-window reb-target-window
390 reb-target-window
391 (if (not (re-search-forward reb-regexp (point-max) t)) 387 (if (not (re-search-forward reb-regexp (point-max) t))
392 (message "No more matches.") 388 (message "No more matches.")
393 (reb-show-subexp 389 (reb-show-subexp
394 (or (and reb-subexp-mode reb-subexp-displayed) 0) 390 (or (and reb-subexp-mode reb-subexp-displayed) 0)
395 t)))) 391 t))))
397 (defun reb-prev-match () 393 (defun reb-prev-match ()
398 "Go to previous match in the RE Builder target window." 394 "Go to previous match in the RE Builder target window."
399 (interactive) 395 (interactive)
400 396
401 (reb-assert-buffer-in-window) 397 (reb-assert-buffer-in-window)
402 (reb-with-current-window reb-target-window 398 (with-selected-window reb-target-window
403 (goto-char (1- (point))) 399 (let ((p (point)))
404 (if (not (re-search-backward reb-regexp (point-min) t)) 400 (goto-char (1- p))
405 (message "No more matches.") 401 (if (re-search-backward reb-regexp (point-min) t)
406 (reb-show-subexp 402 (reb-show-subexp
407 (or (and reb-subexp-mode reb-subexp-displayed) 0) 403 (or (and reb-subexp-mode reb-subexp-displayed) 0)
408 t)))) 404 t)
405 (goto-char p)
406 (message "No more matches.")))))
409 407
410 (defun reb-toggle-case () 408 (defun reb-toggle-case ()
411 "Toggle case sensitivity of searches for RE Builder target buffer." 409 "Toggle case sensitivity of searches for RE Builder target buffer."
412 (interactive) 410 (interactive)
413 411
440 "Visually show limit of subexpression SUBEXP of recent search. 438 "Visually show limit of subexpression SUBEXP of recent search.
441 On color displays this just puts point to the end of the expression as 439 On color displays this just puts point to the end of the expression as
442 the match should already be marked by an overlay. 440 the match should already be marked by an overlay.
443 On other displays jump to the beginning and the end of it. 441 On other displays jump to the beginning and the end of it.
444 If the optional PAUSE is non-nil then pause at the end in any case." 442 If the optional PAUSE is non-nil then pause at the end in any case."
445 (reb-with-current-window reb-target-window 443 (with-selected-window reb-target-window
446 (if (not (reb-color-display-p)) 444 (if (not (reb-color-display-p))
447 (progn (goto-char (match-beginning subexp)) 445 (progn (goto-char (match-beginning subexp))
448 (sit-for reb-blink-delay))) 446 (sit-for reb-blink-delay)))
449 (goto-char (match-end subexp)) 447 (goto-char (match-end subexp))
450 (if (or (not (reb-color-display-p)) pause) 448 (if (or (not (reb-color-display-p)) pause)
464 Optional argument SYNTAX must be specified if called non-interactively." 462 Optional argument SYNTAX must be specified if called non-interactively."
465 (interactive 463 (interactive
466 (list (intern 464 (list (intern
467 (completing-read "Select syntax: " 465 (completing-read "Select syntax: "
468 (mapcar (lambda (el) (cons (symbol-name el) 1)) 466 (mapcar (lambda (el) (cons (symbol-name el) 1))
469 '(read string lisp-re sregex)) 467 '(read string lisp-re sregex rx))
470 nil t (symbol-name reb-re-syntax))))) 468 nil t (symbol-name reb-re-syntax)))))
471 469
472 (if (memq syntax '(read string lisp-re sregex)) 470 (if (memq syntax '(read string lisp-re sregex rx))
473 (let ((buffer (get-buffer reb-buffer))) 471 (let ((buffer (get-buffer reb-buffer)))
474 (setq reb-re-syntax syntax) 472 (setq reb-re-syntax syntax)
475 (if buffer 473 (when buffer
476 (with-current-buffer buffer 474 (with-current-buffer buffer
477 (erase-buffer) 475 (reb-initialize-buffer))))
478 (reb-insert-regexp)
479 (goto-char (+ 2 (point-min)))
480 (cond ((reb-lisp-syntax-p)
481 (reb-lisp-mode))
482 (t (reb-mode))))))
483 (error "Invalid syntax: %s" syntax))) 476 (error "Invalid syntax: %s" syntax)))
484 477
485 478
486 ;; Non-interactive functions below 479 ;; Non-interactive functions below
487 (defun reb-do-update (&optional subexp) 480 (defun reb-do-update (&optional subexp)
492 (reb-update-regexp) 485 (reb-update-regexp)
493 (reb-update-overlays subexp)) 486 (reb-update-overlays subexp))
494 487
495 (defun reb-auto-update (beg end lenold &optional force) 488 (defun reb-auto-update (beg end lenold &optional force)
496 "Called from `after-update-functions' to update the display. 489 "Called from `after-update-functions' to update the display.
497 BEG END and LENOLD are passed in from the hook. 490 BEG, END and LENOLD are passed in from the hook.
498 An actual update is only done if the regexp has changed or if the 491 An actual update is only done if the regexp has changed or if the
499 optional fourth argument FORCE is non-nil." 492 optional fourth argument FORCE is non-nil."
500 (let ((prev-valid reb-valid-string) 493 (let ((prev-valid reb-valid-string)
501 (new-valid 494 (new-valid
502 (condition-case nil 495 (condition-case nil
546 (defun reb-display-subexp (&optional subexp) 539 (defun reb-display-subexp (&optional subexp)
547 "Highlight only subexpression SUBEXP in the RE Builder." 540 "Highlight only subexpression SUBEXP in the RE Builder."
548 (interactive) 541 (interactive)
549 542
550 (setq reb-subexp-displayed 543 (setq reb-subexp-displayed
551 (or subexp (string-to-int (format "%c" last-command-char)))) 544 (or subexp (string-to-number (format "%c" last-command-char))))
552 (reb-update-modestring) 545 (reb-update-modestring)
553 (reb-do-update reb-subexp-displayed)) 546 (reb-do-update reb-subexp-displayed))
554 547
555 (defun reb-kill-buffer () 548 (defun reb-kill-buffer ()
556 "When the RE Builder buffer is killed make sure no overlays stay around." 549 "When the RE Builder buffer is killed make sure no overlays stay around."
599 (reb-empty-regexp))))))) 592 (reb-empty-regexp)))))))
600 593
601 (defun reb-cook-regexp (re) 594 (defun reb-cook-regexp (re)
602 "Return RE after processing it according to `reb-re-syntax'." 595 "Return RE after processing it according to `reb-re-syntax'."
603 (cond ((eq reb-re-syntax 'lisp-re) 596 (cond ((eq reb-re-syntax 'lisp-re)
604 (lre-compile-string (eval (car (read-from-string re))))) 597 (if (fboundp 'lre-compile-string)
598 (lre-compile-string (eval (car (read-from-string re))))))
605 ((eq reb-re-syntax 'sregex) 599 ((eq reb-re-syntax 'sregex)
606 (apply 'sregex (eval (car (read-from-string re))))) 600 (apply 'sregex (eval (car (read-from-string re)))))
601 ((eq reb-re-syntax 'rx)
602 (rx-to-string (eval (car (read-from-string re)))))
607 (t re))) 603 (t re)))
608 604
609 (defun reb-update-regexp () 605 (defun reb-update-regexp ()
610 "Update the regexp for the target buffer. 606 "Update the regexp for the target buffer.
611 Return t if the (cooked) expression changed." 607 Return t if the (cooked) expression changed."
668 (error "Too many subexpressions - face `%s' not defined" 664 (error "Too many subexpressions - face `%s' not defined"
669 face-name ))) 665 face-name )))
670 (overlay-put overlay 'priority i))) 666 (overlay-put overlay 'priority i)))
671 (setq i (1+ i)))))) 667 (setq i (1+ i))))))
672 (let ((count (if subexp submatches matches))) 668 (let ((count (if subexp submatches matches)))
673 (message"%s %smatch(es)%s" 669 (message "%s %smatch%s%s"
674 (if (= 0 count) "No" (int-to-string count)) 670 (if (= 0 count) "No" (int-to-string count))
675 (if subexp "subexpression " "") 671 (if subexp "subexpression " "")
672 (if (= 1 count) "" "es")
676 (if (and reb-auto-match-limit 673 (if (and reb-auto-match-limit
677 (= reb-auto-match-limit count)) 674 (= reb-auto-match-limit count))
678 " (limit reached)" ""))) 675 " (limit reached)" "")))
679 (if firstmatch 676 (if firstmatch
680 (progn (store-match-data firstmatch) 677 (progn (store-match-data firstmatch)
681 (reb-show-subexp (or subexp 0)))))) 678 (reb-show-subexp (or subexp 0))))))
682 679
683 (provide 're-builder) 680 (provide 're-builder)
684 681
682 ;;; arch-tag: 5c5515ac-4085-4524-a421-033f44f032e7
685 ;;; re-builder.el ends here 683 ;;; re-builder.el ends here