Download
(require 'grep)
(defgroup grep-o-matic nil
"Automation layer for grep.el"
:group 'grep
:group 'convenience
:prefix "grep-o-matic-")
(defcustom grep-o-matic-search-patterns
(list "*.cpp" "*.c" "*.h" "*.awk" "*.sh" "*.py" "*.pl" "[Mm]akefile" "*.el")
"*Search file patterns for use with grep-o-matic-* commands."
:group 'grep-o-matic
:type '(repeat string))
(defcustom grep-o-matic-repository-root-function (if (featurep 'repository-root)
'repository-root
nil)
"*If non-nil, a function that returns the current file's repository root directory.
The function is called with a single string argument (a file name) and should
return either nil, or a string, which is the root directory of that file's repository.
The default value is nil, unless the repository-root library is loaded before
loading grep-o-matic, in which case the default value is `repository-root'."
:group 'grep-o-matic
:type '(choice (const nil) (function)))
(defcustom grep-o-matic-ask-about-save t
"*If non-nil ask which buffers to save before performing a search.
Otherwise, all modified buffers are saved without asking."
:group 'grep-o-matic
:type 'boolean)
(defun grep-o-matic-repository-root (filename)
"Attempt to deduce the current file's repository root directory.
You should customize `grep-o-matic-repository-root-function' and provide a function that
does the actual work, based of the type of SCM tool that you're using."
(if (null filename)
nil
(let* ((directory (file-name-directory filename))
(repository-root (if (and grep-o-matic-repository-root-function
(functionp grep-o-matic-repository-root-function))
(apply grep-o-matic-repository-root-function (list filename))
nil)))
(or repository-root directory))))
(defun grep-o-matic-get-regexp (prompt)
"Get the default regexp or query the user for it."
(let ((regexp (grep-tag-default)))
(if (and (not prompt) regexp)
(progn
(add-to-list 'grep-regexp-history regexp)
regexp)
(grep-read-regexp))))
(defun grep-o-matic-directory (prompt directory)
"Search directory for word at point.
Optionaly prompt for regexp to search."
(let ((patterns grep-o-matic-search-patterns)
(extension (if buffer-file-name
(file-name-extension buffer-file-name)
nil))
(filename (if buffer-file-name
(file-name-nondirectory buffer-file-name)
nil)))
(let ((nomatch (or (null filename)
(and filename
(let ((head (car patterns))
(tail (cdr patterns)))
(while (and (not (null head))
(not (string-match (wildcard-to-regexp head) filename)))
(progn
(setq head (car tail))
(setq tail (cdr tail))))
(null head))))))
(when nomatch
(setq patterns (list (if extension
(concat "*." extension)
"*"))))
(grep-compute-defaults)
(save-some-buffers (not grep-o-matic-ask-about-save) nil)
(rgrep (grep-o-matic-get-regexp prompt)
(mapconcat (lambda (s) s) patterns " ")
(if directory
directory
default-directory)))))
(defun grep-o-matic-repository (&optional prompt)
"Search repository for word at point.
Optionaly prompt for regexp to search."
(interactive "P")
(grep-o-matic-directory prompt (grep-o-matic-repository-root buffer-file-name)))
(defun grep-o-matic-current-directory (&optional prompt)
"Search current directory for word at point.
Optionaly prompt for regexp to search."
(interactive "P")
(grep-o-matic-directory prompt (if buffer-file-name
(file-name-directory buffer-file-name)
nil)))
(defun grep-o-matic-visited-files (&optional prompt)
"Search currently visited files for word at point.
Optionaly prompt for regexp to search."
(interactive "P")
(let ((regexp (grep-o-matic-get-regexp prompt))
(files (let ((directory-abbrev-alist
(cons (cons (regexp-quote (expand-file-name default-directory)) "./") directory-abbrev-alist)))
(mapconcat (lambda (fn) (abbreviate-file-name (shell-quote-argument fn)))
(apply 'nconc
(mapcar '(lambda (buffer)
(let ((file (buffer-file-name buffer)))
(if (and file
(cond ((featurep 'ange-ftp)
(not (ange-ftp-ftp-name file)))
((featurep 'efs)
(not (efs-ftp-path file)))
(t t)))
(list file))))
(buffer-list)))
" ")))
(dir "")
(excl ""))
(progn
(grep-compute-defaults)
(save-some-buffers (not compilation-ask-about-save) nil)
(grep (grep-expand-template grep-template regexp files dir excl)))))
(define-prefix-command 'grep-o-matic-map)
(define-key grep-o-matic-map "\M-/" 'grep-o-matic-repository)
(define-key grep-o-matic-map "/" 'grep-o-matic-repository)
(define-key grep-o-matic-map "\M-." 'grep-o-matic-current-directory)
(define-key grep-o-matic-map "." 'grep-o-matic-current-directory)
(define-key grep-o-matic-map "\M-," 'grep-o-matic-visited-files)
(define-key grep-o-matic-map "," 'grep-o-matic-visited-files)
(global-set-key "\M-]" 'grep-o-matic-map)
(provide 'grep-o-matic)