Show
Ignore:
Timestamp:
05/03/06 18:37:43 (3 years ago)
Author:
miyoshi
Message:

Sync up with Emacs CVS HEAD.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk

    • Property svn:ignore changed from
      bin
      to
      bin
      site-lisp
  • trunk/lisp/progmodes/grep.el

    r4058 r4073  
    3636 
    3737(defgroup grep nil 
    38   "Run compiler as inferior of Emacs, parse error messages." 
     38  "Run grep as inferior of Emacs, parse error messages." 
    3939  :group 'tools 
    4040  :group 'processes) 
     
    4646  :type '(choice (const :tag "Default" nil) 
    4747                 integer) 
    48   :version "22.1" 
    49   :group 'grep) 
    50  
    51 (defcustom grep-auto-highlight t 
    52   "*Specify how many grep matches to highlight (and parse) initially. 
    53 \(Highlighting applies to an grep match when the mouse is over it.) 
    54 If this is a number N, all grep matches in the first N lines 
    55 are highlighted and parsed as soon as they arrive in Emacs. 
    56 If t, highlight and parse the whole grep output as soon as it arrives. 
    57 If nil, don't highlight or parse any of the grep buffer until you try to 
    58 move to the error messages. 
    59  
    60 Those grep matches which are not parsed and highlighted initially 
    61 will be parsed and highlighted as soon as you try to move to them." 
    62   :type '(choice (const :tag "All" t) 
    63                  (const :tag "None" nil) 
    64                  (integer :tag "First N lines")) 
    6548  :version "22.1" 
    6649  :group 'grep) 
     
    10992  :group 'grep) 
    11093 
     94(defcustom grep-template nil 
     95  "The default command to run for \\[lgrep]. 
     96The default value of this variable is set up by `grep-compute-defaults'; 
     97call that function before using this variable in your program. 
     98The following place holders should be present in the string: 
     99 <C> - place to put -i if case insensitive grep. 
     100 <F> - file names and wildcards to search. 
     101 <R> - the regular expression searched for. 
     102 <N> - place to insert null-device." 
     103  :type '(choice string 
     104                 (const :tag "Not Set" nil)) 
     105  :version "22.1" 
     106  :group 'grep) 
     107 
    111108(defcustom grep-use-null-device 'auto-detect 
    112109  "If t, append the value of `null-device' to `grep' commands. 
     
    131128  :group 'grep) 
    132129 
    133 (defcustom grep-tree-command nil 
    134   "The default find command for \\[grep-tree]. 
     130(defcustom grep-find-template nil 
     131  "The default command to run for \\[rgrep]. 
    135132The default value of this variable is set up by `grep-compute-defaults'; 
    136133call that function before using this variable in your program. 
     
    146143  :group 'grep) 
    147144 
    148 (defcustom grep-tree-files-aliases '( 
     145(defcustom grep-files-aliases '( 
     146        ("el" . "*.el") 
    149147        ("ch" . "*.[ch]") 
    150148        ("c" .  "*.c") 
    151149        ("h" .  "*.h") 
     150        ("asm" . "*.[sS]") 
    152151        ("m" .  "[Mm]akefile*") 
    153         ("asm" . "*.[sS]") 
    154         ("all" . "*") 
    155         ("el" . "*.el") 
     152        ("l" . "[Cc]hange[Ll]og*") 
    156153        ) 
    157   "*Alist of aliases for the FILES argument to `grep-tree'." 
     154  "*Alist of aliases for the FILES argument to `lgrep' and `rgrep'." 
    158155  :type 'alist 
    159156  :group 'grep) 
    160157 
    161 (defcustom grep-tree-ignore-case t 
    162   "*If non-nil, `grep-tree' ignores case in matches." 
    163   :type 'boolean 
    164   :group 'grep) 
    165  
    166 (defcustom grep-tree-ignore-CVS-directories t 
    167   "*If non-nil, `grep-tree' does no recurse into CVS directories." 
    168   :type 'boolean 
     158(defcustom grep-find-ignored-directories '("CVS" ".hg" "{arch}") 
     159  "*List of names of sub-directories which `rgrep' shall not recurse into." 
     160  :type '(repeat string) 
    169161  :group 'grep) 
    170162 
     
    209201    (define-key map [menu-bar grep compilation-grep] 
    210202      '("Another grep..." . grep)) 
     203    (define-key map [menu-bar grep compilation-grep-find] 
     204      '("Recursive grep..." . grep-find)) 
    211205    (define-key map [menu-bar grep compilation-recompile] 
    212206      '("Repeat grep" . recompile)) 
     
    354348(defvar grep-find-history nil) 
    355349 
     350;; History of lgrep and rgrep regexp and files args. 
     351(defvar grep-regexp-history nil) 
     352(defvar grep-files-history '("ch" "el")) 
     353 
     354 
    356355;;;###autoload 
    357356(defun grep-process-setup () 
     
    379378  (run-hooks 'grep-setup-hook)) 
    380379 
     380(defun grep-probe (command args &optional func result) 
     381  (equal (condition-case nil 
     382             (apply (or func 'call-process) command args) 
     383           (error nil)) 
     384         (or result 0))) 
     385 
    381386;;;###autoload 
    382387(defun grep-compute-defaults () 
     
    386391            (let ((hello-file (expand-file-name "HELLO" data-directory))) 
    387392              (not 
    388                (and (equal (condition-case nil 
    389                                (if grep-command 
    390                                    ;; `grep-command' is already set, so 
    391                                    ;; use that for testing. 
    392                                    (call-process-shell-command 
    393                                     grep-command nil t nil 
    394                                     "^English" hello-file) 
    395                                  ;; otherwise use `grep-program' 
    396                                  (call-process grep-program nil t nil 
    397                                                "-nH" "^English" hello-file)) 
    398                              (error nil)) 
    399                            0) 
     393               (and (if grep-command 
     394                        ;; `grep-command' is already set, so 
     395                        ;; use that for testing. 
     396                        (grep-probe grep-command 
     397                                    `(nil t nil "^English" ,hello-file) 
     398                                    #'call-process-shell-command) 
     399                      ;; otherwise use `grep-program' 
     400                      (grep-probe grep-program 
     401                                  `(nil t nil "-nH" "^English" ,hello-file))) 
    400402                    (progn 
    401403                      (goto-char (point-min)) 
     
    403405                       (concat (regexp-quote hello-file) 
    404406                               ":[0-9]+:English"))))))))) 
    405   (unless grep-command 
    406     (setq grep-command 
    407           (let ((required-options (if grep-use-null-device "-n" "-nH"))) 
    408             (if (equal (condition-case nil ; in case "grep" isn't in exec-path 
    409                           (call-process grep-program nil nil nil 
    410                                         "-e" "foo" null-device) 
    411                         (error nil)
    412                        1
    413                 (format "%s %s -e " grep-program required-options) 
    414               (format "%s %s " grep-program required-options))))) 
    415   (unless grep-find-use-xargs 
    416     (setq grep-find-use-xargs 
    417           (if (and 
    418                (equal (call-process "find" nil nil nil 
    419                                     null-device "-print0") 
    420                       0) 
    421                (equal (call-process "xargs" nil nil nil 
    422                                     "-0" "-e" "echo"
    423                       0)) 
    424               'gnu))) 
    425   (unless grep-find-command 
    426     (setq grep-find-command 
    427           (cond ((eq grep-find-use-xargs 'gnu) 
    428                  (format "%s . -type f -print0 | xargs -0 -e %s" 
    429                          find-program grep-command)) 
    430                 (grep-find-use-xargs 
    431                  (format "%s . -type f -print | xargs %s" 
    432                          find-program grep-command)) 
    433                 (t (cons (format "%s . -type f -exec %s {} %s \\;" 
    434                                  find-program grep-command null-device) 
    435                          (+ 22 (length grep-command))))))) 
    436   (unless grep-tree-command 
    437     (setq grep-tree-command 
    438           (let* ((glen (length grep-program)) 
    439                 (gcmd (concat grep-program " <C>" (substring grep-command glen)))) 
    440             (cond ((eq grep-find-use-xargs 'gnu) 
    441                    (format "%s <D> <X> -type f <F> -print0 | xargs -0 -e %s <R>
    442                            find-program gcmd)) 
    443                   (grep-find-use-xargs 
    444                    (format "%s <D> <X> -type f <F> -print | xargs %s <R>
    445                            find-program gcmd)) 
    446                   (t (format "%s <D> <X> -type f <F> -exec %s <R> {} %s \\;" 
    447                              find-program gcmd null-device)))))) 
     407  (unless (and grep-command grep-find-command 
     408               grep-template grep-find-template) 
     409    (let ((grep-options 
     410           (concat (if grep-use-null-device "-n" "-nH") 
     411                   (if (grep-probe grep-program 
     412                                   `(nil nil nil "-e" "foo" ,null-device) 
     413                                  nil 1
     414                       " -e")))
     415      (unless grep-command 
     416        (setq grep-command 
     417              (format "%s %s " grep-program grep-options))) 
     418      (unless grep-template 
     419        (setq grep-template 
     420              (format "%s <C> %s <R> <F>" grep-program grep-options))) 
     421      (unless grep-find-use-xargs 
     422        (setq grep-find-use-xargs 
     423              (if (and 
     424                  (grep-probe find-program `(nil nil nil ,null-device "-print0")
     425                   (grep-probe "xargs" `(nil nil nil "-0" "-e" "echo"))) 
     426                 'gnu))) 
     427      (unless grep-find-command 
     428       (setq grep-find-command 
     429             (cond ((eq grep-find-use-xargs 'gnu) 
     430                     (format "%s . -type f -print0 | xargs -0 -e %s" 
     431                             find-program grep-command)) 
     432                    (grep-find-use-xargs 
     433                     (format "%s . -type f -print | xargs %s" 
     434                            find-program grep-command)) 
     435                    (t (cons (format "%s . -type f -exec %s {} %s \\;" 
     436                                     find-program grep-command null-device) 
     437                             (+ 22 (length grep-command))))))) 
     438      (unless grep-find-template 
     439        (setq grep-find-template 
     440              (let ((gcmd (format "%s <C> %s <R>" 
     441                                 grep-program grep-options))) 
     442               (cond ((eq grep-find-use-xargs 'gnu) 
     443                       (format "%s . <X> -type f <F> -print0 | xargs -0 -e %s
     444                               find-program gcmd)) 
     445                      (grep-find-use-xargs 
     446                       (format "%s . <X> -type f <F> -print | xargs %s
     447                               find-program gcmd)) 
     448                      (t (format "%s . <X> -type f <F> -exec %s {} %s \\;" 
     449                                find-program gcmd null-device)))))))) 
    448450  (unless (or (not grep-highlight-matches) (eq grep-highlight-matches t)) 
    449451    (setq grep-highlight-matches 
    450452          (with-temp-buffer 
    451             (and (equal (condition-case nil 
    452                             (call-process grep-program nil t nil "--help") 
    453                           (error nil)) 
    454                         0) 
     453            (and (grep-probe grep-program '(nil t nil "--help")) 
    455454                 (progn 
    456455                   (goto-char (point-min)) 
     
    488487      (replace-match tag-default t t grep-default 1)))) 
    489488 
    490 ;;;###autoload 
    491 (defun grep (command-args &optional highlight-regexp) 
    492   "Run grep, with user-specified args, and collect output in a buffer. 
    493 While grep runs asynchronously, you can use \\[next-error] (M-x next-error), 
    494 or \\<grep-mode-map>\\[compile-goto-error] in the grep \ 
    495 output buffer, to go to the lines 
    496 where grep found matches. 
    497  
    498 This command uses a special history list for its COMMAND-ARGS, so you can 
    499 easily repeat a grep command. 
    500  
    501 A prefix argument says to default the argument based upon the current 
    502 tag the cursor is over, substituting it into the last grep command 
    503 in the grep command history (or into `grep-command' 
    504 if that history list is empty). 
    505  
    506 If specified, optional second arg HIGHLIGHT-REGEXP is the regexp to 
    507 temporarily highlight in visited source lines." 
    508   (interactive 
    509    (progn 
    510      (unless (and grep-command 
    511                   (or (not grep-use-null-device) (eq grep-use-null-device t))) 
    512        (grep-compute-defaults)) 
    513      (let ((default (grep-default-command))) 
    514        (list (read-from-minibuffer "Run grep (like this): " 
    515                                    (if current-prefix-arg 
    516                                        default grep-command) 
    517                                    nil nil 'grep-history 
    518                                    (if current-prefix-arg nil default)))))) 
    519  
    520   ;; Setting process-setup-function makes exit-message-function work 
    521   ;; even when async processes aren't supported. 
    522   (compilation-start (if (and grep-use-null-device null-device) 
    523                          (concat command-args " " null-device) 
    524                        command-args) 
    525                      'grep-mode nil highlight-regexp)) 
    526489 
    527490;;;###autoload 
     
    537500  (set (make-local-variable 'compilation-disable-input) t)) 
    538501 
     502 
     503;;;###autoload 
     504(defun grep (command-args) 
     505  "Run grep, with user-specified args, and collect output in a buffer. 
     506While grep runs asynchronously, you can use \\[next-error] (M-x next-error), 
     507or \\<grep-mode-map>\\[compile-goto-error] in the grep \ 
     508output buffer, to go to the lines 
     509where grep found matches. 
     510 
     511This command uses a special history list for its COMMAND-ARGS, so you can 
     512easily repeat a grep command. 
     513 
     514A prefix argument says to default the argument based upon the current 
     515tag the cursor is over, substituting it into the last grep command 
     516in the grep command history (or into `grep-command' 
     517if that history list is empty)." 
     518  (interactive 
     519   (progn 
     520     (grep-compute-defaults) 
     521     (let ((default (grep-default-command))) 
     522       (list (read-from-minibuffer "Run grep (like this): " 
     523                                   (if current-prefix-arg 
     524                                       default grep-command) 
     525                                   nil nil 'grep-history 
     526                                   (if current-prefix-arg nil default)))))) 
     527 
     528  ;; Setting process-setup-function makes exit-message-function work 
     529  ;; even when async processes aren't supported. 
     530  (compilation-start (if (and grep-use-null-device null-device) 
     531                         (concat command-args " " null-device) 
     532                       command-args) 
     533                     'grep-mode)) 
     534 
     535 
    539536;;;###autoload 
    540537(defun grep-find (command-args) 
     
    548545  (interactive 
    549546   (progn 
    550      (unless (and grep-command 
    551                   (or (not grep-use-null-device) (eq grep-use-null-device t))) 
    552        (grep-compute-defaults)) 
     547     (grep-compute-defaults) 
    553548     (if grep-find-command 
    554549         (list (read-from-minibuffer "Run find (like this): " 
     
    566561(defalias 'find-grep 'grep-find) 
    567562 
    568 (defun grep-expand-command-macros (command &optional regexp files dir excl case-fold) 
    569   "Patch grep COMMAND replacing <D>, etc." 
    570   (setq command 
    571         (replace-regexp-in-string "<D>" 
    572                                   (or dir ".") command t t)) 
    573   (setq command 
    574         (replace-regexp-in-string "<X>" 
    575                                   (or excl "") command t t)) 
    576   (setq command 
    577         (replace-regexp-in-string "<F>" 
    578                                   (or files "") command t t)) 
    579   (setq command 
    580         (replace-regexp-in-string "<C>" 
    581                                   (if case-fold "-i" "") command t t)) 
    582   (setq command 
    583         (replace-regexp-in-string "<R>" 
    584                                   (or regexp "") command t t)) 
    585   command) 
    586  
    587 (defvar grep-tree-last-regexp "") 
    588 (defvar grep-tree-last-files (car (car grep-tree-files-aliases))) 
    589  
    590 ;;;###autoload 
    591 (defun grep-tree (regexp files dir &optional subdirs) 
    592   "Grep for REGEXP in FILES in directory tree rooted at DIR. 
    593 Collect output in a buffer. 
    594 Interactively, prompt separately for each search parameter. 
    595 With prefix arg, reuse previous REGEXP. 
     563 
     564;; User-friendly interactive API. 
     565 
     566(defconst grep-expand-keywords 
     567  '(("<C>" . (and cf (isearch-no-upper-case-p regexp t) "-i")) 
     568    ("<D>" . dir) 
     569    ("<F>" . files) 
     570    ("<N>" . null-device) 
     571    ("<X>" . excl) 
     572    ("<R>" . (shell-quote-argument (or regexp "")))) 
     573  "List of substitutions performed by `grep-expand-template'. 
     574If car of an element matches, the cdr is evalled in to get the 
     575substitution string.  Note dynamic scoping of variables.") 
     576 
     577(defun grep-expand-template (template &optional regexp files dir excl) 
     578  "Patch grep COMMAND string replacing <C>, <D>, <F>, <R>, and <X>." 
     579  (let ((command template) 
     580        (cf case-fold-search) 
     581        (case-fold-search nil)) 
     582    (dolist (kw grep-expand-keywords command) 
     583      (if (string-match (car kw) command) 
     584          (setq command 
     585                (replace-match 
     586                 (or (if (symbolp (cdr kw)) 
     587                         (symbol-value (cdr kw)) 
     588                       (save-match-data (eval (cdr kw)))) 
     589                     "") 
     590                 t t command)))))) 
     591 
     592(defun grep-read-regexp () 
     593  "Read regexp arg for interactive grep." 
     594  (let ((default 
     595          (or (funcall (or find-tag-default-function 
     596                           (get major-mode 'find-tag-default-function) 
     597                           'find-tag-default)) 
     598              ""))) 
     599    (read-string 
     600     (concat "Search for" 
     601             (if (and default (> (length default) 0)) 
     602                 (format " (default %s): " default) ": ")) 
     603     nil 'grep-regexp-history default))) 
     604 
     605(defun grep-read-files (regexp) 
     606  "Read files arg for interactive grep." 
     607  (let* ((bn (or (buffer-file-name) (buffer-name))) 
     608         (fn (and bn 
     609                  (stringp bn) 
     610                  (file-name-nondirectory bn))) 
     611         (default 
     612           (or (and fn 
     613                    (let ((aliases grep-files-aliases) 
     614                          alias) 
     615                      (while aliases 
     616                        (setq alias (car aliases) 
     617                              aliases (cdr aliases)) 
     618                        (if (string-match (wildcard-to-regexp (cdr alias)) fn) 
     619                            (setq aliases nil) 
     620                          (setq alias nil))) 
     621                      (cdr alias))) 
     622               (and fn 
     623                    (let ((ext (file-name-extension fn))) 
     624                      (and ext (concat "*." ext)))))) 
     625         (files (read-string 
     626                 (concat "Search for \"" regexp 
     627                         "\" in files" 
     628                         (if default (concat " (default " default ")")) 
     629                         ": ") 
     630                 nil 'grep-files-history default))) 
     631    (and files 
     632         (or (cdr (assoc files grep-files-aliases)) 
     633             files)))) 
     634 
     635;;;###autoload 
     636(defun lgrep (regexp &optional files) 
     637  "Run grep, searching for REGEXP in FILES in current directory. 
    596638The search is limited to file names matching shell pattern FILES. 
    597 FILES may use abbreviations defined in `grep-tree-files-aliases', e.g. 
     639FILES may use abbreviations defined in `grep-files-aliases', e.g. 
    598640entering `ch' is equivalent to `*.[ch]'. 
    599641 
    600 While find runs asynchronously, you can use the \\[next-error] command 
    601 to find the text that grep hits refer to. 
    602  
    603 This command uses a special history list for its arguments, so you can 
    604 easily repeat a find command. 
    605  
    606 When used non-interactively, optional arg SUBDIRS limits the search to 
    607 those sub directories of DIR." 
     642With \\[universal-argument] prefix, allow user to edit the constructed 
     643shell command line before it is executed. 
     644With two \\[universal-argument] prefixes, edit and run grep shell command. 
     645 
     646Collect output in a buffer.  While grep runs asynchronously, you 
     647can use \\[next-error] (M-x next-error), or \\<grep-mode-map>\\[compile-goto-error] 
     648in the grep output buffer, to go to the lines where grep found matches. 
     649 
     650This command shares argument histories with \\[rgrep] and \\[grep]." 
    608651  (interactive 
    609    (let* ((regexp 
    610            (if current-prefix-arg 
    611                grep-tree-last-regexp 
    612              (let* ((default (current-word)) 
    613                     (spec (read-string 
    614                            (concat "Search for" 
    615                                    (if (and default (> (length default) 0)) 
    616                                        (format " (default %s): " default) ": "))))) 
    617                (if (equal spec "") default spec)))) 
    618           (files 
    619            (read-string (concat "Search for \"" regexp "\" in files (default "   grep-tree-last-files  "): "))) 
    620           (dir 
    621            (read-directory-name "Base directory: " nil default-directory t))) 
    622      (list regexp files dir))) 
    623   (unless grep-tree-command 
    624     (grep-compute-defaults)) 
    625   (unless (and (stringp files) (> (length files) 0)) 
    626     (setq files grep-tree-last-files)) 
    627   (when files 
    628     (setq grep-tree-last-files files) 
    629     (let ((mf (assoc files grep-tree-files-aliases))) 
    630       (if mf 
    631           (setq files (cdr mf))))) 
    632   (let ((command-args (grep-expand-command-macros 
    633                        grep-tree-command 
    634                        (setq grep-tree-last-regexp regexp) 
    635                        (and files (concat "-name '" files "'")) 
    636                        (if subdirs 
    637                            (if (stringp subdirs) 
    638                                subdirs 
    639                              (mapconcat 'identity subdirs " ")) 
    640                          nil)  ;; we change default-directory to dir 
    641                        (and grep-tree-ignore-CVS-directories "-path '*/CVS' -prune -o ") 
    642                        grep-tree-ignore-case)) 
    643         (default-directory (file-name-as-directory (expand-file-name dir))) 
    644         (null-device nil))              ; see grep 
    645     (grep command-args regexp))) 
     652   (progn 
     653     (grep-compute-defaults) 
     654     (cond 
     655      ((and grep-command (equal current-prefix-arg '(16))) 
     656       (list (read-from-minibuffer "Run: " grep-command 
     657                                   nil nil 'grep-history) 
     658             nil)) 
     659      ((not grep-template) 
     660       (list nil 
     661             (read-string "grep.el: No `grep-template' available. Press RET."))) 
     662      (t (let* ((regexp (grep-read-regexp)) 
     663                (files (grep-read-files regexp))) 
     664           (list regexp files)))))) 
     665  (when (and (stringp regexp) (> (length regexp) 0)) 
     666    (let ((command regexp)) 
     667      (if (null files) 
     668          (if (string= command grep-command) 
     669              (setq command nil)) 
     670        (setq command (grep-expand-template 
     671                       grep-template 
     672                       regexp 
     673                       files)) 
     674        (when command 
     675          (if (equal current-prefix-arg '(4)) 
     676              (setq command 
     677                    (read-from-minibuffer "Confirm: " 
     678                                          command nil nil 'grep-history)) 
     679            (push command grep-history)))) 
     680      (when command 
     681        ;; Setting process-setup-function makes exit-message-function work 
     682        ;; even when async processes aren't supported. 
     683        (compilation-start (if (and grep-use-null-device null-device) 
     684                               (concat command " " null-device) 
     685                             command) 'grep-mode))))) 
     686 
     687 
     688;;;###autoload 
     689(defun rgrep (regexp &optional files dir) 
     690  "Recusively grep for REGEXP in FILES in directory tree rooted at DIR. 
     691The search is limited to file names matching shell pattern FILES. 
     692FILES may use abbreviations defined in `grep-files-aliases', e.g. 
     693entering `ch' is equivalent to `*.[ch]'. 
     694 
     695With \\[universal-argument] prefix, allow user to edit the constructed 
     696shell command line before it is executed. 
     697With two \\[universal-argument] prefixes, edit and run grep-find shell command. 
     698 
     699Collect output in a buffer.  While find runs asynchronously, you 
     700can use \\[next-error] (M-x next-error), or \\<grep-mode-map>\\[compile-goto-error] 
     701in the grep output buffer, to go to the lines where grep found matches. 
     702 
     703This command shares argument histories with \\[lgrep] and \\[grep-find]." 
     704  (interactive 
     705   (progn 
     706     (grep-compute-defaults) 
     707     (cond 
     708      ((and grep-find-command (equal current-prefix-arg '(16))) 
     709       (list (read-from-minibuffer "Run: " grep-find-command 
     710                                   nil nil 'grep-find-history) 
     711             nil)) 
     712      ((not grep-find-template) 
     713       (list nil nil 
     714             (read-string "grep.el: No `grep-find-template' available. Press RET."))) 
     715      (t (let* ((regexp (grep-read-regexp)) 
     716                (files (grep-read-files regexp)) 
     717                (dir (read-directory-name "Base directory: " 
     718                                          nil default-directory t))) 
     719           (list regexp files dir)))))) 
     720  (when (and (stringp regexp) (> (length regexp) 0)) 
     721    (if (null files) 
     722        (if (not (string= regexp grep-find-command)) 
     723            (compilation-start regexp 'grep-mode)) 
     724      (let* ((default-directory (file-name-as-directory (expand-file-name dir))) 
     725             (command (grep-expand-template 
     726                       grep-find-template 
     727                       regexp 
     728                       (concat "\\( -name " 
     729                               (mapconcat #'shell-quote-argument 
     730                                          (split-string files) 
     731                                          " -o -name ") 
     732                               " \\)") 
     733                       default-directory 
     734                       (and grep-find-ignored-directories 
     735                            (concat "\\( -path '*/" 
     736                                    (mapconcat #'identity 
     737                                               grep-find-ignored-directories 
     738                                               "' -o -path '*/") 
     739                                    "' \\) -prune -o "))))) 
     740        (when command 
     741          (if current-prefix-arg 
     742              (setq command 
     743                    (read-from-minibuffer "Confirm: " 
     744                                          command nil nil 'grep-find-history)) 
     745            (push command grep-find-history)) 
     746          (compilation-start command 'grep-mode)))))) 
    646747 
    647748