comparison lisp/emacs-lisp/re-builder.el @ 93198:eb3d659f5085

(reb-mode-common): Remove reference to bogus variable `reb-kill-buffer'; don't make hooks buffer-local, use the LOCAL arg of `add-hook'. (reb-blink-delay, reb-mode-hook, reb-re-syntax, reb-auto-match-limit): Remove spurious * from defcustom docstrings. (reb-next-match, reb-prev-match, reb-enter-subexp-mode): Fix typos in messages. (reb-mode-buffer-p): New function. (re-builder, reb-kill-buffer): Use `reb-mode-buffer-p'. Use `when'. (top, reb-show-subexp, reb-auto-update, reb-auto-update, reb-delete-overlays, reb-cook-regexp, reb-update-regexp, reb-update-overlays): Use `unless', `when'. (re-builder-unload-function): New function.
author Juanma Barranquero <lekktu@gmail.com>
date Tue, 25 Mar 2008 16:48:19 +0000
parents 107ccd98fa12
children 44fab469d68d
comparison
equal deleted inserted replaced
93197:212fa666680e 93198:eb3d659f5085
107 107
108 108
109 ;;; Code: 109 ;;; Code:
110 110
111 ;; On XEmacs, load the overlay compatibility library 111 ;; On XEmacs, load the overlay compatibility library
112 (if (not (fboundp 'make-overlay)) 112 (unless (fboundp 'make-overlay)
113 (require 'overlay)) 113 (require 'overlay))
114 114
115 ;; User customizable variables 115 ;; User customizable variables
116 (defgroup re-builder nil 116 (defgroup re-builder nil
117 "Options for the RE Builder." 117 "Options for the RE Builder."
118 :group 'lisp 118 :group 'lisp
119 :prefix "reb-") 119 :prefix "reb-")
120 120
121 (defcustom reb-blink-delay 0.5 121 (defcustom reb-blink-delay 0.5
122 "*Seconds to blink cursor for next/previous match in RE Builder." 122 "Seconds to blink cursor for next/previous match in RE Builder."
123 :group 're-builder 123 :group 're-builder
124 :type 'number) 124 :type 'number)
125 125
126 (defcustom reb-mode-hook nil 126 (defcustom reb-mode-hook nil
127 "*Hooks to run on entering RE Builder mode." 127 "Hooks to run on entering RE Builder mode."
128 :group 're-builder 128 :group 're-builder
129 :type 'hook) 129 :type 'hook)
130 130
131 (defcustom reb-re-syntax 'read 131 (defcustom reb-re-syntax 'read
132 "*Syntax for the REs in the RE Builder. 132 "Syntax for the REs in the RE Builder.
133 Can either be `read', `string', `sregex', `lisp-re', `rx'." 133 Can either be `read', `string', `sregex', `lisp-re', `rx'."
134 :group 're-builder 134 :group 're-builder
135 :type '(choice (const :tag "Read syntax" read) 135 :type '(choice (const :tag "Read syntax" read)
136 (const :tag "String syntax" string) 136 (const :tag "String syntax" string)
137 (const :tag "`sregex' syntax" sregex) 137 (const :tag "`sregex' syntax" sregex)
138 (const :tag "`lisp-re' syntax" lisp-re) 138 (const :tag "`lisp-re' syntax" lisp-re)
139 (const :tag "`rx' syntax" rx))) 139 (const :tag "`rx' syntax" rx)))
140 140
141 (defcustom reb-auto-match-limit 200 141 (defcustom reb-auto-match-limit 200
142 "*Positive integer limiting the matches for RE Builder auto updates. 142 "Positive integer limiting the matches for RE Builder auto updates.
143 Set it to nil if you don't want limits here." 143 Set it to nil if you don't want limits here."
144 :group 're-builder 144 :group 're-builder
145 :type '(restricted-sexp :match-alternatives 145 :type '(restricted-sexp :match-alternatives
146 (integerp 'nil))) 146 (integerp 'nil)))
147 147
290 (setq reb-mode-string "" 290 (setq reb-mode-string ""
291 reb-valid-string "" 291 reb-valid-string ""
292 mode-line-buffer-identification 292 mode-line-buffer-identification
293 '(25 . ("%b" reb-mode-string reb-valid-string))) 293 '(25 . ("%b" reb-mode-string reb-valid-string)))
294 (reb-update-modestring) 294 (reb-update-modestring)
295 (make-local-variable 'after-change-functions) 295 (add-hook 'after-change-functions 'reb-auto-update nil t)
296 (add-hook 'after-change-functions
297 'reb-auto-update)
298 ;; At least make the overlays go away if the buffer is killed 296 ;; At least make the overlays go away if the buffer is killed
299 (make-local-variable 'reb-kill-buffer) 297 (add-hook 'kill-buffer-hook 'reb-kill-buffer nil t)
300 (add-hook 'kill-buffer-hook 'reb-kill-buffer)
301 (reb-auto-update nil nil nil)) 298 (reb-auto-update nil nil nil))
302 299
303 (defun reb-color-display-p () 300 (defun reb-color-display-p ()
304 "Return t if display is capable of displaying colors." 301 "Return t if display is capable of displaying colors."
305 (eq 'color 302 (eq 'color
324 (goto-char (+ 2 (point-min))) 321 (goto-char (+ 2 (point-min)))
325 (cond ((reb-lisp-syntax-p) 322 (cond ((reb-lisp-syntax-p)
326 (reb-lisp-mode)) 323 (reb-lisp-mode))
327 (t (reb-mode)))) 324 (t (reb-mode))))
328 325
326 (defun reb-mode-buffer-p ()
327 "Return non-nil if the current buffer is a RE Builder buffer."
328 (memq major-mode '(reb-mode reb-lisp-mode)))
329
329 ;;; This is to help people find this in Apropos. 330 ;;; This is to help people find this in Apropos.
330 ;;;###autoload 331 ;;;###autoload
331 (defalias 'regexp-builder 're-builder) 332 (defalias 'regexp-builder 're-builder)
332 333
333 ;;;###autoload 334 ;;;###autoload
334 (defun re-builder () 335 (defun re-builder ()
335 "Construct a regexp interactively." 336 "Construct a regexp interactively."
336 (interactive) 337 (interactive)
337 338
338 (if (and (string= (buffer-name) reb-buffer) 339 (if (and (string= (buffer-name) reb-buffer)
339 (memq major-mode '(reb-mode reb-lisp-mode))) 340 (reb-mode-buffer-p))
340 (message "Already in the RE Builder") 341 (message "Already in the RE Builder")
341 (if reb-target-buffer 342 (when reb-target-buffer
342 (reb-delete-overlays)) 343 (reb-delete-overlays))
343 (setq reb-target-buffer (current-buffer) 344 (setq reb-target-buffer (current-buffer)
344 reb-target-window (selected-window) 345 reb-target-window (selected-window)
345 reb-window-config (current-window-configuration)) 346 reb-window-config (current-window-configuration))
346 (select-window (split-window (selected-window) (- (window-height) 4))) 347 (select-window (split-window (selected-window) (- (window-height) 4)))
347 (switch-to-buffer (get-buffer-create reb-buffer)) 348 (switch-to-buffer (get-buffer-create reb-buffer))
383 (interactive) 384 (interactive)
384 385
385 (reb-assert-buffer-in-window) 386 (reb-assert-buffer-in-window)
386 (with-selected-window reb-target-window 387 (with-selected-window reb-target-window
387 (if (not (re-search-forward reb-regexp (point-max) t)) 388 (if (not (re-search-forward reb-regexp (point-max) t))
388 (message "No more matches.") 389 (message "No more matches")
389 (reb-show-subexp 390 (reb-show-subexp
390 (or (and reb-subexp-mode reb-subexp-displayed) 0) 391 (or (and reb-subexp-mode reb-subexp-displayed) 0)
391 t)))) 392 t))))
392 393
393 (defun reb-prev-match () 394 (defun reb-prev-match ()
401 (if (re-search-backward reb-regexp (point-min) t) 402 (if (re-search-backward reb-regexp (point-min) t)
402 (reb-show-subexp 403 (reb-show-subexp
403 (or (and reb-subexp-mode reb-subexp-displayed) 0) 404 (or (and reb-subexp-mode reb-subexp-displayed) 0)
404 t) 405 t)
405 (goto-char p) 406 (goto-char p)
406 (message "No more matches."))))) 407 (message "No more matches")))))
407 408
408 (defun reb-toggle-case () 409 (defun reb-toggle-case ()
409 "Toggle case sensitivity of searches for RE Builder target buffer." 410 "Toggle case sensitivity of searches for RE Builder target buffer."
410 (interactive) 411 (interactive)
411 412
430 "Enter the subexpression mode in the RE Builder." 431 "Enter the subexpression mode in the RE Builder."
431 (interactive) 432 (interactive)
432 (setq reb-subexp-mode t) 433 (setq reb-subexp-mode t)
433 (reb-update-modestring) 434 (reb-update-modestring)
434 (use-local-map reb-subexp-mode-map) 435 (use-local-map reb-subexp-mode-map)
435 (message "`0'-`9' to display subexpressions `q' to quit subexp mode.")) 436 (message "`0'-`9' to display subexpressions `q' to quit subexp mode"))
436 437
437 (defun reb-show-subexp (subexp &optional pause) 438 (defun reb-show-subexp (subexp &optional pause)
438 "Visually show limit of subexpression SUBEXP of recent search. 439 "Visually show limit of subexpression SUBEXP of recent search.
439 On color displays this just puts point to the end of the expression as 440 On color displays this just puts point to the end of the expression as
440 the match should already be marked by an overlay. 441 the match should already be marked by an overlay.
441 On other displays jump to the beginning and the end of it. 442 On other displays jump to the beginning and the end of it.
442 If the optional PAUSE is non-nil then pause at the end in any case." 443 If the optional PAUSE is non-nil then pause at the end in any case."
443 (with-selected-window reb-target-window 444 (with-selected-window reb-target-window
444 (if (not (reb-color-display-p)) 445 (unless (reb-color-display-p)
445 (progn (goto-char (match-beginning subexp)) 446 (goto-char (match-beginning subexp))
446 (sit-for reb-blink-delay))) 447 (sit-for reb-blink-delay))
447 (goto-char (match-end subexp)) 448 (goto-char (match-end subexp))
448 (if (or (not (reb-color-display-p)) pause) 449 (when (or (not (reb-color-display-p)) pause)
449 (sit-for reb-blink-delay)))) 450 (sit-for reb-blink-delay))))
450 451
451 (defun reb-quit-subexp-mode () 452 (defun reb-quit-subexp-mode ()
452 "Quit the subexpression mode in the RE Builder." 453 "Quit the subexpression mode in the RE Builder."
453 (interactive) 454 (interactive)
454 (setq reb-subexp-mode nil 455 (setq reb-subexp-mode nil
492 optional fourth argument FORCE is non-nil." 493 optional fourth argument FORCE is non-nil."
493 (let ((prev-valid reb-valid-string) 494 (let ((prev-valid reb-valid-string)
494 (new-valid 495 (new-valid
495 (condition-case nil 496 (condition-case nil
496 (progn 497 (progn
497 (if (or (reb-update-regexp) force) 498 (when (or (reb-update-regexp) force)
498 (progn 499 (reb-assert-buffer-in-window)
499 (reb-assert-buffer-in-window) 500 (reb-do-update))
500 (reb-do-update)))
501 "") 501 "")
502 (error " *invalid*")))) 502 (error " *invalid*"))))
503 (setq reb-valid-string new-valid) 503 (setq reb-valid-string new-valid)
504 (force-mode-line-update) 504 (force-mode-line-update)
505 505
506 ;; Through the caching of the re a change invalidating the syntax 506 ;; Through the caching of the re a change invalidating the syntax
507 ;; for symbolic expressions will not delete the overlays so we 507 ;; for symbolic expressions will not delete the overlays so we
508 ;; catch it here 508 ;; catch it here
509 (if (and (reb-lisp-syntax-p) 509 (when (and (reb-lisp-syntax-p)
510 (not (string= prev-valid new-valid)) 510 (not (string= prev-valid new-valid))
511 (string= prev-valid "")) 511 (string= prev-valid ""))
512 (reb-delete-overlays)))) 512 (reb-delete-overlays))))
513 513
514 (defun reb-delete-overlays () 514 (defun reb-delete-overlays ()
515 "Delete all RE Builder overlays in the `reb-target-buffer' buffer." 515 "Delete all RE Builder overlays in the `reb-target-buffer' buffer."
516 (if (buffer-live-p reb-target-buffer) 516 (when (buffer-live-p reb-target-buffer)
517 (with-current-buffer reb-target-buffer 517 (with-current-buffer reb-target-buffer
518 (mapc 'delete-overlay reb-overlays) 518 (mapc 'delete-overlay reb-overlays)
519 (setq reb-overlays nil)))) 519 (setq reb-overlays nil))))
520 520
521 (defun reb-assert-buffer-in-window () 521 (defun reb-assert-buffer-in-window ()
546 (reb-do-update reb-subexp-displayed)) 546 (reb-do-update reb-subexp-displayed))
547 547
548 (defun reb-kill-buffer () 548 (defun reb-kill-buffer ()
549 "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."
550 550
551 (if (member major-mode '(reb-mode reb-lisp-mode)) 551 (when (reb-mode-buffer-p)
552 (reb-delete-overlays))) 552 (reb-delete-overlays)))
553 553
554 554
555 ;; The next functions are the interface between the regexp and 555 ;; The next functions are the interface between the regexp and
556 ;; its textual representation in the RE Builder buffer. 556 ;; its textual representation in the RE Builder buffer.
557 ;; They are the only functions concerned with the actual syntax 557 ;; They are the only functions concerned with the actual syntax
592 (reb-empty-regexp))))))) 592 (reb-empty-regexp)))))))
593 593
594 (defun reb-cook-regexp (re) 594 (defun reb-cook-regexp (re)
595 "Return RE after processing it according to `reb-re-syntax'." 595 "Return RE after processing it according to `reb-re-syntax'."
596 (cond ((eq reb-re-syntax 'lisp-re) 596 (cond ((eq reb-re-syntax 'lisp-re)
597 (if (fboundp 'lre-compile-string) 597 (when (fboundp 'lre-compile-string)
598 (lre-compile-string (eval (car (read-from-string re)))))) 598 (lre-compile-string (eval (car (read-from-string re))))))
599 ((eq reb-re-syntax 'sregex) 599 ((eq reb-re-syntax 'sregex)
600 (apply 'sregex (eval (car (read-from-string re))))) 600 (apply 'sregex (eval (car (read-from-string re)))))
601 ((eq reb-re-syntax 'rx) 601 ((eq reb-re-syntax 'rx)
602 (rx-to-string (eval (car (read-from-string re))))) 602 (rx-to-string (eval (car (read-from-string re)))))
603 (t re))) 603 (t re)))
611 (let ((oldre reb-regexp)) 611 (let ((oldre reb-regexp))
612 (prog1 612 (prog1
613 (not (string= oldre re)) 613 (not (string= oldre re))
614 (setq reb-regexp re) 614 (setq reb-regexp re)
615 ;; Only update the source re for the lisp formats 615 ;; Only update the source re for the lisp formats
616 (if (reb-lisp-syntax-p) 616 (when (reb-lisp-syntax-p)
617 (setq reb-regexp-src re-src))))))) 617 (setq reb-regexp-src re-src)))))))
618 618
619 619
620 ;; And now the real core of the whole thing 620 ;; And now the real core of the whole thing
621 (defun reb-count-subexps (re) 621 (defun reb-count-subexps (re)
622 "Return number of sub-expressions in the regexp RE." 622 "Return number of sub-expressions in the regexp RE."
641 (goto-char (point-min)) 641 (goto-char (point-min))
642 (while (and (not (eobp)) 642 (while (and (not (eobp))
643 (re-search-forward re (point-max) t) 643 (re-search-forward re (point-max) t)
644 (or (not reb-auto-match-limit) 644 (or (not reb-auto-match-limit)
645 (< matches reb-auto-match-limit))) 645 (< matches reb-auto-match-limit)))
646 (if (= 0 (length (match-string 0))) 646 (when (and (= 0 (length (match-string 0)))
647 (unless (eobp) 647 (not (eobp)))
648 (forward-char 1))) 648 (forward-char 1))
649 (let ((i 0) 649 (let ((i 0)
650 suffix max-suffix) 650 suffix max-suffix)
651 (setq matches (1+ matches)) 651 (setq matches (1+ matches))
652 (while (<= i subexps) 652 (while (<= i subexps)
653 (if (and (or (not subexp) (= subexp i)) 653 (when (and (or (not subexp) (= subexp i))
654 (match-beginning i)) 654 (match-beginning i))
655 (let ((overlay (make-overlay (match-beginning i) 655 (let ((overlay (make-overlay (match-beginning i)
656 (match-end i))) 656 (match-end i)))
657 ;; When we have exceeded the number of provided faces, 657 ;; When we have exceeded the number of provided faces,
658 ;; cycle thru them where `max-suffix' denotes the maximum 658 ;; cycle thru them where `max-suffix' denotes the maximum
659 ;; suffix for `reb-match-*' that has been defined and 659 ;; suffix for `reb-match-*' that has been defined and
660 ;; `suffix' the suffix calculated for the current match. 660 ;; `suffix' the suffix calculated for the current match.
661 (face 661 (face
662 (cond 662 (cond
663 (max-suffix 663 (max-suffix
664 (if (= suffix max-suffix) 664 (if (= suffix max-suffix)
665 (setq suffix 1) 665 (setq suffix 1)
666 (setq suffix (1+ suffix))) 666 (setq suffix (1+ suffix)))
667 (intern-soft (format "reb-match-%d" suffix))) 667 (intern-soft (format "reb-match-%d" suffix)))
668 ((intern-soft (format "reb-match-%d" i))) 668 ((intern-soft (format "reb-match-%d" i)))
669 ((setq max-suffix (1- i)) 669 ((setq max-suffix (1- i))
670 (setq suffix 1) 670 (setq suffix 1)
671 ;; `reb-match-1' must exist. 671 ;; `reb-match-1' must exist.
672 'reb-match-1)))) 672 'reb-match-1))))
673 (unless firstmatch (setq firstmatch (match-data))) 673 (unless firstmatch (setq firstmatch (match-data)))
674 (setq reb-overlays (cons overlay reb-overlays) 674 (setq reb-overlays (cons overlay reb-overlays)
675 submatches (1+ submatches)) 675 submatches (1+ submatches))
676 (overlay-put overlay 'face face) 676 (overlay-put overlay 'face face)
677 (overlay-put overlay 'priority i))) 677 (overlay-put overlay 'priority i)))
678 (setq i (1+ i)))))) 678 (setq i (1+ i))))))
679 (let ((count (if subexp submatches matches))) 679 (let ((count (if subexp submatches matches)))
680 (message "%s %smatch%s%s" 680 (message "%s %smatch%s%s"
681 (if (= 0 count) "No" (int-to-string count)) 681 (if (= 0 count) "No" (int-to-string count))
682 (if subexp "subexpression " "") 682 (if subexp "subexpression " "")
683 (if (= 1 count) "" "es") 683 (if (= 1 count) "" "es")
684 (if (and reb-auto-match-limit 684 (if (and reb-auto-match-limit
685 (= reb-auto-match-limit count)) 685 (= reb-auto-match-limit count))
686 " (limit reached)" ""))) 686 " (limit reached)" "")))
687 (if firstmatch 687 (when firstmatch
688 (progn (store-match-data firstmatch) 688 (store-match-data firstmatch)
689 (reb-show-subexp (or subexp 0)))))) 689 (reb-show-subexp (or subexp 0)))))
690
691 ;; The End
692 (defun re-builder-unload-function ()
693 "Unload the RE Builder library."
694 (when (buffer-live-p (get-buffer reb-buffer))
695 (with-current-buffer reb-buffer
696 (remove-hook 'after-change-functions 'reb-auto-update t)
697 (remove-hook 'kill-buffer-hook 'reb-kill-buffer t)
698 (when (reb-mode-buffer-p)
699 (reb-delete-overlays)
700 (funcall default-major-mode))))
701 ;; continue standard unloading
702 nil)
690 703
691 (provide 're-builder) 704 (provide 're-builder)
692 705
693 ;;; arch-tag: 5c5515ac-4085-4524-a421-033f44f032e7 706 ;;; arch-tag: 5c5515ac-4085-4524-a421-033f44f032e7
694 ;;; re-builder.el ends here 707 ;;; re-builder.el ends here