├── TODO └── regex-tool.el /TODO: -------------------------------------------------------------------------------- 1 | REGEX-TOOL -*- mode: org; fill-column: 78 -*- 2 | 3 | #+STARTUP: overview 4 | #+ARCHIVE: TODO-OLD:: 5 | #+SEQ_TODO: TODO(@) STARTED(@) WAITING(@) DELEGATED(@) | DONE(@) DEFERRED(@) CANCELLED(@) WONTFIX(@) WORKSFORME(@) INVALID(@) DUPLICATE(@) NOTE 6 | #+TAGS: FEATURE(f) DOCS(d) WEBSITE(w) BUILD(b) ATTACH(a) 7 | #+CATEGORY: rgx-tool 8 | 9 | * TODO [#B] Add regex-tool patch for Emacs 21 support 10 | (from e-mail [[message://47A86418.6000704@trueposition.com][regex-tool]]): Works okay in emacs 22, but I had to add this 11 | [attached] to backport to emacs 21. 12 | :PROPERTIES: 13 | :Submitter: Mitchell Perilstein 14 | :ID: 064CDAC0-D021-422C-BB16-F563CCF575A6 15 | :Attachments: remove-overlays.el 16 | :END: 17 | [2008-02-05 Tue] 18 | * TODO [#B] T. Kurt Bond suggested several changes to regex-tool :ATTACH: 19 | (from e-mail [[message://uabovlded.fsf@tkb.mpl.com][regex-tool.el patch]]): I've enclosed a patch that adds two 20 | things: 21 | 22 | 1. An *Elisp* buffer that shows a quoted version of the regex suitable for 23 | cutting and pasting into emacs lisp source. Unfortunately, I didn't take 24 | into account the perl backend, so it would need some tweaking. 25 | 26 | 2. Allows more than 9 matches to be displayed, so that 27 | \(1\)\(2\)\(3\)\(4\)\(5\)\(6\)\(7\)\(8\)\(9\)\(a\)\(b\)\(c\)\(d\)\(e\)\(f\) 28 | matched against 29 | 123456789abcdef 30 | shows all 15 individual matches in addition to the group 0 match. 31 | (Just look for the change to dotimes.) 32 | :PROPERTIES: 33 | :Submitter: T. Kurt Bond 34 | :ID: F7E77C16-2EB1-4447-A192-B1916DE45279 35 | :Attachments: bond.patch 36 | :END: 37 | [2007-11-30 Fri] 38 | * TODO [#B] Patch for / characters in a regular expression :ATTACH: 39 | I found a minor bug though: in perl mode it uses m// syntax, but slashes 40 | aren't escaped in elisp code, which makes the tool fail if I have '/' in 41 | regexp. This patch helped me [attached]. 42 | :PROPERTIES: 43 | :Submitter: Marcin Bachry 44 | :ID: 597BF019-56C5-4C72-B13C-E8D8C930ADC5 45 | :Attachments: guard-slash.patch 46 | :END: 47 | [2008-03-27 Thu] 48 | * TODO [#B] Apply patch to regex-tool sent by Christian Stucchio :ATTACH: 49 | (from e-mail [[message://60424aeb0712270704q263ba990h7b5c7db9eaea058c@mail.gmail.com][regex-tool.el]]): So far, I've only found one thing I dislike: 50 | the fact that it opens a new frame. I prefer it to open in the current 51 | frame. 52 | 53 | I've attached a slightly modified version in which that behavior is 54 | customizable. If regex-tool-new-frame is t (the default), the current 55 | behavior is preserved. If nil, the current frame is used. Steal the code if 56 | you like it. 57 | :PROPERTIES: 58 | :Submitter: Christian Stucchio 59 | :ID: C37A5A8A-8EF2-4788-855A-961DA72C69E7 60 | :Attachments: reuse-frame.patch 61 | :END: 62 | [2007-12-27 Thu] 63 | * TODO [#B] Johan LindstrXm found a typo in regex-tool 64 | (from e-mail [[message://200801202048.BYP36673@imap.infopop.com][Regex Tool - wrong description?]]): This defun looks like it was 65 | copied from org-mode and not cleaned up properly :) 66 | :OUTPUT: 67 | (defgroup regex-tool nil 68 | "Outline-based notes management and organizer." 69 | :tag "Org" 70 | :group 'programming) 71 | :END: 72 | :PROPERTIES: 73 | :Submitter: Johan LindstrXm 74 | :ID: 107D4BC7-5949-4933-9D94-0E682C9748F0 75 | :END: 76 | [2008-01-20 Sun] 77 | * TODO [#A] Apply Johan LindstrXm's regex-tool patch :ATTACH: 78 | (from e-mail [[message://200801202043.BYP36639@imap.infopop.com][Regex Tool]]): I just recently started using your excellent Emacs 79 | Regex Tool. Very useful, so hats off for that! 80 | 81 | One thing I missed though was the ability of specifying Perl regex 82 | modifiers, such as /x etc. So I wrote a patch to change the Perl regex 83 | syntax from 'MY-REGEX' to '/MY-REGEX/MODIFIERS' 84 | 85 | (It is still aware of /g and multiple matches if needed) 86 | 87 | This patch would change the usage in an incompatible way from before, but 88 | OTOH this tool is supposedly not used programmatically anyway so that's 89 | probably not a big deal. 90 | 91 | If you think this sounds like a good idea, I'd be very happy for you to 92 | incorporate it with your package. 93 | :PROPERTIES: 94 | :Submitter: Johan LindstrXm 95 | :ID: 915929F6-4A97-43E0-861C-25B9B7FE9AF9 96 | :Attachments: regex-modifiers.patch 97 | :END: 98 | [2008-01-20 Sun] 99 | -------------------------------------------------------------------------------- /regex-tool.el: -------------------------------------------------------------------------------- 1 | ;;; regex-tool.el --- A regular expression evaluation tool for programmers 2 | 3 | ;; Copyright (C) 2007 John Wiegley 4 | 5 | ;; Author: John Wiegley 6 | ;; Created: 29 Oct 2007 7 | ;; Modified: 17 Nov 2007 8 | ;; Version: 1.2 9 | ;; Keywords: regex languages programming development 10 | ;; X-URL: http://www.newartisans.com/ 11 | 12 | ;; This program is free software; you can redistribute it and/or 13 | ;; modify it under the terms of the GNU General Public License as 14 | ;; published by the Free Software Foundation; either version 2, or (at 15 | ;; your option) any later version. 16 | 17 | ;; This program is distributed in the hope that it will be useful, but 18 | ;; WITHOUT ANY WARRANTY; without even the implied warranty of 19 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | ;; General Public License for more details. 21 | 22 | ;; You should have received a copy of the GNU General Public License 23 | ;; along with GNU Emacs; see the file COPYING. If not, write to the 24 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, 25 | ;; Boston, MA 02111-1307, USA. 26 | 27 | ;;; Commentary: 28 | 29 | ;; This program currently uses frames only. 30 | ;; 31 | ;; After you type M-x regex-tool, you will see three buffers: *Regex*, *Text* 32 | ;; and *Groups*. The *Regex* buffer contains your regular expression. By 33 | ;; default, this tool uses Emacs regular expressions. If you customize the 34 | ;; variable `regex-tool-backend', you can switch to using full Perl regular 35 | ;; expressions. 36 | ;; 37 | ;; The *Text* buffer contains the sample text you want to match against. 38 | ;; Change this however you like. 39 | ;; 40 | ;; The *Groups* buffer will list out any regular expression groups that match. 41 | ;; Your regular expression is searched for as many times as it appears in the 42 | ;; buffer, and any groups that match will be repeated. 43 | ;; 44 | ;; The results are updated as you type in either the *Regex* or *Text* buffer. 45 | ;; Use C-c C-c to force an update. Use C-c C-k to quit all the regex-tool 46 | ;; buffers and remove the frame. 47 | 48 | ;;; Version History: 49 | 50 | ;; 1.1 - Don't die horribly if the user simply types '^' or '$' 51 | ;; 1.2 - Include cl.el at compile time 52 | 53 | ;;; Code: 54 | 55 | (eval-when-compile 56 | (require 'cl)) 57 | 58 | (defgroup regex-tool nil 59 | "Outline-based notes management and organizer." 60 | :tag "Org" 61 | :group 'programming) 62 | 63 | (defvar regex-tool-mode-map (make-sparse-keymap)) 64 | (defvar regex-tool-mode-abbrev-table) 65 | 66 | (define-derived-mode regex-tool-mode text-mode "Regex Tool" 67 | "This is regex-tool mode." 68 | (define-key regex-tool-mode-map [(control ?c) (control ?c)] 69 | 'regex-tool-markup-text) 70 | (define-key regex-tool-mode-map [(control ?c) (control ?k)] 71 | 'regex-tool-quit) 72 | (add-hook 'after-change-functions 'regex-tool-markup-text nil t)) 73 | 74 | (defface regex-tool-matched-face 75 | '((((background light)) (:foreground "Red" :bold t)) 76 | (((background dark)) (:foreground "Orange" :bold t))) 77 | "" 78 | :group 'regex-tool) 79 | 80 | (defcustom regex-tool-backend 'emacs 81 | "The backend used to process regular expressions. 82 | The `emacs' backend handles regular expressions directly. 83 | The `perl' backend talks to a perl subprocess to do the handling.\" 84 | " 85 | :type '(choice 86 | (const :tag "Emacs" emacs) 87 | (const :tag "Perl" perl)) 88 | :group 'regex-tool) 89 | 90 | (defun regex-render-perl (regex sample) 91 | (with-temp-buffer 92 | (insert (format "@lines = ; 93 | $line = join(\"\", @lines); 94 | print \"(\"; 95 | while ($line =~ m/%s/mg) { 96 | print \"(\", length($`), \" \", length($&), \" \"; 97 | for $i (1 .. 20) { 98 | if ($$i) { 99 | my $group = $$i; 100 | $group =~ s/([\\\\\"])/\\\\\\1/g; 101 | print \"(\", $i, \" . \\\"\", $group, \"\\\") \"; 102 | } 103 | } 104 | print \")\"; 105 | } 106 | print \")\"; 107 | __DATA__ 108 | %s" regex sample)) 109 | (call-process-region (point-min) (point-max) "perl" t t) 110 | (goto-char (point-min)) 111 | (read (current-buffer)))) 112 | 113 | (defvar regex-expr-buffer nil) 114 | (defvar regex-text-buffer nil) 115 | (defvar regex-group-buffer nil) 116 | 117 | ;;;###autoload 118 | (defun regex-tool () 119 | (interactive) 120 | (let ((sample-text 121 | (when (use-region-p) 122 | (buffer-substring-no-properties (region-beginning) (region-end))))) 123 | (select-frame (make-frame-command)) 124 | (split-window-vertically) 125 | (split-window-vertically) 126 | (balance-windows) 127 | (setq regex-expr-buffer (get-buffer-create "*Regex*")) 128 | (switch-to-buffer regex-expr-buffer) 129 | (regex-tool-mode) 130 | (other-window 1) 131 | (setq regex-text-buffer (get-buffer-create "*Text*")) 132 | (switch-to-buffer regex-text-buffer) 133 | (goto-char (point-min)) 134 | (if sample-text 135 | (progn 136 | (delete-region (point-min) (point-max)) 137 | (insert sample-text) 138 | (goto-char (point-min))) 139 | (if (eolp) 140 | (insert "Hello, this is text your regular expression will match against."))) 141 | (regex-tool-mode) 142 | (other-window 1) 143 | (setq regex-group-buffer (get-buffer-create "*Groups*")) 144 | (switch-to-buffer regex-group-buffer) 145 | (other-window 1))) 146 | 147 | (defun regex-tool-markup-text (&optional beg end len) 148 | (interactive) 149 | (let ((regex (with-current-buffer regex-expr-buffer 150 | (buffer-string))) 151 | previous-point) 152 | (when (> (length regex) 0) 153 | (with-current-buffer regex-group-buffer 154 | (erase-buffer)) 155 | (with-current-buffer regex-text-buffer 156 | (remove-overlays) 157 | (save-excursion 158 | (ignore-errors 159 | (goto-char (point-min)) 160 | (if (eq regex-tool-backend 'emacs) 161 | (while (and (setq previous-point (point)) 162 | (re-search-forward regex nil t)) 163 | (if (= (point) previous-point) 164 | (forward-char 1) 165 | (overlay-put (make-overlay (match-beginning 0) 166 | (match-end 0)) 167 | 'face 'regex-tool-matched-face) 168 | (dotimes (i 10) 169 | (let ((text (match-string i))) 170 | (if text 171 | (save-match-data 172 | (with-current-buffer regex-group-buffer 173 | (goto-char (point-max)) 174 | (insert (format "Group %d: '%s'\n" i text))))))) 175 | (with-current-buffer regex-group-buffer 176 | (insert ?\n)))) 177 | (let ((results (regex-render-perl regex (buffer-string)))) 178 | (dolist (result results) 179 | (let ((offset (nth 0 result)) 180 | (length (nth 1 result)) 181 | (matches (nthcdr 2 result))) 182 | (overlay-put (make-overlay (1+ offset) (+ offset length 1)) 183 | 'face 'regex-tool-matched-face) 184 | (let ((match-zero (buffer-substring (1+ offset) 185 | (+ offset length 1)))) 186 | (with-current-buffer regex-group-buffer 187 | (insert (format "Group 0: '%s'\n" match-zero)))) 188 | (dolist (match matches) 189 | (with-current-buffer regex-group-buffer 190 | (goto-char (point-max)) 191 | (insert (format "Group %d: '%s'\n" (car match) 192 | (cdr match))))) 193 | (with-current-buffer regex-group-buffer 194 | (insert ?\n))))))))) 195 | (with-current-buffer regex-group-buffer 196 | (goto-char (point-min)))))) 197 | 198 | (defun regex-tool-quit () 199 | (interactive) 200 | (kill-buffer regex-expr-buffer) 201 | (kill-buffer regex-text-buffer) 202 | (kill-buffer regex-group-buffer) 203 | (delete-frame)) 204 | 205 | (provide 'regex-tool) 206 | 207 | ;;; regex-tool.el ends here 208 | --------------------------------------------------------------------------------