Skip to content

Instantly share code, notes, and snippets.

@deangiberson
Created November 29, 2012 03:52
Show Gist options
  • Save deangiberson/4166712 to your computer and use it in GitHub Desktop.
Save deangiberson/4166712 to your computer and use it in GitHub Desktop.
Integrate Emacs with git grep for grepping and interactive search and replace
(defun* get-closest-pathname (&optional (file "Makefile"))
"Determine the pathname of the first instance of FILE starting from the
current directory towards root. This may not do the correct thing in presence
of links. If it does not find FILE, then it shall return the name of FILE in
the current directory, suitable for creation"
(let ((root (expand-file-name "/")))
(expand-file-name file
(loop
for d = default-directory
then (expand-file-name ".." d)
if (file-exists-p (expand-file-name file d))
return d
if (equal d root)
return nil))))
(defun region-or-symbol-at-point ()
(if mark-active
(buffer-substring-no-properties (region-beginning) (region-end))
(or (symbol-name (symbol-at-point)) "")))
(defun git-grep (regexp)
(interactive
(let ((regexp (read-string
(format "Grep (default %s): " (region-or-symbol-at-point))
nil 'git-grep (region-or-symbol-at-point))))
(list regexp)))
(print regexp)
(let ((grep-use-null-device nil)
(default-directory (file-name-directory (get-closest-pathname ".git"))))
(grep (format "git grep --extended-regexp -I -n --ignore-case -e %s | cat"
regexp))))
(defun git-grep-query-replace (regexp to-string)
(interactive
(let* ((last-regexp (and (boundp 'git-grep-query-replace-regexp)
git-grep-query-replace-regexp
(car git-grep-query-replace-regexp)))
(last-to-string (and (boundp 'git-grep-query-replace-to-string)
git-grep-query-replace-to-string
(car git-grep-query-replace-to-string)))
(regexp
(if (and last-regexp last-to-string)
(read-string
(format "Query replace (%s -> %s): " last-regexp last-to-string)
nil 'git-grep-query-replace-regexp)
(read-string "Query replace: " nil
'git-grep-query-replace-regexp)))
(to-string
(if (and regexp (not (string= "" regexp)))
(read-string (format "Query replace %s with: " regexp)
nil 'git-grep-query-replace-to-string))))
(if (and regexp (not (string= "" regexp)))
(list regexp to-string)
(list last-regexp last-to-string))))
(let* ((default-directory (file-name-directory (get-closest-pathname ".git")))
(buffer-name (concat "*Git Grep Dired " default-directory "*")))
(switch-to-buffer buffer-name)
(fundamental-mode)
(let ((buffer-read-only nil))
(erase-buffer)
(call-process-shell-command
(format (concat
"git grep --extended-regexp -l -I -n --ignore-case -e %s | "
"cat | xargs ls -l | sed -e 's/^/ /g'") regexp) nil t)
(dired-mode)
(dired-toggle-marks)
(if (fboundp 'dired-simple-subdir-alist)
(dired-simple-subdir-alist)
(set (make-local-variable 'dired-subdir-alist)
(list (cons default-directory (point-min-marker)))))
(bury-buffer)
(with-current-buffer buffer-name
(dired-do-query-replace-regexp regexp to-string)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment