Jens Petersen ce72b2
;;; igrep.el --- An improved interface to `grep` and `find`
Jens Petersen ce72b2
;;; -*-unibyte: t;-*-
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Copyright © 1993-1998,2000-2004 Kevin Rodgers
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Author: Kevin Rodgers <ihs_4664@yahoo.com>
Jens Petersen ce72b2
;; Created:  22 Jun 1993
Jens Petersen ce72b2
;; Version: 2.112
Jens Petersen ce72b2
;; Keywords: tools, processes, search
Jens Petersen ce72b2
;; SCCS: @(#)igrep.el	2.112
Jens Petersen ce72b2

Jens Petersen ce72b2
;; This program is free software; you can redistribute it and/or
Jens Petersen ce72b2
;; modify it under the terms of the GNU General Public License as
Jens Petersen ce72b2
;; published by the Free Software Foundation; either version 2 of
Jens Petersen ce72b2
;; the License, or (at your option) any later version.
Jens Petersen ce72b2

Jens Petersen ce72b2
;; This program is distributed in the hope that it will be
Jens Petersen ce72b2
;; useful, but WITHOUT ANY WARRANTY; without even the implied
Jens Petersen ce72b2
;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Jens Petersen ce72b2
;; PURPOSE.  See the GNU General Public License for more details.
Jens Petersen ce72b2

Jens Petersen ce72b2
;; You should have received a copy of the GNU General Public
Jens Petersen ce72b2
;; License along with this program; if not, write to the Free
Jens Petersen ce72b2
;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
Jens Petersen ce72b2
;; MA 02111-1307 USA
Jens Petersen ce72b2

Jens Petersen ce72b2
;;; Commentary:
Jens Petersen ce72b2

Jens Petersen ce72b2
;; The `igrep' command is like `grep' except that it takes three
Jens Petersen ce72b2
;; required arguments (PROGRAM, REGEX, and FILES) and an optional
Jens Petersen ce72b2
;; argument (OPTIONS) instead of just one argument (COMMAND).  The
Jens Petersen ce72b2
;; analogous `egrep' and `fgrep' commands are also defined for
Jens Petersen ce72b2
;; convenience.
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; The `igrep-find' command is like `igrep' except that it uses `find`
Jens Petersen ce72b2
;; to recursively `grep` a directory.  The analogous `egrep-find' and
Jens Petersen ce72b2
;; `fgrep-find' commands are also defined for convenience.
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; When called interactively, `igrep' and `igrep-find' (and their
Jens Petersen ce72b2
;; analogues) provide defaults for the REGEX and FILES arguments based
Jens Petersen ce72b2
;; on the current word and the visited file name (if the `igrep-regex-
Jens Petersen ce72b2
;; default' and `igrep-files-default' options are set, respectively).
Jens Petersen ce72b2
;; The `igrep-insert-default-key' option allows the default value to be
Jens Petersen ce72b2
;; inserted into the minibuffer for editing; since Emacs 20 provides
Jens Petersen ce72b2
;; that via the minibuffer history, it's only enabled for older
Jens Petersen ce72b2
;; versions by default. Other options that control the user interface
Jens Petersen ce72b2
;; are `igrep-insert-default-directory', `igrep-read-options', `igrep-
Jens Petersen ce72b2
;; read-multiple-files', `igrep-verbose-prompts', `igrep-save-buffers',
Jens Petersen ce72b2
;; and `igrep-menu-bar'.
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; Besides the basic `igrep-program' and `igrep-find-program' global
Jens Petersen ce72b2
;; variables, other variables control the syntax of the `grep` and
Jens Petersen ce72b2
;; `find` shell commands that are executed: `igrep-options', `igrep-
Jens Petersen ce72b2
;; regex-option', `igrep-case-fold-search', `igrep-find-prune-clause',
Jens Petersen ce72b2
;; `igrep-find-file-clause', and `igrep-find-use-xargs'.
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; The `igrep-use-zgrep' user option controls whether the corresponding
Jens Petersen ce72b2
;; GNU (gzip) "zPROGRAM" script is used, to `grep` compressed files.
Jens Petersen ce72b2
;; Special minibuffer history lists are maintained for the REGEX and
Jens Petersen ce72b2
;; FILES arguments.
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; The `agrep' and `agrep-find' commands are interfaces to the
Jens Petersen ce72b2
;; approximate `grep` utility, which is distributed with the `glimpse'
Jens Petersen ce72b2
;; indexing and query tool (available from http://www.tgries.de/agrep/).
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; `grep' itself can be advised to provide the `igrep' interface when
Jens Petersen ce72b2
;; it is invoked interactively (but still use the original argument
Jens Petersen ce72b2
;; list when it is called from Emacs Lisp), via the `igrep-insinuate'
Jens Petersen ce72b2
;; command.  `igrep-insinuate' also defines `grep-find' as an alias for
Jens Petersen ce72b2
;; `igrep-find', `dired-do-grep' and `dired-do-grep-find' as aliases
Jens Petersen ce72b2
;; for `dired-do-igrep' and `dired-do-igrep-find', and `Buffer-menu-
Jens Petersen ce72b2
;; grep' as an alias for `Buffer-menu-igrep'.
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; When run interactively from Dired mode, the various `igrep' commands
Jens Petersen ce72b2
;; provide defaults for the REGEX and FILES arguments that are based on
Jens Petersen ce72b2
;; the visited directory (including any inserted subdirectories) and
Jens Petersen ce72b2
;; the current file.  The alternative `dired-do-igrep' and `dired-do-
Jens Petersen ce72b2
;; igrep-find' commands respect the `dired-do-*' command conventions: a
Jens Petersen ce72b2
;; prefix argument is interpreted as the number of succeeding files to
Jens Petersen ce72b2
;; `grep`, otherwise all the marked files are `grep`ed.
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; The `igrep-visited-files' command provides a simple way to `grep`
Jens Petersen ce72b2
;; just those files that are being visited in buffers.  The `Buffer-
Jens Petersen ce72b2
;; menu-igrep' command does the same thing, for buffers marked for
Jens Petersen ce72b2
;; selection in Buffer Menu mode.
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Installation:
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; 1. Put this file in a directory that is a member of load-path, and
Jens Petersen ce72b2
;;    byte-compile it (e.g. with `M-x byte-compile-file') for better
Jens Petersen ce72b2
;;    performance.  You can ignore any warnings about references to free
Jens Petersen ce72b2
;;    variables and "not known to be defined" functions.
Jens Petersen ce72b2
;; 2. Put these forms in default.el or ~/.emacs:
Jens Petersen ce72b2
;;    (autoload 'igrep "igrep"
Jens Petersen ce72b2
;;       "*Run `grep` PROGRAM to match REGEX in FILES..." t)
Jens Petersen ce72b2
;;    (autoload 'igrep-find "igrep"
Jens Petersen ce72b2
;;       "*Run `grep` via `find`..." t)
Jens Petersen ce72b2
;;    (autoload 'igrep-visited-files "igrep"
Jens Petersen ce72b2
;;       "*Run `grep` ... on all visited files." t)
Jens Petersen ce72b2
;;    (autoload 'dired-do-igrep "igrep"
Jens Petersen ce72b2
;;       "*Run `grep` on the marked (or next prefix ARG) files." t)
Jens Petersen ce72b2
;;    (autoload 'dired-do-igrep-find "igrep"
Jens Petersen ce72b2
;;       "*Run `grep` via `find` on the marked (or next prefix ARG) directories." t)
Jens Petersen ce72b2
;;    (autoload 'Buffer-menu-igrep "igrep"
Jens Petersen ce72b2
;;      "*Run `grep` on the files visited in buffers marked with '>'." t)
Jens Petersen ce72b2
;;    (autoload 'igrep-insinuate "igrep"
Jens Petersen ce72b2
;;      "Define `grep' aliases for the corresponding `igrep' commands." t)
Jens Petersen ce72b2
;; 2. a. For completeness, you can add these forms as well:
Jens Petersen ce72b2
;;    (autoload 'grep "igrep"
Jens Petersen ce72b2
;;       "*Run `grep` PROGRAM to match REGEX in FILES..." t)
Jens Petersen ce72b2
;;    (autoload 'egrep "igrep"
Jens Petersen ce72b2
;;       "*Run `egrep`..." t)
Jens Petersen ce72b2
;;    (autoload 'fgrep "igrep"
Jens Petersen ce72b2
;;       "*Run `fgrep`..." t)
Jens Petersen ce72b2
;;    (autoload 'agrep "igrep"
Jens Petersen ce72b2
;;       "*Run `agrep`..." t)
Jens Petersen ce72b2
;;    (autoload 'grep-find "igrep"
Jens Petersen ce72b2
;;       "*Run `grep` via `find`..." t)
Jens Petersen ce72b2
;;    (autoload 'egrep-find "igrep"
Jens Petersen ce72b2
;;       "*Run `egrep` via `find`..." t)
Jens Petersen ce72b2
;;    (autoload 'fgrep-find "igrep"
Jens Petersen ce72b2
;;       "*Run `fgrep` via `find`..." t)
Jens Petersen ce72b2
;;    (autoload 'agrep-find "igrep"
Jens Petersen ce72b2
;;       "*Run `agrep` via `find`..." t)
Jens Petersen ce72b2
;; 3. If you are running Windows 95/NT, you should install findutils
Jens Petersen ce72b2
;;    and grep from release 17.1 (or higher) of the Cygnus GNU-Win32
Jens Petersen ce72b2
;;    distribution (http://www.cygnus.com/misc/gnu-win32/).
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Usage:
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; These igrep commands accept 1, 2, or 3 `C-u' prefix arguments:
Jens Petersen ce72b2
;; 	M-x igrep		M-x igrep-find
Jens Petersen ce72b2
;; 	M-x  grep		M-x  grep-find	[after `M-x igrep-insinuate']
Jens Petersen ce72b2
;; 	M-x egrep		M-x egrep-find
Jens Petersen ce72b2
;; 	M-x fgrep		M-x fgrep-find
Jens Petersen ce72b2
;; 	M-x agrep		M-x agrep-find
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; These igrep commands accept a single `C-u' prefix argument:
Jens Petersen ce72b2
;; 	M-x igrep-visited-files
Jens Petersen ce72b2
;; 	M-x Buffer-menu-igrep	[in the *Buffer List* buffer]
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; These igrep commands interpret a prefix argument like the Emacs
Jens Petersen ce72b2
;; `dired-do-*' commands:
Jens Petersen ce72b2
;; 	M-x dired-do-igrep	M-x dired-do-igrep-find
Jens Petersen ce72b2
;; 	M-x  dired-do-grep	M-x  dired-do-grep-find	[after `M-x
Jens Petersen ce72b2
;; 							 igrep-insinuate']
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; These Emacs commands can be used after any igrep command:
Jens Petersen ce72b2
;; 	C-x ` (M-x next-error)
Jens Petersen ce72b2
;; 	C-c C-c (M-x compile-goto-error)	[in the *igrep* buffer]
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Customization examples:
Jens Petersen ce72b2
;; 
Jens Petersen ce72b2
;; To ignore case by default:
Jens Petersen ce72b2
;; 	(setq igrep-options "-i")
Jens Petersen ce72b2
;; or:
Jens Petersen ce72b2
;; 	(setq igrep-case-fold-search t)
Jens Petersen ce72b2
;; To search subdirectories by default:
Jens Petersen ce72b2
;; 	(setq igrep-find t)
Jens Petersen ce72b2
;; To search files with the GNU (gzip) zgrep script:
Jens Petersen ce72b2
;; 	(setq igrep-use-zgrep t)
Jens Petersen ce72b2
;; or define new igrep commands (this works for zegrep and zfgrep as well):
Jens Petersen ce72b2
;; 	(igrep-define zgrep)		; M-x zgrep
Jens Petersen ce72b2
;; 	(igrep-find-define zgrep)	; M-x zgrep-find
Jens Petersen ce72b2
;; To search "*.[ch]" files by default in C mode:
Jens Petersen ce72b2
;; 	(put 'igrep-files-default 'c-mode
Jens Petersen ce72b2
;; 	     (lambda () "*.[ch]"))
Jens Petersen ce72b2
;; To disable the default search regex and/or files pattern, except for
Jens Petersen ce72b2
;; specific modes:
Jens Petersen ce72b2
;; 	(setq igrep-regex-default 'ignore)
Jens Petersen ce72b2
;; 	(setq igrep-files-default 'ignore)
Jens Petersen ce72b2
;; To avoid exceeding some shells' limit on command argument length
Jens Petersen ce72b2
;; (this only searches files in the current directory):
Jens Petersen ce72b2
;; 	(setq igrep-find t
Jens Petersen ce72b2
;; 	      igrep-find-prune-clause "-type d \\! -name .")
Jens Petersen ce72b2

Jens Petersen ce72b2
;; To do:
Jens Petersen ce72b2
;; 1. Replace igrep-options with a table that maps igrep-program
Jens Petersen ce72b2
;;    to the appropriate options, and/or support POSIX (egrep -> `grep -E`).
Jens Petersen ce72b2
;; 2. Generalize support for the -prune find clause (e.g. -fstype nfs).
Jens Petersen ce72b2
;; 3. Provide support for `glimpse`.
Jens Petersen ce72b2

Jens Petersen ce72b2
;;; Code:
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Package interface:
Jens Petersen ce72b2

Jens Petersen ce72b2
(require 'custom)			; defgroup, defcustom
Jens Petersen ce72b2

Jens Petersen ce72b2
(require 'easymenu)			; easy-menu-define, easy-menu-add-item
Jens Petersen ce72b2

Jens Petersen ce72b2
(or (condition-case nil
Jens Petersen ce72b2
	(require 'grep)			; CVS Emacs (21.3.50/21.4)
Jens Petersen ce72b2
      (error nil))
Jens Petersen ce72b2
    (require 'compile))			; compile-internal, grep-regexp-alist,
Jens Petersen ce72b2
					; grep-null-device
Jens Petersen ce72b2

Jens Petersen ce72b2
(eval-when-compile
Jens Petersen ce72b2
  (require 'dired)			; dired-directory,
Jens Petersen ce72b2
					; dired-get-filename,
Jens Petersen ce72b2
					; dired-current-directory,
Jens Petersen ce72b2
					; dired-get-marked-files,
Jens Petersen ce72b2
					; dired-mark-get-files
Jens Petersen ce72b2
  (or (featurep 'ange-ftp)
Jens Petersen ce72b2
      (featurep 'efs)
Jens Petersen ce72b2
      (condition-case nil
Jens Petersen ce72b2
	  (load-library "ange-ftp")	; ange-ftp-ftp-name
Jens Petersen ce72b2
	(error nil))
Jens Petersen ce72b2
      (condition-case nil
Jens Petersen ce72b2
	  (load-library "efs")		; efs-ftp-path
Jens Petersen ce72b2
	(error nil)))
Jens Petersen ce72b2
  )
Jens Petersen ce72b2

Jens Petersen ce72b2
(defconst igrep-version "2.112"
Jens Petersen ce72b2
  "This version of igrep.el.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defgroup igrep nil
Jens Petersen ce72b2
  "An improved interface to `grep` and `find`."
Jens Petersen ce72b2
  :group 'compilation)
Jens Petersen ce72b2

Jens Petersen ce72b2
;; User options:
Jens Petersen ce72b2

Jens Petersen ce72b2
(defcustom igrep-options nil
Jens Petersen ce72b2
  "*The options passed by `\\[igrep]' to `igrep-program', or nil.
Jens Petersen ce72b2

Jens Petersen ce72b2
\"-n\" will automatically be passed to `igrep-program', to generate the
Jens Petersen ce72b2
output expected by `\\[next-error]' and `\\[compile-goto-error]'.
Jens Petersen ce72b2
\"-e\" will automatically be passed to `igrep-program', if it supports
Jens Petersen ce72b2
that option."
Jens Petersen ce72b2
  :group 'igrep
Jens Petersen ce72b2
  :type '(choice (const nil) (string)))
Jens Petersen ce72b2
(put 'igrep-options 'variable-interactive
Jens Petersen ce72b2
     "xOptions (\"-xyz\" or nil): ")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defcustom igrep-case-fold-search nil
Jens Petersen ce72b2
  "*If non-nil, `\\[igrep]' ignores case unless REGEX has uppercase letters."
Jens Petersen ce72b2
  :group 'igrep
Jens Petersen ce72b2
  :type '(boolean))
Jens Petersen ce72b2
(put 'igrep-case-fold-search 'variable-interactive
Jens Petersen ce72b2
     "XIgnore case? (t or nil): ")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defcustom igrep-read-options nil
Jens Petersen ce72b2
  "*If non-nil, `\\[igrep]' always prompts for options;
Jens Petersen ce72b2
otherwise, it only prompts when 1 or 3 `C-u's are given as a prefix arg."
Jens Petersen ce72b2
  :group 'igrep
Jens Petersen ce72b2
  :type '(boolean))
Jens Petersen ce72b2
(put 'igrep-read-options 'variable-interactive
Jens Petersen ce72b2
     "XAlways prompt for options? (t or nil): ")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defcustom igrep-read-multiple-files nil
Jens Petersen ce72b2
  "*If non-nil, `\\[igrep]' always prompts for multiple-files;
Jens Petersen ce72b2
otherwise, it only prompts when 2 or 3 `C-u's are given as a prefix arg."
Jens Petersen ce72b2
  :group 'igrep
Jens Petersen ce72b2
  :type '(boolean))
Jens Petersen ce72b2
(put 'igrep-read-multiple-files 'variable-interactive
Jens Petersen ce72b2
     "XAlways prompt for multiple files? (t or nil): ")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defcustom igrep-regex-default 'current-word
Jens Petersen ce72b2
  "*If non-nil, a function that returns a default REGEX for `\\[igrep]'.
Jens Petersen ce72b2
The function is called with no arguments and should return a string (or nil).
Jens Petersen ce72b2

Jens Petersen ce72b2
A different function can be specified for any particular mode by specifying
Jens Petersen ce72b2
a value for that `major-mode' property; for example:
Jens Petersen ce72b2
	(put 'igrep-regex-default 'dired-mode
Jens Petersen ce72b2
	     'igrep-dired-file-current-word)"
Jens Petersen ce72b2
  :group 'igrep
Jens Petersen ce72b2
  :type '(choice (const nil) (function)))
Jens Petersen ce72b2
(put 'igrep-regex-default 'variable-interactive
Jens Petersen ce72b2
     "SProvide a default regex? (function or nil): ")
Jens Petersen ce72b2
(put 'igrep-regex-default 'dired-mode
Jens Petersen ce72b2
     'igrep-dired-file-current-word)
Jens Petersen ce72b2

Jens Petersen ce72b2
(defcustom igrep-files-default 'igrep-buffer-file-name-pattern
Jens Petersen ce72b2
  "*If non-nil, a function that returns the default FILES for `\\[igrep]'.
Jens Petersen ce72b2
The function is called with no arguments and should return a string,
Jens Petersen ce72b2
or a list of strings (or nil).
Jens Petersen ce72b2

Jens Petersen ce72b2
A different function can be specified for any particular mode by specifying
Jens Petersen ce72b2
a value for that `major-mode' property; for example:
Jens Petersen ce72b2
	(put 'igrep-files-default 'dired-mode
Jens Petersen ce72b2
	     'igrep-dired-directory-file-pattern)"
Jens Petersen ce72b2
  :group 'igrep
Jens Petersen ce72b2
  :type '(choice (const nil) (function)))
Jens Petersen ce72b2
(put 'igrep-files-default 'variable-interactive
Jens Petersen ce72b2
     "SProvide a default file name pattern? (function or nil): ")
Jens Petersen ce72b2
(put 'igrep-files-default 'dired-mode
Jens Petersen ce72b2
     'igrep-dired-directory-file-pattern)
Jens Petersen ce72b2

Jens Petersen ce72b2
(defcustom igrep-verbose-prompts t
Jens Petersen ce72b2
  "*If t, `\\[igrep]' prompts for arguments verbosely;
Jens Petersen ce72b2
if not t but non-nil, `\\[igrep]' prompts for arguments semi-verbosely;
Jens Petersen ce72b2
if nil, `\\[igrep]' prompts for arguments tersely."
Jens Petersen ce72b2
  :group 'igrep
Jens Petersen ce72b2
  :type '(choice (const :tag "Verbose" t)
Jens Petersen ce72b2
		 (other :tag "Semi-verbose" semi)
Jens Petersen ce72b2
		 (const :tag "Terse" nil)))
Jens Petersen ce72b2
(put 'igrep-verbose-prompts 'variable-interactive
Jens Petersen ce72b2
     "XPrompt verbosely? (t, 'semi, or nil): ")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defcustom igrep-insert-default-directory nil
Jens Petersen ce72b2
  "*The value of `insert-default-directory' for `\\[igrep]'."
Jens Petersen ce72b2
  :group 'igrep
Jens Petersen ce72b2
  :type '(boolean))
Jens Petersen ce72b2
(put 'igrep-insert-default-directory 'variable-interactive
Jens Petersen ce72b2
     "XPrompt with directory in the minibuffer? (t or nil): ")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defcustom igrep-insert-default-key
Jens Petersen ce72b2
  (if (< emacs-major-version 20) "\C-c\C-e")
Jens Petersen ce72b2
  "*The key used to insert the default argument in the minibuffer.
Jens Petersen ce72b2
In Emacs 20, the default is available via the minibuffer history \
Jens Petersen ce72b2
\(\\<minibuffer-local-map>\\[next-history-element])."
Jens Petersen ce72b2
  :group 'igrep
Jens Petersen ce72b2
  :type '(choice (const nil) (string) (vector))) ; key-binding
Jens Petersen ce72b2
(put 'igrep-insert-default-key 'variable-interactive
Jens Petersen ce72b2
     "kSet key to insert the default `\\[igrep]' argument in the minibuffer: ")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defcustom igrep-save-buffers 'query
Jens Petersen ce72b2
  "*If t, `\\[igrep]' first saves each modified file buffer;
Jens Petersen ce72b2
if not t but non-nil, `\\[igrep]' offers to save each modified file buffer."
Jens Petersen ce72b2
  :group 'igrep
Jens Petersen ce72b2
  :type '(choice (const :tag "Save" t)
Jens Petersen ce72b2
		 (other :tag "Query" query)
Jens Petersen ce72b2
		 (const :tag "Don't Save" nil)))
Jens Petersen ce72b2
(put 'igrep-save-buffers 'variable-interactive
Jens Petersen ce72b2
     "XSave modified buffers? (t, 'query, or nil): ")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defcustom igrep-menu-bar t
Jens Petersen ce72b2
  "*If non-nil, enable the `igrep-menu' submenu on the \"Tools\" menu bar."
Jens Petersen ce72b2
  :group 'igrep
Jens Petersen ce72b2
  :type '(boolean))
Jens Petersen ce72b2
(put 'igrep-menu-bar 'variable-interactive
Jens Petersen ce72b2
     "XEnable menu bar? (t or nil): ")
Jens Petersen ce72b2

Jens Petersen ce72b2
;; User variables:
Jens Petersen ce72b2

Jens Petersen ce72b2
(defsubst igrep-easy-menu-item (name callback help-keyword help-text)
Jens Petersen ce72b2
  "Return a [NAME CALLBACK HELP-KEYWORD HELP-TEXT] menu item.
Jens Petersen ce72b2
See `easy-menu-define'."
Jens Petersen ce72b2
  (if (featurep 'xemacs)                ; no :help keyword
Jens Petersen ce72b2
      (vector name callback)
Jens Petersen ce72b2
    (vector name callback help-keyword help-text)))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar :help ':help)			; Emacs 19
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-easy-menu
Jens Petersen ce72b2
  `("Search Files and Directories (igrep)"
Jens Petersen ce72b2
    ,@(cond ((featurep 'xemacs) '(:included igrep-menu-bar))
Jens Petersen ce72b2
	    ((>= emacs-major-version 20) '(:active igrep-menu-bar))
Jens Petersen ce72b2
	    (t ()))
Jens Petersen ce72b2
    ("Search files"
Jens Petersen ce72b2
     ,(igrep-easy-menu-item "`grep` files..." 'igrep
Jens Petersen ce72b2
                            :help "Search files for basic regex(5)s")
Jens Petersen ce72b2
     ,(igrep-easy-menu-item "`egrep` files..." 'egrep
Jens Petersen ce72b2
                            :help "Search files for extended regex(5)s")
Jens Petersen ce72b2
     ,(igrep-easy-menu-item "`fgrep` files..." 'fgrep
Jens Petersen ce72b2
                            :help "Search files for strings"))
Jens Petersen ce72b2
    ("Search directories"
Jens Petersen ce72b2
     ,(igrep-easy-menu-item "`find | grep` directories..." 'igrep-find
Jens Petersen ce72b2
                            :help "Search directories for basic regex(5)s")
Jens Petersen ce72b2
     ,(igrep-easy-menu-item "`find | egrep` directories..." 'egrep-find
Jens Petersen ce72b2
                            :help "Search directories for extended regex(5)s")
Jens Petersen ce72b2
     ,(igrep-easy-menu-item "`find | fgrep` directories..." 'fgrep-find
Jens Petersen ce72b2
                            :help "Search directories for strings"))
Jens Petersen ce72b2
    "--"
Jens Petersen ce72b2
    ,(igrep-easy-menu-item "Search visited files..." 'igrep-visited-files
Jens Petersen ce72b2
                           :help "Search visited files for basic regex(5)s"))
Jens Petersen ce72b2
  "If non-nil, the menu bar submenu of `igrep' commands.
Jens Petersen ce72b2
See `easy-menu-define'.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-null-device
Jens Petersen ce72b2
  (cond ((boundp 'null-device) null-device) ; Emacs 20
Jens Petersen ce72b2
	((boundp 'grep-null-device) grep-null-device)) ; Emacs 19
Jens Petersen ce72b2
  "The system null device.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-program "grep"
Jens Petersen ce72b2
  "The default program run by `\\[igrep]' and `\\[igrep-find]'.
Jens Petersen ce72b2
It must accept a `grep` regex argument and one or more file names, plus
Jens Petersen ce72b2
the \"-n\" option.  If nil, `\\[igrep]' prompts for the program to run.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-regex-option
Jens Petersen ce72b2
  (if (equal (call-process igrep-program nil nil nil
Jens Petersen ce72b2
			   "-e" "foo" igrep-null-device)
Jens Petersen ce72b2
	     1)
Jens Petersen ce72b2
      "-e")
Jens Petersen ce72b2
  "If non-nil, the option used to specify the REGEX argument to `\\[igrep]'.
Jens Petersen ce72b2
This protects an initial \"-\" from option processing.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-program-table		; referenced by igrep-use-zgrep
Jens Petersen ce72b2
  (let ((exec-directories exec-path)
Jens Petersen ce72b2
	(program-obarray (make-vector 11 0)))
Jens Petersen ce72b2
    (while exec-directories
Jens Petersen ce72b2
      (if (and (car exec-directories)
Jens Petersen ce72b2
	       (file-directory-p (car exec-directories))
Jens Petersen ce72b2
	       (file-readable-p (car exec-directories)))
Jens Petersen ce72b2
	  (let ((grep-programs
Jens Petersen ce72b2
		 (directory-files (car exec-directories)
Jens Petersen ce72b2
				  nil "grep\\(\\.exe\\)?\\'")))
Jens Petersen ce72b2
	    (while grep-programs
Jens Petersen ce72b2
	      ;; Check `(file-executable-p (car grep-programs))'?
Jens Petersen ce72b2
	      (if (save-match-data
Jens Petersen ce72b2
		    (string-match "\\.exe\\'" (car grep-programs)))
Jens Petersen ce72b2
		  (intern (substring (car grep-programs) 0 -4) program-obarray)
Jens Petersen ce72b2
		(intern (car grep-programs) program-obarray))
Jens Petersen ce72b2
	      (setq grep-programs (cdr grep-programs)))))
Jens Petersen ce72b2
      (setq exec-directories (cdr exec-directories)))
Jens Petersen ce72b2
    program-obarray)
Jens Petersen ce72b2
  "An obarray of available `grep` programs.
Jens Petersen ce72b2
This is passed by `igrep-read-program' to `completing-read' when
Jens Petersen ce72b2
`igrep-program' is nil.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-use-zgrep
Jens Petersen ce72b2
  (if (intern-soft "zgrep" igrep-program-table)
Jens Petersen ce72b2
      'files)
Jens Petersen ce72b2
  "If t, `\\[igrep]' searches files using the GNU (gzip) `zPROGRAM` script;
Jens Petersen ce72b2
If not t but non-nil, `\\[igrep]' searches compressed FILES using `zPROGRAM`;
Jens Petersen ce72b2
if nil, `\\[igrep]' searches files with `PROGRAM`.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-find nil
Jens Petersen ce72b2
  "If non-nil, `\\[igrep]' searches directories using `find`.
Jens Petersen ce72b2
See `igrep-find'.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-find-program "find"
Jens Petersen ce72b2
  "The program run by `\\[igrep-find]'.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-find-prune-clause
Jens Petersen ce72b2
  (if (equal (call-process igrep-find-program nil nil nil
Jens Petersen ce72b2
			   igrep-null-device "-prune")
Jens Petersen ce72b2
	     0)
Jens Petersen ce72b2
      (format "-type d %s -name RCS -o -name CVS -o -name SCCS %s"
Jens Petersen ce72b2
	      (shell-quote-argument "(")
Jens Petersen ce72b2
	      (shell-quote-argument ")")))
Jens Petersen ce72b2
  "The `find` clause used to prune directories, or nil;
Jens Petersen ce72b2
see `igrep-find'.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-find-file-clause
Jens Petersen ce72b2
  (format "-type f %s -name %s %s -name %s %s -name %s %s -name %s" ; -type l
Jens Petersen ce72b2
	  (shell-quote-argument "!")
Jens Petersen ce72b2
	  (shell-quote-argument "*~")	; Emacs backup
Jens Petersen ce72b2
	  (shell-quote-argument "!")
Jens Petersen ce72b2
	  (shell-quote-argument "*,v")	; RCS file
Jens Petersen ce72b2
	  (shell-quote-argument "!")
Jens Petersen ce72b2
	  (shell-quote-argument "s.*")	; SCCS file
Jens Petersen ce72b2
	  (shell-quote-argument "!")
Jens Petersen ce72b2
	  (shell-quote-argument ".#*"))	; CVS file
Jens Petersen ce72b2
  "The `find` clause used to filter files passed to `grep`, or nil;
Jens Petersen ce72b2
see `igrep-find'.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-find-use-xargs
Jens Petersen ce72b2
  (cond ((equal (call-process igrep-find-program nil nil nil
Jens Petersen ce72b2
			      igrep-null-device "-print0")
Jens Petersen ce72b2
		0)
Jens Petersen ce72b2
	 'gnu)
Jens Petersen ce72b2
	((not (equal system-type 'darwin)))) ; not MacOS
Jens Petersen ce72b2
  "Whether `\\[igrep-find]' uses the `xargs` program or not.
Jens Petersen ce72b2
If `gnu', it executes
Jens Petersen ce72b2
	`find ... -print0 | xargs -0 -e grep ...`;
Jens Petersen ce72b2
if not `gnu' but non-nil, it executes
Jens Petersen ce72b2
	`find ... -print | xargs -e grep ...`;
Jens Petersen ce72b2
if nil, it executes
Jens Petersen ce72b2
	`find ... -exec grep ...`.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-program-default "grep"
Jens Petersen ce72b2
  "The default `grep` program.
Jens Petersen ce72b2
This is passed by `igrep-read-program' to `completing-read' when
Jens Petersen ce72b2
`igrep-program' is nil.")
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Internal variables:
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-regex-history '()
Jens Petersen ce72b2
  "The minibuffer history list for `\\[igrep]'s REGEX argument.")
Jens Petersen ce72b2

Jens Petersen ce72b2
(defvar igrep-files-history '()
Jens Petersen ce72b2
  "The minibuffer history list for `\\[igrep]'s FILES argument.")
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Commands:
Jens Petersen ce72b2

Jens Petersen ce72b2
;;;###autoload
Jens Petersen ce72b2
(defun igrep-insinuate (&optional override)
Jens Petersen ce72b2
  "Define `grep' aliases for the corresponding `igrep' commands.
Jens Petersen ce72b2
With a prefix arg, OVERRIDE the current `grep' command definitions."
Jens Petersen ce72b2
  (interactive "P")
Jens Petersen ce72b2
  (if override
Jens Petersen ce72b2
      (defalias 'grep 'igrep)
Jens Petersen ce72b2
    (defadvice grep (around igrep-interactive first (&rest command-args)
Jens Petersen ce72b2
			    activate)
Jens Petersen ce72b2
      "If called interactively, use the `\\[igrep]' interface instead,
Jens Petersen ce72b2
where COMMAND-ARGS is (PROGRAM REGEX FILES [OPTIONS]); if called
Jens Petersen ce72b2
programmatically, COMMAND-ARGS is still (COMMAND)."
Jens Petersen ce72b2
      (interactive (igrep-read-args))
Jens Petersen ce72b2
      (if (interactive-p)
Jens Petersen ce72b2
	  (apply 'igrep command-args)
Jens Petersen ce72b2
	ad-do-it)))
Jens Petersen ce72b2
  (if (or (not (fboundp 'grep-find))
Jens Petersen ce72b2
	  override)
Jens Petersen ce72b2
      (defalias 'grep-find 'igrep-find))
Jens Petersen ce72b2
  (if (or (not (fboundp 'dired-do-grep))
Jens Petersen ce72b2
	  override)
Jens Petersen ce72b2
      (defalias 'dired-do-grep 'dired-do-igrep))
Jens Petersen ce72b2
  (if (or (not (fboundp 'dired-do-grep-find))
Jens Petersen ce72b2
	  override)
Jens Petersen ce72b2
      (defalias 'dired-do-grep-find 'dired-do-igrep-find))
Jens Petersen ce72b2
  (if (or (not (fboundp 'Buffer-menu-grep))
Jens Petersen ce72b2
	  override)
Jens Petersen ce72b2
      (defalias 'Buffer-menu-grep 'Buffer-menu-igrep)))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defsubst igrep-quote-file-name (file)
Jens Petersen ce72b2
  "Quote FILE name pattern for `shell-file-name'."
Jens Petersen ce72b2
  (if (fboundp 'shell-quote-wildcard-pattern) ; Emacs 21
Jens Petersen ce72b2
      (shell-quote-wildcard-pattern file)
Jens Petersen ce72b2
    (shell-quote-argument file)))
Jens Petersen ce72b2

Jens Petersen ce72b2
;;;###autoload
Jens Petersen ce72b2
(defun igrep (program regex files &optional options)
Jens Petersen ce72b2
  "*Run `grep` PROGRAM to match REGEX in FILES.
Jens Petersen ce72b2
The output is displayed in the *igrep* buffer, which `\\[next-error]' and
Jens Petersen ce72b2
`\\[compile-goto-error]' parse to find each line of matched text.
Jens Petersen ce72b2

Jens Petersen ce72b2
PROGRAM may be nil, in which case it defaults to `igrep-program'.
Jens Petersen ce72b2

Jens Petersen ce72b2
REGEX is automatically quoted by `shell-quote-argument'.
Jens Petersen ce72b2

Jens Petersen ce72b2
FILES is either a file name pattern (automatically quoted by
Jens Petersen ce72b2
`shell-quote-wildcard-pattern', then expanded by the `shell-file-name' shell),
Jens Petersen ce72b2
or a list of file name patterns.
Jens Petersen ce72b2

Jens Petersen ce72b2
Optional OPTIONS is also passed to PROGRAM; it defaults to `igrep-options'.
Jens Petersen ce72b2

Jens Petersen ce72b2
If a prefix argument \
Jens Petersen ce72b2
\(`\\[universal-argument]') \
Jens Petersen ce72b2
is given when called interactively,
Jens Petersen ce72b2
or if `igrep-read-options' is set, OPTIONS is read from the minibuffer.
Jens Petersen ce72b2

Jens Petersen ce72b2
If two prefix arguments \
Jens Petersen ce72b2
\(`\\[universal-argument] \\[universal-argument]') \
Jens Petersen ce72b2
are given when called interactively,
Jens Petersen ce72b2
or if `igrep-read-multiple-files' is set, FILES is read from the minibuffer
Jens Petersen ce72b2
multiple times.
Jens Petersen ce72b2

Jens Petersen ce72b2
If three prefix arguments \
Jens Petersen ce72b2
\(`\\[universal-argument] \\[universal-argument] \\[universal-argument]') \
Jens Petersen ce72b2
are given when called interactively,
Jens Petersen ce72b2
or if `igrep-read-options' and `igrep-read-multiple-files' are set,
Jens Petersen ce72b2
OPTIONS is read and FILES is read multiple times.
Jens Petersen ce72b2

Jens Petersen ce72b2
If `igrep-find' is non-nil, the directory or directories
Jens Petersen ce72b2
containing FILES is recursively searched for files whose name matches
Jens Petersen ce72b2
the file name component of FILES (and whose contents match REGEX)."
Jens Petersen ce72b2
  (interactive
Jens Petersen ce72b2
   (igrep-read-args))
Jens Petersen ce72b2
  (if (null program)
Jens Petersen ce72b2
      (setq program (or igrep-program "grep")))
Jens Petersen ce72b2
  (if (null options)
Jens Petersen ce72b2
      (setq options igrep-options))
Jens Petersen ce72b2
  (if (not (listp files))		; (stringp files)
Jens Petersen ce72b2
      (setq files (list files)))
Jens Petersen ce72b2
  (if (and (member ?~ (mapcar 'string-to-char files))
Jens Petersen ce72b2
	   (save-match-data
Jens Petersen ce72b2
	     (string-match "\\`[rj]?sh\\(\\.exe\\)?\\'"
Jens Petersen ce72b2
			   (file-name-nondirectory shell-file-name))))
Jens Petersen ce72b2
      ;; (restricted, job-control, or standard) Bourne shell doesn't expand ~:
Jens Petersen ce72b2
      (setq files
Jens Petersen ce72b2
	    (mapcar 'expand-file-name files)))
Jens Petersen ce72b2
  (let* ((use-zgrep (cond ((eq igrep-use-zgrep t))
Jens Petersen ce72b2
			  (igrep-use-zgrep
Jens Petersen ce72b2
			   (let ((files files)
Jens Petersen ce72b2
				 (compressed-p nil))
Jens Petersen ce72b2
			     (while (and files (not compressed-p))
Jens Petersen ce72b2
			       (if (save-match-data
Jens Petersen ce72b2
				     (string-match "\\.g?[zZ]\\'" (car files)))
Jens Petersen ce72b2
				   (setq compressed-p t))
Jens Petersen ce72b2
			       (setq files (cdr files)))
Jens Petersen ce72b2
			     compressed-p))
Jens Petersen ce72b2
			  (t nil)))
Jens Petersen ce72b2
	 (command (format "%s -n %s %s %s %s %s"
Jens Petersen ce72b2
			  (if (and use-zgrep
Jens Petersen ce72b2
				   (save-match-data
Jens Petersen ce72b2
				     (not (string-match "\\`z" program))))
Jens Petersen ce72b2
			      (setq program (concat "z" program))
Jens Petersen ce72b2
			    program)
Jens Petersen ce72b2
			  (or options
Jens Petersen ce72b2
			      (and igrep-case-fold-search
Jens Petersen ce72b2
				   (equal regex (downcase regex))
Jens Petersen ce72b2
				   "-i")
Jens Petersen ce72b2
			      "")
Jens Petersen ce72b2
			  (or igrep-regex-option
Jens Petersen ce72b2
			      (progn
Jens Petersen ce72b2
				(if (save-match-data
Jens Petersen ce72b2
				      (string-match "\\`-" regex))
Jens Petersen ce72b2
				    (setq regex (concat "\\" regex)))
Jens Petersen ce72b2
				""))
Jens Petersen ce72b2
			  (shell-quote-argument regex)
Jens Petersen ce72b2
			  (if igrep-find
Jens Petersen ce72b2
			      (if igrep-find-use-xargs
Jens Petersen ce72b2
				  ""
Jens Petersen ce72b2
				(shell-quote-argument "{}"))
Jens Petersen ce72b2
			    (mapconcat (lambda (file)
Jens Petersen ce72b2
					 (let ((dir (file-name-directory file)))
Jens Petersen ce72b2
					   (if dir
Jens Petersen ce72b2
					       (expand-file-name
Jens Petersen ce72b2
						(file-name-nondirectory file)
Jens Petersen ce72b2
						(igrep-quote-file-name dir))
Jens Petersen ce72b2
					     file)))
Jens Petersen ce72b2
				       files " "))
Jens Petersen ce72b2
			  igrep-null-device)))
Jens Petersen ce72b2
    (if igrep-find
Jens Petersen ce72b2
	(setq command
Jens Petersen ce72b2
	      (igrep-format-find-command command files)))
Jens Petersen ce72b2
    (cond ((eq igrep-save-buffers t) (save-some-buffers t))
Jens Petersen ce72b2
	  (igrep-save-buffers (save-some-buffers)))
Jens Petersen ce72b2
    (if (fboundp 'compilation-start)    ; CVS Emacs (21.3.50/21.4)
Jens Petersen ce72b2
        (let ((compilation-process-setup-function 'grep-process-setup))
Jens Petersen ce72b2
          (or (fboundp 'igrep-mode)
Jens Petersen ce72b2
              (define-derived-mode igrep-mode grep-mode "Igrep"))
Jens Petersen ce72b2
          (compilation-start command
Jens Petersen ce72b2
                             'igrep-mode
Jens Petersen ce72b2
                             nil
Jens Petersen ce72b2
                             (cond ((eq compilation-highlight-regexp t))
Jens Petersen ce72b2
                                   (compilation-highlight-regexp
Jens Petersen ce72b2
                                    (if (eq program "fgrep")
Jens Petersen ce72b2
                                        (regexp-quote regex)
Jens Petersen ce72b2
                                      regex)))))
Jens Petersen ce72b2
      (compile-internal command (format "No more %s matches" program)
Jens Petersen ce72b2
                        "Igrep" nil grep-regexp-alist))))
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Analogue commands:
Jens Petersen ce72b2

Jens Petersen ce72b2
(defmacro igrep-define (analogue-command &rest igrep-bindings)
Jens Petersen ce72b2
  "Define ANALOGUE-COMMAND as an `igrep' analogue command.
Jens Petersen ce72b2
Optional (VARIABLE VALUE) arguments specify the temporary IGREP-BINDINGS
Jens Petersen ce72b2
for the command."
Jens Petersen ce72b2
  ;; (interactive "SCommand: ") ; C-u => read bindings?
Jens Petersen ce72b2
  (let ((analogue-program (symbol-name analogue-command)))
Jens Petersen ce72b2
    `(defun ,analogue-command (&rest igrep-args)
Jens Petersen ce72b2
       ,(format "*Run `%s` via `\\[igrep]'.
Jens Petersen ce72b2
All arguments (including prefix arguments, when called interactively)
Jens Petersen ce72b2
are handled by `igrep'."
Jens Petersen ce72b2
		analogue-program)
Jens Petersen ce72b2
       (interactive
Jens Petersen ce72b2
	(let ((igrep-program (if igrep-program ,analogue-program))
Jens Petersen ce72b2
	      (igrep-program-default ,analogue-program))
Jens Petersen ce72b2
	  (igrep-read-args)))
Jens Petersen ce72b2
       (let (,@ igrep-bindings)
Jens Petersen ce72b2
	 (apply 'igrep
Jens Petersen ce72b2
		(cond ((interactive-p) (car igrep-args))
Jens Petersen ce72b2
		      ((car igrep-args))
Jens Petersen ce72b2
		      (t ,analogue-program))
Jens Petersen ce72b2
		(cdr igrep-args))))))
Jens Petersen ce72b2

Jens Petersen ce72b2
(igrep-define egrep)
Jens Petersen ce72b2
(igrep-define fgrep)
Jens Petersen ce72b2
(igrep-define agrep
Jens Petersen ce72b2
  (igrep-use-zgrep nil)
Jens Petersen ce72b2
  (igrep-regex-option "-e"))
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Recursive (`find`) commands:
Jens Petersen ce72b2

Jens Petersen ce72b2
;;;###autoload
Jens Petersen ce72b2
(defun igrep-find (&rest igrep-args)
Jens Petersen ce72b2
  "*Run `grep` via `find`; see `igrep' and `igrep-find'.
Jens Petersen ce72b2
All IGREP-ARGS (including prefix arguments, when called interactively)
Jens Petersen ce72b2
are handled by `igrep'."
Jens Petersen ce72b2
  (interactive
Jens Petersen ce72b2
   (let ((igrep-find t))
Jens Petersen ce72b2
     (igrep-read-args)))
Jens Petersen ce72b2
  (let ((igrep-find t))
Jens Petersen ce72b2
    (apply 'igrep igrep-args)))
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Analogue recursive (`find`) commands:
Jens Petersen ce72b2

Jens Petersen ce72b2
(defmacro igrep-find-define (analogue-command &rest igrep-bindings)
Jens Petersen ce72b2
  "Define ANALOGUE-COMMAND-find as an `igrep' analogue `find` command.
Jens Petersen ce72b2
Optional (VARIABLE VALUE) arguments specify the temporary IGREP-BINDINGS
Jens Petersen ce72b2
for the command."
Jens Petersen ce72b2
  ;; (interactive "SCommand: ") ; C-u => read bindings?
Jens Petersen ce72b2
  (let ((analogue-program (symbol-name analogue-command)))
Jens Petersen ce72b2
    (setq analogue-command
Jens Petersen ce72b2
	  (intern (format "%s-find" analogue-command)))
Jens Petersen ce72b2
    `(defun ,analogue-command (&rest igrep-args)
Jens Petersen ce72b2
       ,(format "*Run `%s` via `\\[igrep-find]'.
Jens Petersen ce72b2
All arguments (including prefix arguments, when called interactively)
Jens Petersen ce72b2
are handled by `igrep'."
Jens Petersen ce72b2
		analogue-program)
Jens Petersen ce72b2
       (interactive
Jens Petersen ce72b2
	(let ((igrep-program (if igrep-program ,analogue-program))
Jens Petersen ce72b2
	      (igrep-program-default ,analogue-program)
Jens Petersen ce72b2
	      (igrep-find t))
Jens Petersen ce72b2
	  (igrep-read-args)))
Jens Petersen ce72b2
       (let (,@ igrep-bindings)
Jens Petersen ce72b2
	 (apply 'igrep-find
Jens Petersen ce72b2
		(cond ((interactive-p) (car igrep-args))
Jens Petersen ce72b2
		      ((car igrep-args))
Jens Petersen ce72b2
		      (t ,analogue-program))
Jens Petersen ce72b2
		(cdr igrep-args))))))
Jens Petersen ce72b2

Jens Petersen ce72b2
(igrep-find-define egrep)
Jens Petersen ce72b2
(igrep-find-define fgrep)
Jens Petersen ce72b2
(igrep-find-define agrep
Jens Petersen ce72b2
  (igrep-use-zgrep nil)
Jens Petersen ce72b2
  (igrep-regex-option "-e"))
Jens Petersen ce72b2

Jens Petersen ce72b2
;;;###autoload
Jens Petersen ce72b2
(defun igrep-visited-files (program regex &optional options)
Jens Petersen ce72b2
  "*Run `grep` PROGRAM to match REGEX (with optional OPTIONS) \
Jens Petersen ce72b2
on all visited files.
Jens Petersen ce72b2
See `\\[igrep]'."
Jens Petersen ce72b2
  (interactive
Jens Petersen ce72b2
   (let ((igrep-args (igrep-read-args 'no-files)))
Jens Petersen ce72b2
     ;; Delete FILES:
Jens Petersen ce72b2
     (setcdr (nthcdr 1 igrep-args) (nthcdr 3 igrep-args))
Jens Petersen ce72b2
     igrep-args))
Jens Petersen ce72b2
  (igrep program regex
Jens Petersen ce72b2
	 (let ((directory-abbrev-alist
Jens Petersen ce72b2
		(cons (cons (regexp-quote (expand-file-name default-directory))
Jens Petersen ce72b2
			    "./")	; or even ""
Jens Petersen ce72b2
		      directory-abbrev-alist)))
Jens Petersen ce72b2
	   (mapcar 'abbreviate-file-name
Jens Petersen ce72b2
		   (apply 'nconc
Jens Petersen ce72b2
			  (mapcar (lambda (buffer)
Jens Petersen ce72b2
				    (let ((file (buffer-file-name buffer)))
Jens Petersen ce72b2
				      (if (and file
Jens Petersen ce72b2
					       (cond ((featurep 'ange-ftp)
Jens Petersen ce72b2
						      (not (ange-ftp-ftp-name file)))
Jens Petersen ce72b2
						     ((featurep 'efs)
Jens Petersen ce72b2
						      (not (efs-ftp-path file)))
Jens Petersen ce72b2
						     (t t))
Jens Petersen ce72b2
					       ;; (file-exists-p file)
Jens Petersen ce72b2
					       )
Jens Petersen ce72b2
					  (list file))))
Jens Petersen ce72b2
				  (buffer-list)))))
Jens Petersen ce72b2
	 options))
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Dired commands:
Jens Petersen ce72b2

Jens Petersen ce72b2
;;;###autoload
Jens Petersen ce72b2
(defun dired-do-igrep (program regex &optional options arg)
Jens Petersen ce72b2
  "*Search the marked (or next prefix ARG) files.
Jens Petersen ce72b2
See `\\[igrep]' for a description of PROGRAM, REGEX, and OPTIONS."
Jens Petersen ce72b2
  (interactive
Jens Petersen ce72b2
   (let ((igrep-args
Jens Petersen ce72b2
	  (let ((current-prefix-arg nil))
Jens Petersen ce72b2
	    (igrep-read-args 'no-files))))
Jens Petersen ce72b2
     ;; Delete FILES:
Jens Petersen ce72b2
     (setcdr (nthcdr 1 igrep-args) (nthcdr 3 igrep-args))
Jens Petersen ce72b2
     ;; Append ARG:
Jens Petersen ce72b2
     (nconc igrep-args (list current-prefix-arg))))
Jens Petersen ce72b2
  (igrep program regex
Jens Petersen ce72b2
	 (funcall (cond ((fboundp 'dired-get-marked-files) ; GNU Emacs
Jens Petersen ce72b2
			 'dired-get-marked-files)
Jens Petersen ce72b2
			((fboundp 'dired-mark-get-files) ; XEmacs
Jens Petersen ce72b2
			 'dired-mark-get-files))
Jens Petersen ce72b2
		  t arg)
Jens Petersen ce72b2
	 options))
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Dired recursive (`find`) commands:
Jens Petersen ce72b2

Jens Petersen ce72b2
;;;###autoload
Jens Petersen ce72b2
(defun dired-do-igrep-find (program regex &optional options arg)
Jens Petersen ce72b2
  "*Run `grep` on the marked (or next prefix ARG) directories.
Jens Petersen ce72b2
See `\\[igrep]' for a description of PROGRAM, REGEX, and OPTIONS."
Jens Petersen ce72b2
  (interactive
Jens Petersen ce72b2
   (let ((igrep-args
Jens Petersen ce72b2
	  (let ((current-prefix-arg nil)
Jens Petersen ce72b2
		(igrep-find t))
Jens Petersen ce72b2
	    (igrep-read-args 'no-files))))
Jens Petersen ce72b2
     ;; Delete FILES:
Jens Petersen ce72b2
     (setcdr (nthcdr 1 igrep-args) (nthcdr 3 igrep-args))
Jens Petersen ce72b2
     ;; Append ARG:
Jens Petersen ce72b2
     (nconc igrep-args (list current-prefix-arg))))
Jens Petersen ce72b2
  (let ((igrep-find t))
Jens Petersen ce72b2
    (dired-do-igrep program regex options arg)))
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Buffer menu commands:
Jens Petersen ce72b2

Jens Petersen ce72b2
;;;###autoload
Jens Petersen ce72b2
(defun Buffer-menu-igrep (program regex &optional options)
Jens Petersen ce72b2
  "*Run `grep` on the files visited in buffers marked with '>'.
Jens Petersen ce72b2
See `\\[igrep]' for a description of PROGRAM, REGEX, and OPTIONS."
Jens Petersen ce72b2
  (interactive
Jens Petersen ce72b2
   (let ((igrep-args (igrep-read-args 'no-files)))
Jens Petersen ce72b2
     ;; Delete FILES:
Jens Petersen ce72b2
     (setcdr (nthcdr 1 igrep-args) (nthcdr 3 igrep-args))
Jens Petersen ce72b2
     igrep-args))
Jens Petersen ce72b2
  ;; See Buffer-menu-select:
Jens Petersen ce72b2
  (let ((marked-files '())
Jens Petersen ce72b2
	marked-buffer
Jens Petersen ce72b2
	file)
Jens Petersen ce72b2
    (goto-char (point-min))
Jens Petersen ce72b2
    (while (search-forward "\n>" nil t)
Jens Petersen ce72b2
      (setq marked-buffer (Buffer-menu-buffer t)
Jens Petersen ce72b2
	    file (buffer-file-name marked-buffer))
Jens Petersen ce72b2
      (if (and file
Jens Petersen ce72b2
	       ;; local:
Jens Petersen ce72b2
	       (cond ((featurep 'ange-ftp)
Jens Petersen ce72b2
		      (not (ange-ftp-ftp-name file)))
Jens Petersen ce72b2
		     ((featurep 'efs)
Jens Petersen ce72b2
		      (not (efs-ftp-path file)))
Jens Petersen ce72b2
		     (t t)))
Jens Petersen ce72b2
	  (setq marked-files (cons file marked-files)))
Jens Petersen ce72b2
;;;    (let ((buffer-read-only nil))
Jens Petersen ce72b2
;;;      (delete-char -1)
Jens Petersen ce72b2
;;;      (insert ?\ ))
Jens Petersen ce72b2
      )
Jens Petersen ce72b2
    (setq marked-files (nreverse marked-files))
Jens Petersen ce72b2
    (igrep program regex
Jens Petersen ce72b2
	   (let ((directory-abbrev-alist
Jens Petersen ce72b2
		  (cons (cons (regexp-quote (expand-file-name default-directory))
Jens Petersen ce72b2
			      "./")	; or even ""
Jens Petersen ce72b2
			directory-abbrev-alist)))
Jens Petersen ce72b2
	     (mapcar 'abbreviate-file-name marked-files))
Jens Petersen ce72b2
	   options)))
Jens Petersen ce72b2

Jens Petersen ce72b2
;; User functions:
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-dired-file-current-word ()
Jens Petersen ce72b2
  "Return the current word in the file on this line, if it is visible;
Jens Petersen ce72b2
else, return the file name on this line, if there is one;
Jens Petersen ce72b2
otherwise, return the current word."
Jens Petersen ce72b2
  (let* ((dired-file
Jens Petersen ce72b2
	  (dired-get-filename t t))
Jens Petersen ce72b2
	 (dired-file-buffer
Jens Petersen ce72b2
	  (if dired-file
Jens Petersen ce72b2
	      (get-file-buffer (expand-file-name dired-file))))
Jens Petersen ce72b2
	 (dired-file-buffer-window
Jens Petersen ce72b2
	  (if dired-file-buffer
Jens Petersen ce72b2
	      (get-buffer-window dired-file-buffer))))
Jens Petersen ce72b2
    (cond (dired-file-buffer-window (save-excursion
Jens Petersen ce72b2
				      (set-buffer dired-file-buffer)
Jens Petersen ce72b2
				      (current-word)))
Jens Petersen ce72b2
	  (dired-file)
Jens Petersen ce72b2
	  (t (current-word)))))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-buffer-file-name-pattern ()
Jens Petersen ce72b2
  "Return a shell file name pattern based on the visited file name.
Jens Petersen ce72b2
If the `buffer-file-name' variable is nil, return \"*\"."
Jens Petersen ce72b2
  ;; (Based on other-possibly-interesting-files in ~/as-is/unix.el, by
Jens Petersen ce72b2
  ;; Wolfgang Rupprecht <wolfgang@mgm.mit.edu>.)
Jens Petersen ce72b2
  (if buffer-file-name
Jens Petersen ce72b2
      (let ((file-name (file-name-nondirectory buffer-file-name)))
Jens Petersen ce72b2
	(concat "*"
Jens Petersen ce72b2
		(save-match-data
Jens Petersen ce72b2
		  (if (string-match "\\.[^.]+\\(\\.g?[zZ]\\)?\\'"
Jens Petersen ce72b2
				    file-name)
Jens Petersen ce72b2
		      (substring file-name (match-beginning 0)
Jens Petersen ce72b2
				 (match-end 0))))))
Jens Petersen ce72b2
    "*"))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-dired-directory-file-pattern ()
Jens Petersen ce72b2
  "Return a shell file name pattern based on `dired-directory', or \"*\"."
Jens Petersen ce72b2
  (cond ((stringp dired-directory)
Jens Petersen ce72b2
	 (if (file-directory-p dired-directory)
Jens Petersen ce72b2
	     "*"
Jens Petersen ce72b2
	   (file-name-nondirectory dired-directory))) ; wildcard
Jens Petersen ce72b2
	((consp dired-directory)	; (DIR FILE ...)
Jens Petersen ce72b2
	 (mapconcat 'identity (cdr dired-directory) " "))))
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Utilities:
Jens Petersen ce72b2

Jens Petersen ce72b2
(defsubst igrep-file-directory (name)
Jens Petersen ce72b2
  "Return the directory component of NAME, or \".\" if it has none."
Jens Petersen ce72b2
  (directory-file-name (or (file-name-directory name)
Jens Petersen ce72b2
			   (file-name-as-directory "."))))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defsubst igrep-file-pattern (name)
Jens Petersen ce72b2
  "Return the file component of NAME, or \"*\" if it has none."
Jens Petersen ce72b2
  (let ((pattern (file-name-nondirectory name)))
Jens Petersen ce72b2
       (if (string= pattern "")
Jens Petersen ce72b2
	   "*"
Jens Petersen ce72b2
	 pattern)))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-format-find-command (command files)
Jens Petersen ce72b2
  "Format `grep` COMMAND to be invoked via `find` on FILES."
Jens Petersen ce72b2
  (let ((directories '())
Jens Petersen ce72b2
	(patterns '()))
Jens Petersen ce72b2
    (while files
Jens Petersen ce72b2
      (let ((dir (igrep-file-directory (car files)))
Jens Petersen ce72b2
	    (pat (igrep-file-pattern (car files))))
Jens Petersen ce72b2
	(if (and (not (string= dir "."))
Jens Petersen ce72b2
		 (file-symlink-p dir))
Jens Petersen ce72b2
	    (setq dir (concat dir "/.")))
Jens Petersen ce72b2
	(if (not (member dir directories))
Jens Petersen ce72b2
	    (setq directories (cons dir directories)))
Jens Petersen ce72b2
	(cond ((equal pat "*")
Jens Petersen ce72b2
	       (setq patterns t))
Jens Petersen ce72b2
	      ((and (listp patterns)
Jens Petersen ce72b2
		    (not (member pat patterns)))
Jens Petersen ce72b2
	       (setq patterns (cons pat patterns)))))
Jens Petersen ce72b2
      (setq files (cdr files)))
Jens Petersen ce72b2
    (format (cond ((eq igrep-find-use-xargs 'gnu)
Jens Petersen ce72b2
		   ;; | \\\n
Jens Petersen ce72b2
		   "%s %s %s %s %s -print0 | xargs -0 -e %s")
Jens Petersen ce72b2
		  (igrep-find-use-xargs
Jens Petersen ce72b2
		   ;; | \\\n
Jens Petersen ce72b2
		   "%s %s %s %s %s -print | xargs -e %s")
Jens Petersen ce72b2
		  (t
Jens Petersen ce72b2
		   "%s %s %s %s %s -exec %s %s"))
Jens Petersen ce72b2
	    igrep-find-program
Jens Petersen ce72b2
	    (mapconcat 'igrep-quote-file-name (nreverse directories)
Jens Petersen ce72b2
		       " ")
Jens Petersen ce72b2
	    (if igrep-find-prune-clause
Jens Petersen ce72b2
		(format "%s -prune -o" igrep-find-prune-clause)
Jens Petersen ce72b2
	      "")
Jens Petersen ce72b2
	    (or igrep-find-file-clause "")
Jens Petersen ce72b2
	    (if (listp patterns)
Jens Petersen ce72b2
		(if (cdr patterns)	; (> (length patterns) 1)
Jens Petersen ce72b2
		    (format "%s %s %s"
Jens Petersen ce72b2
			    (shell-quote-argument "(")
Jens Petersen ce72b2
			    (mapconcat (lambda (pat)
Jens Petersen ce72b2
					 (format "-name %s"
Jens Petersen ce72b2
						 (shell-quote-argument pat)))
Jens Petersen ce72b2
				       (nreverse patterns)
Jens Petersen ce72b2
				       " -o ")
Jens Petersen ce72b2
			    (shell-quote-argument ")"))
Jens Petersen ce72b2
		  (format "-name %s" (shell-quote-argument (car patterns))))
Jens Petersen ce72b2
	      "")
Jens Petersen ce72b2
	    command
Jens Petersen ce72b2
	    (shell-quote-argument ";")
Jens Petersen ce72b2
	    )))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defmacro igrep-default-arg (variable)
Jens Petersen ce72b2
  "Return the default arg based on VARIABLE."
Jens Petersen ce72b2
  `(if ,variable
Jens Petersen ce72b2
       (cond ((get (quote ,variable) major-mode)
Jens Petersen ce72b2
	      (funcall (get (quote ,variable) major-mode)))
Jens Petersen ce72b2
	     (t (funcall ,variable)))))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-default-regex ()
Jens Petersen ce72b2
  "Return the default REGEX for `\\[igrep]'."
Jens Petersen ce72b2
  (let ((default-regex (igrep-default-arg igrep-regex-default)))
Jens Petersen ce72b2
    (if (not (equal default-regex ""))
Jens Petersen ce72b2
	default-regex)))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-default-files ()
Jens Petersen ce72b2
  "Return the default FILES for `\\[igrep]'."
Jens Petersen ce72b2
  (let* ((dired-subdirectory (if (cond ((fboundp 'derived-mode-p) ; Emacs 21
Jens Petersen ce72b2
					(derived-mode-p 'dired-mode))
Jens Petersen ce72b2
				       (t (eq major-mode 'dired-mode)))
Jens Petersen ce72b2
				 (dired-current-directory t)))
Jens Petersen ce72b2
	 (default-files (igrep-default-arg igrep-files-default)))
Jens Petersen ce72b2
    (if (not (listp default-files))	; stringp
Jens Petersen ce72b2
	(setq default-files (list default-files)))
Jens Petersen ce72b2
    (if dired-subdirectory
Jens Petersen ce72b2
	(mapcar (lambda (file)
Jens Petersen ce72b2
		  (concat dired-subdirectory file))
Jens Petersen ce72b2
		default-files)
Jens Petersen ce72b2
      default-files)))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defsubst igrep-prefix (prefix string &rest strings)
Jens Petersen ce72b2
  "Concatenate PREFIX (if non-nil), STRING, and any other STRINGS."
Jens Petersen ce72b2
  (if (or prefix strings)
Jens Petersen ce72b2
      (apply 'concat prefix string strings)
Jens Petersen ce72b2
    string))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-read-args (&optional no-files)
Jens Petersen ce72b2
  "Read and return a list: (PROGRAM REGEX FILES OPTIONS).
Jens Petersen ce72b2
If NO-FILES is non-nil, then FILES is not read and nil is returned
Jens Petersen ce72b2
in its place."
Jens Petersen ce72b2
  (let* ((pre-prefix (if (and igrep-find (eq igrep-verbose-prompts t))
Jens Petersen ce72b2
			 "[find] "))
Jens Petersen ce72b2
	 (program
Jens Petersen ce72b2
	  (igrep-read-program pre-prefix))
Jens Petersen ce72b2
	 (prefix (if (and program (eq igrep-verbose-prompts t))
Jens Petersen ce72b2
		     (igrep-prefix pre-prefix program " ")
Jens Petersen ce72b2
		   pre-prefix))
Jens Petersen ce72b2
	 (options
Jens Petersen ce72b2
	  (igrep-read-options prefix))
Jens Petersen ce72b2
	 (post-prefix (if (and options (eq igrep-verbose-prompts t))
Jens Petersen ce72b2
			    (igrep-prefix prefix options " ")
Jens Petersen ce72b2
			  prefix)))
Jens Petersen ce72b2
    (list program
Jens Petersen ce72b2
	  (igrep-read-regex post-prefix)
Jens Petersen ce72b2
	  (if (not no-files)
Jens Petersen ce72b2
	      (igrep-read-files post-prefix))
Jens Petersen ce72b2
	  options)))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-read-program (&optional prompt-prefix)
Jens Petersen ce72b2
  "Read and return a `grep` program name from the minibuffer.
Jens Petersen ce72b2
If `igrep-program' is non-nil, it.
Jens Petersen ce72b2

Jens Petersen ce72b2
Optional PROMPT-PREFIX is prepended to the \"Program: \" prompt."
Jens Petersen ce72b2
  (or igrep-program
Jens Petersen ce72b2
      (let ((prompt "Program: "))
Jens Petersen ce72b2
	(completing-read (igrep-prefix prompt-prefix prompt) igrep-program-table
Jens Petersen ce72b2
			 nil t igrep-program-default))))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-read-options (&optional prompt-prefix)
Jens Petersen ce72b2
  "Read and return an options string from the minibuffer.
Jens Petersen ce72b2
If `current-prefix-arg' is '(4) or '(64), return `igrep-options'.
Jens Petersen ce72b2

Jens Petersen ce72b2
Optional PROMPT-PREFIX is prepended to the \"Options: \" prompt."
Jens Petersen ce72b2
  (if (or igrep-read-options
Jens Petersen ce72b2
	  (and (consp current-prefix-arg)
Jens Petersen ce72b2
	       (memq (prefix-numeric-value current-prefix-arg)
Jens Petersen ce72b2
		     '(4 64))))
Jens Petersen ce72b2
      (let ((prompt "Options: "))
Jens Petersen ce72b2
	(read-string (igrep-prefix prompt-prefix prompt)
Jens Petersen ce72b2
		     (or igrep-options "-")))
Jens Petersen ce72b2
    igrep-options))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-read-regex (&optional prompt-prefix)
Jens Petersen ce72b2
  "Read and return a `grep` regex(5) string from the minibuffer.
Jens Petersen ce72b2
Optional PROMPT-PREFIX is prepended to the \"Regex: \" prompt."
Jens Petersen ce72b2
  (if igrep-insert-default-key
Jens Petersen ce72b2
      (define-key minibuffer-local-map igrep-insert-default-key
Jens Petersen ce72b2
	'igrep-insert-default-regex))
Jens Petersen ce72b2
  (let* ((default-regex (igrep-default-regex))
Jens Petersen ce72b2
	 (prompt (igrep-prefix prompt-prefix
Jens Petersen ce72b2
			       (if default-regex
Jens Petersen ce72b2
				   (format "Regex [default: %s]: "
Jens Petersen ce72b2
					   default-regex)
Jens Petersen ce72b2
				 "Regex: ")))
Jens Petersen ce72b2
	 (regex (cond ((featurep 'xemacs) ; incompatible
Jens Petersen ce72b2
                       ;; DEFAULT-VALUE is the 7th arg in 21.4 (but 21.1
Jens Petersen ce72b2
                       ;; only accepts 6 args):
Jens Petersen ce72b2
		       (read-from-minibuffer prompt
Jens Petersen ce72b2
					     nil nil nil
Jens Petersen ce72b2
					     'igrep-regex-history
Jens Petersen ce72b2
					     nil)) ; ABBREV-TABLE
Jens Petersen ce72b2
		      ((>= emacs-major-version 20)
Jens Petersen ce72b2
		       (read-from-minibuffer prompt
Jens Petersen ce72b2
					     nil nil nil
Jens Petersen ce72b2
					     'igrep-regex-history
Jens Petersen ce72b2
					     default-regex))
Jens Petersen ce72b2
		      (t
Jens Petersen ce72b2
		       (read-from-minibuffer prompt
Jens Petersen ce72b2
					     nil nil nil
Jens Petersen ce72b2
					     'igrep-regex-history)))))
Jens Petersen ce72b2
    (if (equal regex "")
Jens Petersen ce72b2
	(progn
Jens Petersen ce72b2
	  (or (equal default-regex (car igrep-regex-history))
Jens Petersen ce72b2
	      (setq igrep-regex-history
Jens Petersen ce72b2
		    (cons default-regex igrep-regex-history)))
Jens Petersen ce72b2
	  default-regex)
Jens Petersen ce72b2
      regex)))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-insert-default-regex (&optional clear-minibuffer)
Jens Petersen ce72b2
  "*Insert the default regex in the minibuffer.
Jens Petersen ce72b2
If a prefix argument is specified, CLEAR-MINIBUFFER contents first."
Jens Petersen ce72b2
  (interactive "P")
Jens Petersen ce72b2
  (if clear-minibuffer
Jens Petersen ce72b2
      (delete-region (if (fboundp 'minibuffer-prompt-end) ; Emacs 21
Jens Petersen ce72b2
			 (minibuffer-prompt-end)
Jens Petersen ce72b2
		       (point-min))
Jens Petersen ce72b2
		     (point-max)))
Jens Petersen ce72b2
  (insert (or (save-excursion
Jens Petersen ce72b2
		(set-buffer (window-buffer minibuffer-scroll-window))
Jens Petersen ce72b2
		(igrep-default-regex))
Jens Petersen ce72b2
	      "")))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-insert-default-files (&optional clear-minibuffer)
Jens Petersen ce72b2
  "*Insert the default files in the minibuffer.
Jens Petersen ce72b2
If a prefix argument is specified, CLEAR-MINIBUFFER contents first."
Jens Petersen ce72b2
  (interactive "P")
Jens Petersen ce72b2
  (if clear-minibuffer
Jens Petersen ce72b2
      (delete-region (if (fboundp 'minibuffer-prompt-end) ; Emacs 21
Jens Petersen ce72b2
			 (minibuffer-prompt-end)
Jens Petersen ce72b2
		       (point-min))
Jens Petersen ce72b2
		     (point-max)))
Jens Petersen ce72b2
  (insert (mapconcat 'identity
Jens Petersen ce72b2
		     (save-excursion
Jens Petersen ce72b2
		       (set-buffer (window-buffer minibuffer-scroll-window))
Jens Petersen ce72b2
		       (igrep-default-files))
Jens Petersen ce72b2
		     " ")))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defsubst igrep-default-key (command &optional keymap key)
Jens Petersen ce72b2
  "Return the key bound to COMMAND in KEYMAP, preferably KEY."
Jens Petersen ce72b2
  (if (null keymap)
Jens Petersen ce72b2
      (setq keymap (current-global-map)))
Jens Petersen ce72b2
  (if (and key
Jens Petersen ce72b2
	   (eq (lookup-key keymap key) command))
Jens Petersen ce72b2
      key
Jens Petersen ce72b2
    (where-is-internal command keymap t)))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-read-files (&optional prompt-prefix)
Jens Petersen ce72b2
  "Read and return a file name pattern from the minibuffer.
Jens Petersen ce72b2
If `current-prefix-arg' is '(16) or '(64), read multiple file name
Jens Petersen ce72b2
patterns and return them in a list.  Optional PROMPT-PREFIX is
Jens Petersen ce72b2
prepended to the \"File(s): \" prompt."
Jens Petersen ce72b2
  (let* ((default-files (igrep-default-files))
Jens Petersen ce72b2
	 (default-files-string (mapconcat 'identity default-files " "))
Jens Petersen ce72b2
	 (insert-default-directory igrep-insert-default-directory)
Jens Petersen ce72b2
	 (file (igrep-read-file-name
Jens Petersen ce72b2
		(igrep-prefix prompt-prefix
Jens Petersen ce72b2
			      (if default-files
Jens Petersen ce72b2
				  (format "File(s) [default: %s]: "
Jens Petersen ce72b2
					  default-files-string)
Jens Petersen ce72b2
				"File(s): "))
Jens Petersen ce72b2
		nil (if default-files default-files-string "") nil nil
Jens Petersen ce72b2
		'igrep-files-history))
Jens Petersen ce72b2
	 (files (list file)))
Jens Petersen ce72b2
    (if (or igrep-read-multiple-files
Jens Petersen ce72b2
	    (and (consp current-prefix-arg)
Jens Petersen ce72b2
		 (memq (prefix-numeric-value current-prefix-arg)
Jens Petersen ce72b2
		       '(16 64))))
Jens Petersen ce72b2
	(let* ((key (igrep-default-key 'exit-minibuffer
Jens Petersen ce72b2
				       minibuffer-local-completion-map
Jens Petersen ce72b2
				       "\r"))
Jens Petersen ce72b2
	       (prompt
Jens Petersen ce72b2
		(igrep-prefix prompt-prefix
Jens Petersen ce72b2
			      (if igrep-verbose-prompts
Jens Petersen ce72b2
				  (format "File(s): [Type `%s' when done] "
Jens Petersen ce72b2
					  (key-description key))
Jens Petersen ce72b2
				"File(s): "))))
Jens Petersen ce72b2
	  (while (and (setq file
Jens Petersen ce72b2
			    (igrep-read-file-name prompt
Jens Petersen ce72b2
						  nil "" nil nil
Jens Petersen ce72b2
						  'igrep-files-history))
Jens Petersen ce72b2
		      (not (equal file "")))
Jens Petersen ce72b2
	    (setq files (cons file files)))))
Jens Petersen ce72b2
    (mapcar (lambda (file)
Jens Petersen ce72b2
	      (if (file-directory-p file)
Jens Petersen ce72b2
		  ;; really should map expand-file-name over default-files:
Jens Petersen ce72b2
		  (expand-file-name (if default-files default-files-string "*")
Jens Petersen ce72b2
				    file)
Jens Petersen ce72b2
		file))
Jens Petersen ce72b2
	    (nreverse files))))
Jens Petersen ce72b2

Jens Petersen ce72b2
(defun igrep-read-file-name (prompt
Jens Petersen ce72b2
  &optional directory default existing initial history)
Jens Petersen ce72b2
  "Just like `read-file-name,' but with optional HISTORY."
Jens Petersen ce72b2
  (if igrep-insert-default-key
Jens Petersen ce72b2
      (define-key minibuffer-local-completion-map igrep-insert-default-key
Jens Petersen ce72b2
	'igrep-insert-default-files))
Jens Petersen ce72b2
  (if history
Jens Petersen ce72b2
      (let ((file-name-history (symbol-value history)))
Jens Petersen ce72b2
	(prog1 (read-file-name prompt directory default existing initial)
Jens Petersen ce72b2
	  (set history file-name-history)))
Jens Petersen ce72b2
    (read-file-name prompt directory default existing initial)))
Jens Petersen ce72b2

Jens Petersen ce72b2
;; Menu bar:
Jens Petersen ce72b2

Jens Petersen ce72b2
(if igrep-easy-menu
Jens Petersen ce72b2
    (progn
Jens Petersen ce72b2
      (easy-menu-define igrep-menu nil
Jens Petersen ce72b2
	"Menu keymap for igrep."
Jens Petersen ce72b2
	igrep-easy-menu)
Jens Petersen ce72b2
      (cond ((fboundp 'add-submenu)	; XEmacs
Jens Petersen ce72b2
	     (add-submenu '("Tools") igrep-menu "Grep..."))
Jens Petersen ce72b2
	    ((fboundp 'easy-menu-add-item) ; Emacs 20
Jens Petersen ce72b2
	     (easy-menu-add-item menu-bar-tools-menu nil igrep-menu
Jens Petersen ce72b2
				 'grep))
Jens Petersen ce72b2
	    (t				; Emacs 19
Jens Petersen ce72b2
	     (define-key-after menu-bar-tools-menu [igrep]
Jens Petersen ce72b2
	       (cons (car igrep-easy-menu) igrep-menu)
Jens Petersen ce72b2
	       (and (lookup-key menu-bar-tools-menu [grep]) 'grep))))))
Jens Petersen ce72b2

Jens Petersen ce72b2
;;; Local Variables:
Jens Petersen ce72b2
;;; eval: (put 'igrep-define 'lisp-indent-function 1)
Jens Petersen ce72b2
;;; eval: (put 'igrep-find-define 'lisp-indent-function 1)
Jens Petersen ce72b2
;;; eval: (put 'easy-menu-define 'lisp-indent-function 'defun)
Jens Petersen ce72b2
;;; End:
Jens Petersen ce72b2

Jens Petersen ce72b2
(provide 'igrep)
Jens Petersen ce72b2

Jens Petersen ce72b2
;;; igrep.el ends here