Greetings,
This is not a submission for magit (but see [1]) because this
command is intended to be bound globally but I thought magit users
might find use for this -- at least I couldn't live without it.
Since starting to write this I've learned that there is already
vc-git-grep, though the version in my Emacs doesn't even work and
besides it wouldn't provide such a user interface that I want.
This is work in progress; I should use my own mode instead of
grep-mode to get rid of modifying grep-mode-font-lock-keywords,
support non-default match colors, get rid of some bad shell usage
and use customize.
[1] Some kind of magit integration might be thinkable: for example,
use magit to select one or more <tree> arguments to git grep.
------8<----------------------------------------------------------
(setq 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))
("^Grep[/a-zA-z]* finished \\(?:(\\(matches found\\))\\|with \\(no
matches found\\)\\).*"
(0 '(face nil 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)
(1 grep-error-face)
(2 grep-error-face nil t))
("^.+?-[0-9]+-.*\n" (0 grep-context-face))
;; Highlight grep matches and delete markers
("\\(\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
;; Lock does not clear that.
(2 (list 'face nil 'font-lock-face grep-match-face))
((lambda (bound))
(progn
;; Delete markers with `replace-match' because it updates
;; the match-data, whereas `delete-region' would render it obsolete.
(replace-match "" t t nil 3)
(replace-match "" t t nil 1))))
("\\(\033\\[[0-9;]*[mK]\\)"
;; Delete all remaining escape sequences
((lambda (bound))
(replace-match "" t t nil 1)))))
(defun se--inside-git-work-tree-p ()
(string-match "^true" (shell-command-to-string "git rev-parse
--is-inside-work-tree 2>&1")))
(defun se--check-inside-git-work-tree ()
(or (se--inside-git-work-tree-p) (error "Error: Not inside git work tree.")))
(defvar se-git-grep-history nil)
(defvar se-git-grep-command "git grep --color -n -H -E -e "
"Basis for default `se-git-grep' comand. Must include -e.")
(defun se-git-grep (command &optional in-this-directory)
"Run git grep with user-specified arguments just like `grep' runs grep.
Interactively `se-git-grep-command' is used as the initial command.
A case-insensitive version of the initial command is available by moving one
step forward in history. Also, by default this command moves to the root of
the repository before executing `command' unless prefix argument is used.
Match fontification relies on default (red) or bold red color.grep.match value."
(interactive
(progn
(se--check-inside-git-work-tree)
(list
(read-shell-command "Run git grep (like this): "
se-git-grep-command 'se-git-grep-history
(let ((case-fold-search nil))
(replace-regexp-in-string " -e " " -i -e "
se-git-grep-command)))
current-prefix-arg)))
(let ((process-environment (cons "GIT_PAGER=cat" process-environment))
(default-directory
(if in-this-directory
default-directory
(concat default-directory
(substring
(with-output-to-string
(with-current-buffer standard-output
(unless (equal 0 (call-process "git" nil t nil
"rev-parse" "--show-cdup"))
(error "Error running git rev-parse --show-cdup: %s"
(buffer-string)))))
0 -1)))))
(compilation-start command 'grep-mode)))
------8<----------------------------------------------------------
--
Hannu
To unsubscribe from this group, send email to magit+unsubscribegooglegroups.com
or reply to this email with the words "REMOVE ME" as the subject.