;;; python-find.el -- Finding words in many python files

;; Copyright (C) 2007 Carlos Eduardo Scheidegger

;;; Author: Carlos Eduardo Scheidegger
;;; email: cscheid@sci.utah.edu
;;; Keywords: python, extension, lisp

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

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

;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

;; $Revision: 1.3 $

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ChangeLog

;; 2007 Jan 01: Initial version

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

(provide 'python-find)

(defvar python-find-directory nil)

(defun python-find-buffer ()
  (get-buffer-create "*python-find result*"))

(defun python-find-change-directory (d)
  (interactive "DEnter directory: ")
  (setq python-find-directory (replace-regexp-in-string
			       "^~" (getenv "HOME") d)))

(defun python-find-quote-directory ()
  (replace-regexp-in-string "/" "\\\\/" python-find-directory))

(defun python-find-buffer-click (event)
  (interactive "e")
  (let (selected-filename
	selected-filename-line-number)
    (save-excursion
      (set-buffer (window-buffer (posn-window (event-end event))))
      (save-excursion
	(goto-char (posn-point (event-start event)))
	(let ((clicked-line
	       (buffer-substring (line-beginning-position)
				 (line-end-position))))
	  (string-match "^\\([^:]+\\):\\([0-9]+\\):" clicked-line)
	  (let ((clicked-filename (concat
				   python-find-directory
				   (match-string 1 clicked-line)))
		(clicked-line-number (string-to-int (match-string 2 clicked-line))))
	    (setq selected-filename clicked-filename)
	    (setq selected-filename-line-number clicked-line-number)))))
    (let ((buffer-to-display (find-file-noselect selected-filename)))
      (switch-to-buffer buffer-to-display)
      (goto-line selected-filename-line-number buffer-to-display))))

(defun python-find-decorate-text ()
  (save-excursion
    (set-buffer (python-find-buffer))
    (save-excursion
      (let ((total-lines (count-lines (point-min) (point-max)))
	    (current-line 0)
	    (map (make-sparse-keymap)))
	(define-key map [mouse-2] 'python-find-buffer-click)
	(define-key map [enter] 'python-find-buffer-click)
	(goto-char (point-min))
	(while (<= current-line total-lines)
	  (put-text-property (line-beginning-position current-line)
			     (line-end-position current-line)
			     'mouse-face 'highlight)
	  (put-text-property (line-beginning-position current-line)
			     (line-end-position current-line)
			     'keymap map)
	  (setq current-line (+ current-line 1)))))))

(defun python-find (word)
  (interactive "sEnter word to search: ")
  (unless python-find-directory
    (call-interactively 'python-find-change-directory))
  (with-output-to-temp-buffer "*python-find result*"
    (let* ((quoted-dir (python-find-quote-directory))
	   (cmd (concat
		 "find "
		 python-find-directory
		 " -name '*.py' -exec grep -iHn "
		 word
		 " {} \\; | "
		 " sed -e 's/"
		 quoted-dir
		 "//'")))
      (call-process-shell-command cmd
       nil (python-find-buffer) t)
      (python-find-decorate-text)
      )))

;;; python-find.el ends here
