;;; grep.el --- run Grep as inferior of Emacs, parse match messages
-;; Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-;; 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+;; Copyright (C) 1985-1987, 1993-1999, 2001-2011
;; Free Software Foundation, Inc.
;; Author: Roland McGrath <roland@gnu.org>
;;;###autoload
(defconst grep-regexp-alist
- '(("^\\(.+?\\)\\(:[ \t]*\\)\\([0-9]+\\)\\2"
+ '(("^\\(.+?\\)\\(:[ \t]*\\)\\([1-9][0-9]*\\)\\2"
1 3)
;; Rule to match column numbers is commented out since no known grep
;; produces them
;; ("^\\(.+?\\)\\(:[ \t]*\\)\\([0-9]+\\)\\2\\(?:\\([0-9]+\\)\\(?:-\\([0-9]+\\)\\)?\\2\\)?"
;; 1 3 (4 . 5))
- ("^\\(\\(.+?\\):\\([0-9]+\\):\\).*?\
+ ;; Note that we want to use as tight a regexp as we can to try and
+ ;; handle weird file names (with colons in them) as well as possible.
+ ;; E.g. we use [1-9][0-9]* rather than [0-9]+ so as to accept ":034:" in
+ ;; file names.
+ ("^\\(\\(.+?\\):\\([1-9][0-9]*\\):\\).*?\
\\(\033\\[01;31m\\(?:\033\\[K\\)?\\)\\(.*?\\)\\(\033\\[[0-9]*m\\)"
2 3
;; Calculate column positions (beg . end) of first grep match on a line
(- (match-beginning 4) (match-end 1)))
.
(lambda () (- (match-end 5) (match-end 1)
- (- (match-end 4) (match-beginning 4)))))
+ (- (match-end 4) (match-beginning 4)))))
nil 1)
("^Binary file \\(.+\\) matches$" 1 nil nil 0 1))
"Regexp used to match grep hits. See `compilation-error-regexp-alist'.")
(defvar grep-mode-font-lock-keywords
'(;; Command output lines.
- ("^\\([A-Za-z_0-9/\.+-]+\\)[ \t]*:" 1 font-lock-function-name-face)
(": \\(.+\\): \\(?:Permission denied\\|No such \\(?:file or directory\\|device or address\\)\\)$"
1 grep-error-face)
;; remove match from grep-regexp-alist before fontifying
("^Grep[/a-zA-z]* started.*"
- (0 '(face nil message nil help-echo nil mouse-face nil) t))
+ (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t))
("^Grep[/a-zA-z]* finished \\(?:(\\(matches found\\))\\|with \\(no matches found\\)\\).*"
- (0 '(face nil message nil help-echo nil mouse-face nil) t)
+ (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
(1 compilation-info-face nil t)
(2 compilation-warning-face nil t))
("^Grep[/a-zA-z]* \\(exited abnormally\\|interrupt\\|killed\\|terminated\\)\\(?:.*with code \\([0-9]+\\)\\)?.*"
- (0 '(face nil message nil help-echo nil mouse-face nil) t)
+ (0 '(face nil compilation-message nil help-echo nil mouse-face nil) t)
(1 grep-error-face)
(2 grep-error-face nil t))
("^.+?-[0-9]+-.*\n" (0 grep-context-face))
- ;; Highlight grep matches and delete markers
+ ;; Highlight grep matches and delete markers.
+ ;; FIXME: Modifying the buffer text from font-lock is a bad idea!
("\\(\033\\[01;31m\\)\\(.*?\\)\\(\033\\[[0-9]*m\\)"
;; Refontification does not work after the markers have been
;; deleted. So we use the font-lock-face property here as Font
(progn
;; Delete markers with `replace-match' because it updates
;; the match-data, whereas `delete-region' would render it obsolete.
+ (syntax-ppss-flush-cache (match-beginning 0))
(replace-match "" t t nil 3)
(replace-match "" t t nil 1))))
- ("\\(\033\\[[0-9;]*[mK]\\)"
+ ("\033\\[[0-9;]*[mK]"
;; Delete all remaining escape sequences
((lambda (bound))
- (replace-match "" t t nil 1))))
+ (syntax-ppss-flush-cache (match-beginning 0))
+ (replace-match "" t t))))
"Additional things to highlight in grep output.
This gets tacked on the end of the generated expressions.")
grep-find-template grep-find-use-xargs
grep-highlight-matches))
(set setting
- (or (cadr (assq setting host-defaults))
- (cadr (assq setting defaults)))))
+ (cadr (or (assq setting host-defaults)
+ (assq setting defaults)))))
(unless (or (not grep-use-null-device) (eq grep-use-null-device t))
(setq grep-use-null-device
(unless grep-find-command
(setq grep-find-command
(cond ((eq grep-find-use-xargs 'gnu)
- (format "%s . -type f -print0 | %s -0 -e %s"
+ ;; Windows shells need the program file name
+ ;; after the pipe symbol be quoted if they use
+ ;; forward slashes as directory separators.
+ (format "%s . -type f -print0 | \"%s\" -0 -e %s"
find-program xargs-program grep-command))
((eq grep-find-use-xargs 'exec)
(let ((cmd0 (format "%s . -type f -exec %s"
(shell-quote-argument ";"))
(1+ (length cmd0)))))
(t
- (format "%s . -type f -print | %s %s"
+ (format "%s . -type f -print | \"%s\" %s"
find-program xargs-program grep-command)))))
(unless grep-find-template
(setq grep-find-template
(let ((gcmd (format "%s <C> %s <R>"
grep-program grep-options)))
(cond ((eq grep-find-use-xargs 'gnu)
- (format "%s . <X> -type f <F> -print0 | %s -0 -e %s"
+ (format "%s . <X> -type f <F> -print0 | \"%s\" -0 -e %s"
find-program xargs-program gcmd))
((eq grep-find-use-xargs 'exec)
(format "%s . <X> -type f <F> -exec %s {} %s %s"
find-program gcmd null-device
(shell-quote-argument ";")))
(t
- (format "%s . <X> -type f <F> -print | %s %s"
+ (format "%s . <X> -type f <F> -print | \"%s\" %s"
find-program xargs-program gcmd))))))))
(when (eq grep-highlight-matches 'auto-detect)
(setq grep-highlight-matches
(file-name-nondirectory bn)))
(default-alias
(and fn
- (let ((aliases grep-files-aliases)
+ (let ((aliases (remove (assoc "all" grep-files-aliases)
+ grep-files-aliases))
alias)
(while aliases
(setq alias (car aliases)
aliases (cdr aliases))
- (if (string-match (wildcard-to-regexp (cdr alias)) fn)
+ (if (string-match (mapconcat
+ 'wildcard-to-regexp
+ (split-string (cdr alias) nil t)
+ "\\|")
+ fn)
(setq aliases nil)
(setq alias nil)))
(cdr alias))))
default-extension
(car grep-files-history)
(car (car grep-files-aliases))))
- (files (read-string
+ (files (completing-read
(concat "Search for \"" regexp
"\" in files"
(if default (concat " (default " default ")"))
": ")
- nil 'grep-files-history
+ 'read-file-name-internal
+ nil nil nil 'grep-files-history
(delete-dups
(delq nil (append (list default default-alias default-extension)
(mapcar 'car grep-files-aliases)))))))
Like `rgrep' but uses `zgrep' for `grep-program', sets the default
file name to `*.gz', and sets `grep-highlight-matches' to `always'."
(interactive
- (let ((grep-program "zgrep")
- (grep-find-template nil) ; output of `grep-compute-defaults'
- (grep-find-command nil)
- (grep-host-defaults-alist nil)
- (grep-files-aliases '(("*.gz" . "*.gz") ; for `grep-read-files'
- ("all" . "* .*"))))
- ;; Recompute defaults using let-bound values above.
+ (progn
+ ;; Compute standard default values.
(grep-compute-defaults)
- (cond
- ((and grep-find-command (equal current-prefix-arg '(16)))
- (list (read-from-minibuffer "Run: " grep-find-command
- nil nil 'grep-find-history)))
- ((not grep-find-template)
- (error "grep.el: No `grep-find-template' available"))
- (t (let* ((regexp (grep-read-regexp))
- (files (grep-read-files regexp))
- (dir (read-directory-name "Base directory: "
- nil default-directory t))
- (confirm (equal current-prefix-arg '(4))))
- (list regexp files dir confirm grep-find-template))))))
+ ;; Compute the default zrgrep command by running `grep-compute-defaults'
+ ;; for grep program "zgrep", but not changing global values.
+ (let ((grep-program "zgrep")
+ ;; Don't change global values for variables computed
+ ;; by `grep-compute-defaults'.
+ (grep-find-template nil)
+ (grep-find-command nil)
+ (grep-host-defaults-alist nil)
+ ;; Use for `grep-read-files'
+ (grep-files-aliases '(("all" . "* .*")
+ ("gz" . "*.gz"))))
+ ;; Recompute defaults using let-bound values above.
+ (grep-compute-defaults)
+ (cond
+ ((and grep-find-command (equal current-prefix-arg '(16)))
+ (list (read-from-minibuffer "Run: " grep-find-command
+ nil nil 'grep-find-history)))
+ ((not grep-find-template)
+ (error "grep.el: No `grep-find-template' available"))
+ (t (let* ((regexp (grep-read-regexp))
+ (files (grep-read-files regexp))
+ (dir (read-directory-name "Base directory: "
+ nil default-directory t))
+ (confirm (equal current-prefix-arg '(4))))
+ (list regexp files dir confirm grep-find-template)))))))
;; Set `grep-highlight-matches' to `always'
;; since `zgrep' puts filters in the grep output.
(let ((grep-highlight-matches 'always))
(provide 'grep)
-;; arch-tag: 5a5b9169-a79d-4f38-9c38-f69615f39c4d
;;; grep.el ends here