Mercurial > emacs
comparison lisp/progmodes/grep.el @ 53139:df3033332097
* progmodes/grep.el: New file with grep code from compile.el.
(grep): New defcustom group.
(grep-window-height): New defcustom, like compilation-window-height.
(grep-auto-highlight): New defcustom, like compile-auto-highlight.
(grep-scroll-output): New defcustom, like compilation-scroll-output.
(grep-command, grep-use-null-device, grep-find-command)
(grep-tree-files-aliases, grep-tree-ignore-case)
(grep-tree-ignore-CVS-directories): Move to grep custom group.
(grep-setup-hook): New hook variable.
(grep-mode-map): New keymap for grep commands. Add Grep menu.
(grep-use-compilation-buffer): New defcustom.
(grep-last-buffer): New defvar, override compilation-last-buffer.
(grep): Add optional arg HIGHLIGHT-REGEXP. Doc fix.
Call compile-internal with args highlight-regexp and grep-mode-map.
author | Kim F. Storm <storm@cua.dk> |
---|---|
date | Sun, 23 Nov 2003 20:56:10 +0000 |
parents | |
children | a0151f86f01e |
comparison
equal
deleted
inserted
replaced
53138:7cf5bcb7a8ad | 53139:df3033332097 |
---|---|
1 ;;; grep.el --- run compiler as inferior of Emacs, parse error messages | |
2 | |
3 ;; Copyright (C) 1985, 86, 87, 93, 94, 95, 96, 97, 98, 1999, 2001, 2002 | |
4 ;; Free Software Foundation, Inc. | |
5 | |
6 ;; Author: Roland McGrath <roland@gnu.org> | |
7 ;; Maintainer: FSF | |
8 ;; Keywords: tools, processes | |
9 | |
10 ;; This file is part of GNU Emacs. | |
11 | |
12 ;; GNU Emacs is free software; you can redistribute it and/or modify | |
13 ;; it under the terms of the GNU General Public License as published by | |
14 ;; the Free Software Foundation; either version 2, or (at your option) | |
15 ;; any later version. | |
16 | |
17 ;; GNU Emacs is distributed in the hope that it will be useful, | |
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
20 ;; GNU 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 package provides the grep facilities documented in the Emacs | |
30 ;; user's manual. | |
31 | |
32 ;;; Code: | |
33 | |
34 (require 'compile) | |
35 | |
36 (defgroup grep nil | |
37 "Run compiler as inferior of Emacs, parse error messages." | |
38 :group 'tools | |
39 :group 'processes) | |
40 | |
41 | |
42 ;;;###autoload | |
43 (defcustom grep-window-height nil | |
44 "*Number of lines in a grep window. If nil, use `compilation-window-height'." | |
45 :type '(choice (const :tag "Default" nil) | |
46 integer) | |
47 :version "21.4" | |
48 :group 'grep) | |
49 | |
50 (defcustom grep-auto-highlight t | |
51 "*Specify how many grep matches to highlight (and parse) initially. | |
52 \(Highlighting applies to an grep match when the mouse is over it.) | |
53 If this is a number N, all grep matches in the first N lines | |
54 are highlighted and parsed as soon as they arrive in Emacs. | |
55 If t, highlight and parse the whole grep output as soon as it arrives. | |
56 If nil, don't highlight or parse any of the grep buffer until you try to | |
57 move to the error messages. | |
58 | |
59 Those grep matches which are not parsed and highlighted initially | |
60 will be parsed and highlighted as soon as you try to move to them." | |
61 :type '(choice (const :tag "All" t) | |
62 (const :tag "None" nil) | |
63 (integer :tag "First N lines")) | |
64 :version "21.4" | |
65 :group 'grep) | |
66 | |
67 (defcustom grep-scroll-output nil | |
68 "*Non-nil to scroll the *grep* buffer window as output appears. | |
69 | |
70 Setting it causes the grep commands to put point at the end of their | |
71 output window so that the end of the output is always visible rather | |
72 than the begining." | |
73 :type 'boolean | |
74 :version "21.4" | |
75 :group 'grep) | |
76 | |
77 (defcustom grep-command nil | |
78 "The default grep command for \\[grep]. | |
79 If the grep program used supports an option to always include file names | |
80 in its output (such as the `-H' option to GNU grep), it's a good idea to | |
81 include it when specifying `grep-command'. | |
82 | |
83 The default value of this variable is set up by `grep-compute-defaults'; | |
84 call that function before using this variable in your program." | |
85 :type '(choice string | |
86 (const :tag "Not Set" nil)) | |
87 :group 'grep) | |
88 | |
89 (defcustom grep-use-null-device 'auto-detect | |
90 "If t, append the value of `null-device' to `grep' commands. | |
91 This is done to ensure that the output of grep includes the filename of | |
92 any match in the case where only a single file is searched, and is not | |
93 necessary if the grep program used supports the `-H' option. | |
94 | |
95 The default value of this variable is set up by `grep-compute-defaults'; | |
96 call that function before using this variable in your program." | |
97 :type 'boolean | |
98 :type '(choice (const :tag "Do Not Append Null Device" nil) | |
99 (const :tag "Append Null Device" t) | |
100 (other :tag "Not Set" auto-detect)) | |
101 :group 'grep) | |
102 | |
103 (defcustom grep-find-command nil | |
104 "The default find command for \\[grep-find]. | |
105 The default value of this variable is set up by `grep-compute-defaults'; | |
106 call that function before using this variable in your program." | |
107 :type '(choice string | |
108 (const :tag "Not Set" nil)) | |
109 :group 'grep) | |
110 | |
111 (defcustom grep-tree-command nil | |
112 "The default find command for \\[grep-tree]. | |
113 The default value of this variable is set up by `grep-compute-defaults'; | |
114 call that function before using this variable in your program. | |
115 The following place holders should be present in the string: | |
116 <D> - base directory for find | |
117 <X> - find options to restrict or expand the directory list | |
118 <F> - find options to limit the files matched | |
119 <C> - place to put -i if case insensitive grep | |
120 <R> - the regular expression searched for." | |
121 :type '(choice string | |
122 (const :tag "Not Set" nil)) | |
123 :version "21.4" | |
124 :group 'grep) | |
125 | |
126 (defcustom grep-tree-files-aliases '( | |
127 ("ch" . "*.[ch]") | |
128 ("c" . "*.c") | |
129 ("h" . "*.h") | |
130 ("m" . "[Mm]akefile*") | |
131 ("asm" . "*.[sS]") | |
132 ("all" . "*") | |
133 ("el" . "*.el") | |
134 ) | |
135 "*Alist of aliases for the FILES argument to `grep-tree'." | |
136 :type 'alist | |
137 :group 'grep) | |
138 | |
139 (defcustom grep-tree-ignore-case t | |
140 "*If non-nil, `grep-tree' ignores case in matches." | |
141 :type 'boolean | |
142 :group 'grep) | |
143 | |
144 (defcustom grep-tree-ignore-CVS-directories t | |
145 "*If non-nil, `grep-tree' does no recurse into CVS directories." | |
146 :type 'boolean | |
147 :group 'grep) | |
148 | |
149 ;;;###autoload | |
150 (defcustom grep-setup-hook nil | |
151 "List of hook functions run by `grep-process-setup' (see `run-hooks')." | |
152 :type 'hook | |
153 :group 'grep) | |
154 | |
155 (defvar grep-mode-map | |
156 (let ((map (cons 'keymap compilation-minor-mode-map))) | |
157 (define-key map " " 'scroll-up) | |
158 (define-key map "\^?" 'scroll-down) | |
159 | |
160 (define-key map [remap next-line] 'compilation-next-error) | |
161 (define-key map [remap previous-line] 'compilation-previous-error) | |
162 | |
163 (define-key map "\r" 'compile-goto-error) ;; ? | |
164 (define-key map "n" 'next-error-no-select) | |
165 (define-key map "p" 'previous-error-no-select) | |
166 (define-key map "{" 'compilation-previous-file) | |
167 (define-key map "}" 'compilation-next-file) | |
168 (define-key map "\t" 'compilation-next-file) | |
169 | |
170 ;; Set up the menu-bar | |
171 (define-key map [menu-bar grep] | |
172 (cons "Grep" (make-sparse-keymap "Grep"))) | |
173 | |
174 (define-key map [menu-bar grep compilation-kill-compilation] | |
175 '("Kill Grep" . kill-compilation)) | |
176 (define-key map [menu-bar grep compilation-separator2] | |
177 '("----" . nil)) | |
178 (define-key map [menu-bar grep compilation-compile] | |
179 '("Compile..." . compile)) | |
180 (define-key map [menu-bar grep compilation-grep] | |
181 '("Another grep" . grep)) | |
182 (define-key map [menu-bar grep compilation-recompile] | |
183 '("Repeat grep" . recompile)) | |
184 (define-key map [menu-bar grep compilation-separator2] | |
185 '("----" . nil)) | |
186 (define-key map [menu-bar grep compilation-first-error] | |
187 '("First Match" . first-error)) | |
188 (define-key map [menu-bar grep compilation-previous-error] | |
189 '("Previous Match" . previous-error)) | |
190 (define-key map [menu-bar grep compilation-next-error] | |
191 '("Next Match" . next-error)) | |
192 map) | |
193 "Keymap for grep buffers. | |
194 `compilation-minor-mode-map' is a cdr of this.") | |
195 | |
196 ;;;; TODO --- refine this!! | |
197 | |
198 (defcustom grep-use-compilation-buffer t | |
199 "When non-nil, grep specific commands update `compilation-last-buffer'. | |
200 This means that standard compile commands like \\[next-error] and \\[compile-goto-error] | |
201 can be used to navigate between grep matches (the default). | |
202 Otherwise, the grep specific commands like \\[grep-next-match] must | |
203 be used to navigate between grep matches." | |
204 :type 'boolean | |
205 :group 'grep) | |
206 | |
207 ;; override compilation-last-buffer | |
208 (defvar grep-last-buffer nil | |
209 "The most recent grep buffer. | |
210 A grep buffer becomes most recent when its process is started | |
211 or when it is used with \\[grep-next-match]. | |
212 Notice that using \\[next-error] or \\[compile-goto-error] modifies | |
213 `complation-last-buffer' rather than `grep-last-buffer'.") | |
214 | |
215 ;; Note: the character class after the optional drive letter does not | |
216 ;; include a space to support file names with blanks. | |
217 (defvar grep-regexp-alist | |
218 '(("\\([a-zA-Z]?:?[^:(\t\n]+\\)[:( \t]+\\([0-9]+\\)[:) \t]" 1 2)) | |
219 "Regexp used to match grep hits. See `compilation-error-regexp-alist'.") | |
220 | |
221 (defvar grep-program | |
222 ;; Currently zgrep has trouble. It runs egrep instead of grep, | |
223 ;; and it doesn't pass along long options right. | |
224 "grep" | |
225 ;; (if (equal (condition-case nil ; in case "zgrep" isn't in exec-path | |
226 ;; (call-process "zgrep" nil nil nil | |
227 ;; "foo" null-device) | |
228 ;; (error nil)) | |
229 ;; 1) | |
230 ;; "zgrep" | |
231 ;; "grep") | |
232 "The default grep program for `grep-command' and `grep-find-command'. | |
233 This variable's value takes effect when `grep-compute-defaults' is called.") | |
234 | |
235 (defvar find-program "find" | |
236 "The default find program for `grep-find-command'. | |
237 This variable's value takes effect when `grep-compute-defaults' is called.") | |
238 | |
239 (defvar grep-find-use-xargs nil | |
240 "Whether \\[grep-find] uses the `xargs' utility by default. | |
241 | |
242 If nil, it uses `find -exec'; if `gnu', it uses `find -print0' and `xargs -0'; | |
243 if not nil and not `gnu', it uses `find -print' and `xargs'. | |
244 | |
245 This variable's value takes effect when `grep-compute-defaults' is called.") | |
246 | |
247 ;; History of grep commands. | |
248 (defvar grep-history nil) | |
249 (defvar grep-find-history nil) | |
250 | |
251 (defun grep-process-setup () | |
252 "Setup compilation variables and buffer for `grep'. | |
253 Set up `compilation-exit-message-function' and `compilation-window-height'. | |
254 Sets `grep-last-buffer' and runs `grep-setup-hook'." | |
255 (setq grep-last-buffer (current-buffer)) | |
256 (set (make-local-variable 'compilation-exit-message-function) | |
257 (lambda (status code msg) | |
258 (if (eq status 'exit) | |
259 (cond ((zerop code) | |
260 '("finished (matches found)\n" . "matched")) | |
261 ((= code 1) | |
262 '("finished with no matches found\n" . "no match")) | |
263 (t | |
264 (cons msg code))) | |
265 (cons msg code)))) | |
266 (if grep-window-height | |
267 (set (make-local-variable 'compilation-window-height) | |
268 grep-window-height)) | |
269 (set (make-local-variable 'compile-auto-highlight) | |
270 grep-auto-highlight) | |
271 (set (make-local-variable 'compilation-scroll-output) | |
272 grep-scroll-output) | |
273 (run-hooks 'grep-setup-hook)) | |
274 | |
275 (defun grep-compute-defaults () | |
276 (unless (or (not grep-use-null-device) (eq grep-use-null-device t)) | |
277 (setq grep-use-null-device | |
278 (with-temp-buffer | |
279 (let ((hello-file (expand-file-name "HELLO" data-directory))) | |
280 (not | |
281 (and (equal (condition-case nil | |
282 (if grep-command | |
283 ;; `grep-command' is already set, so | |
284 ;; use that for testing. | |
285 (call-process-shell-command | |
286 grep-command nil t nil | |
287 "^English" hello-file) | |
288 ;; otherwise use `grep-program' | |
289 (call-process grep-program nil t nil | |
290 "-nH" "^English" hello-file)) | |
291 (error nil)) | |
292 0) | |
293 (progn | |
294 (goto-char (point-min)) | |
295 (looking-at | |
296 (concat (regexp-quote hello-file) | |
297 ":[0-9]+:English"))))))))) | |
298 (unless grep-command | |
299 (setq grep-command | |
300 (let ((required-options (if grep-use-null-device "-n" "-nH"))) | |
301 (if (equal (condition-case nil ; in case "grep" isn't in exec-path | |
302 (call-process grep-program nil nil nil | |
303 "-e" "foo" null-device) | |
304 (error nil)) | |
305 1) | |
306 (format "%s %s -e " grep-program required-options) | |
307 (format "%s %s " grep-program required-options))))) | |
308 (unless grep-find-use-xargs | |
309 (setq grep-find-use-xargs | |
310 (if (and | |
311 (equal (call-process "find" nil nil nil | |
312 null-device "-print0") | |
313 0) | |
314 (equal (call-process "xargs" nil nil nil | |
315 "-0" "-e" "echo") | |
316 0)) | |
317 'gnu))) | |
318 (unless grep-find-command | |
319 (setq grep-find-command | |
320 (cond ((eq grep-find-use-xargs 'gnu) | |
321 (format "%s . -type f -print0 | xargs -0 -e %s" | |
322 find-program grep-command)) | |
323 (grep-find-use-xargs | |
324 (format "%s . -type f -print | xargs %s" | |
325 find-program grep-command)) | |
326 (t (cons (format "%s . -type f -exec %s {} %s \\;" | |
327 find-program grep-command null-device) | |
328 (+ 22 (length grep-command))))))) | |
329 (unless grep-tree-command | |
330 (setq grep-tree-command | |
331 (let* ((glen (length grep-program)) | |
332 (gcmd (concat grep-program " <C>" (substring grep-command glen)))) | |
333 (cond ((eq grep-find-use-xargs 'gnu) | |
334 (format "%s <D> <X> -type f <F> -print0 | xargs -0 -e %s <R>" | |
335 find-program gcmd)) | |
336 (grep-find-use-xargs | |
337 (format "%s <D> <X> -type f <F> -print | xargs %s <R>" | |
338 find-program gcmd)) | |
339 (t (format "%s <D> <X> -type f <F> -exec %s <R> {} %s \\;" | |
340 find-program gcmd null-device))))))) | |
341 | |
342 (defun grep-default-command () | |
343 (let ((tag-default | |
344 (funcall (or find-tag-default-function | |
345 (get major-mode 'find-tag-default-function) | |
346 ;; We use grep-tag-default instead of | |
347 ;; find-tag-default, to avoid loading etags. | |
348 'grep-tag-default))) | |
349 (sh-arg-re "\\(\\(?:\"\\(?:[^\"]\\|\\\\\"\\)+\"\\|'[^']+'\\|[^\"' \t\n]\\)+\\)") | |
350 (grep-default (or (car grep-history) grep-command))) | |
351 ;; Replace the thing matching for with that around cursor. | |
352 (when (or (string-match | |
353 (concat "[^ ]+\\s +\\(?:-[^ ]+\\s +\\)*" | |
354 sh-arg-re "\\(\\s +\\(\\S +\\)\\)?") | |
355 grep-default) | |
356 ;; If the string is not yet complete. | |
357 (string-match "\\(\\)\\'" grep-default)) | |
358 (unless (or (not (stringp buffer-file-name)) | |
359 (when (match-beginning 2) | |
360 (save-match-data | |
361 (string-match | |
362 (wildcard-to-regexp | |
363 (file-name-nondirectory | |
364 (match-string 3 grep-default))) | |
365 (file-name-nondirectory buffer-file-name))))) | |
366 (setq grep-default (concat (substring grep-default | |
367 0 (match-beginning 2)) | |
368 " *." | |
369 (file-name-extension buffer-file-name)))) | |
370 (replace-match (or tag-default "") t t grep-default 1)))) | |
371 | |
372 ;;;###autoload | |
373 (defun grep (command-args &optional highlight-regexp) | |
374 "Run grep, with user-specified args, and collect output in a buffer. | |
375 While grep runs asynchronously, you can use \\[next-error] (M-x next-error), | |
376 or \\<grep-minor-mode-map>\\[compile-goto-error] in the grep \ | |
377 output buffer, to go to the lines | |
378 where grep found matches. | |
379 | |
380 This command uses a special history list for its COMMAND-ARGS, so you can | |
381 easily repeat a grep command. | |
382 | |
383 A prefix argument says to default the argument based upon the current | |
384 tag the cursor is over, substituting it into the last grep command | |
385 in the grep command history (or into `grep-command' | |
386 if that history list is empty). | |
387 | |
388 If specified, optional second arg HIGHLIGHT-REGEXP is the regexp to | |
389 temporarily highlight in visited source lines." | |
390 (interactive | |
391 (progn | |
392 (unless (and grep-command | |
393 (or (not grep-use-null-device) (eq grep-use-null-device t))) | |
394 (grep-compute-defaults)) | |
395 (let ((default (grep-default-command))) | |
396 (list (read-from-minibuffer "Run grep (like this): " | |
397 (if current-prefix-arg | |
398 default grep-command) | |
399 nil nil 'grep-history | |
400 (if current-prefix-arg nil default)))))) | |
401 | |
402 ;; Setting process-setup-function makes exit-message-function work | |
403 ;; even when async processes aren't supported. | |
404 (let* ((compilation-process-setup-function 'grep-process-setup) | |
405 (buf (compile-internal (if (and grep-use-null-device null-device) | |
406 (concat command-args " " null-device) | |
407 command-args) | |
408 "No more grep hits" "grep" | |
409 ;; Give it a simpler regexp to match. | |
410 nil grep-regexp-alist | |
411 nil nil nil nil nil nil | |
412 highlight-regexp grep-mode-map))))) | |
413 | |
414 ;; This is a copy of find-tag-default from etags.el. | |
415 (defun grep-tag-default () | |
416 (save-excursion | |
417 (while (looking-at "\\sw\\|\\s_") | |
418 (forward-char 1)) | |
419 (when (or (re-search-backward "\\sw\\|\\s_" | |
420 (save-excursion (beginning-of-line) (point)) | |
421 t) | |
422 (re-search-forward "\\(\\sw\\|\\s_\\)+" | |
423 (save-excursion (end-of-line) (point)) | |
424 t)) | |
425 (goto-char (match-end 0)) | |
426 (buffer-substring (point) | |
427 (progn (forward-sexp -1) | |
428 (while (looking-at "\\s'") | |
429 (forward-char 1)) | |
430 (point)))))) | |
431 | |
432 ;;;###autoload | |
433 (defun grep-find (command-args) | |
434 "Run grep via find, with user-specified args COMMAND-ARGS. | |
435 Collect output in a buffer. | |
436 While find runs asynchronously, you can use the \\[next-error] command | |
437 to find the text that grep hits refer to. | |
438 | |
439 This command uses a special history list for its arguments, so you can | |
440 easily repeat a find command." | |
441 (interactive | |
442 (progn | |
443 (unless grep-find-command | |
444 (grep-compute-defaults)) | |
445 (list (read-from-minibuffer "Run find (like this): " | |
446 grep-find-command nil nil | |
447 'grep-find-history)))) | |
448 (let ((null-device nil)) ; see grep | |
449 (grep command-args))) | |
450 | |
451 (defun grep-expand-command-macros (command &optional regexp files dir excl case-fold) | |
452 "Patch grep COMMAND replacing <D>, etc." | |
453 (setq command | |
454 (replace-regexp-in-string "<D>" | |
455 (or dir ".") command t t)) | |
456 (setq command | |
457 (replace-regexp-in-string "<X>" | |
458 (or excl "") command t t)) | |
459 (setq command | |
460 (replace-regexp-in-string "<F>" | |
461 (or files "") command t t)) | |
462 (setq command | |
463 (replace-regexp-in-string "<C>" | |
464 (if case-fold "-i" "") command t t)) | |
465 (setq command | |
466 (replace-regexp-in-string "<R>" | |
467 (or regexp "") command t t)) | |
468 command) | |
469 | |
470 (defvar grep-tree-last-regexp "") | |
471 (defvar grep-tree-last-files (car (car grep-tree-files-aliases))) | |
472 | |
473 ;;;###autoload | |
474 (defun grep-tree (regexp files dir &optional subdirs) | |
475 "Grep for REGEXP in FILES in directory tree rooted at DIR. | |
476 Collect output in a buffer. | |
477 Interactively, prompt separately for each search parameter. | |
478 With prefix arg, reuse previous REGEXP. | |
479 The search is limited to file names matching shell pattern FILES. | |
480 FILES may use abbreviations defined in `grep-tree-files-aliases', e.g. | |
481 entering `ch' is equivalent to `*.[ch]'. | |
482 | |
483 While find runs asynchronously, you can use the \\[next-error] command | |
484 to find the text that grep hits refer to. | |
485 | |
486 This command uses a special history list for its arguments, so you can | |
487 easily repeat a find command. | |
488 | |
489 When used non-interactively, optional arg SUBDIRS limits the search to | |
490 those sub directories of DIR." | |
491 (interactive | |
492 (let* ((regexp | |
493 (if current-prefix-arg | |
494 grep-tree-last-regexp | |
495 (let* ((default (current-word)) | |
496 (spec (read-string | |
497 (concat "Search for" | |
498 (if (and default (> (length default) 0)) | |
499 (format " (default %s): " default) ": "))))) | |
500 (if (equal spec "") default spec)))) | |
501 (files | |
502 (read-string (concat "Search for \"" regexp "\" in files (default " grep-tree-last-files "): "))) | |
503 (dir | |
504 (read-directory-name "Base directory: " nil default-directory t))) | |
505 (list regexp files dir))) | |
506 (unless grep-tree-command | |
507 (grep-compute-defaults)) | |
508 (unless (and (stringp files) (> (length files) 0)) | |
509 (setq files grep-tree-last-files)) | |
510 (when files | |
511 (setq grep-tree-last-files files) | |
512 (let ((mf (assoc files grep-tree-files-aliases))) | |
513 (if mf | |
514 (setq files (cdr mf))))) | |
515 (let ((command-args (grep-expand-command-macros | |
516 grep-tree-command | |
517 (setq grep-tree-last-regexp regexp) | |
518 (and files (concat "-name '" files "'")) | |
519 (if subdirs | |
520 (if (stringp subdirs) | |
521 subdirs | |
522 (mapconcat 'identity subdirs " ")) | |
523 nil) ;; we change default-directory to dir | |
524 (and grep-tree-ignore-CVS-directories "-path '*/CVS' -prune -o ") | |
525 grep-tree-ignore-case)) | |
526 (default-directory dir) | |
527 (null-device nil)) ; see grep | |
528 (grep command-args regexp))) | |
529 | |
530 | |
531 (provide 'grep) | |
532 | |
533 ;;; grep.el ends here | |
534 |