Download
(require 'compile)
(require 'ring)
(defgroup opengrok nil
"Global minor mode for source code indexer OpenGrok."
:group 'programming)
(defcustom opengrok-marker-ring-length 16
"*Length of marker ring `opengrok-find-marker-ring'."
:group 'opengrok
:type 'integer)
(defcustom opengrok-dir nil
"Source directory containing a directory in which an OpenGrok
project resides."
:group 'opengrok
:type 'directory)
(defcustom opengrok-project-dir-name ".opengrok"
"Name of the directory containing an OpenGrok project."
:group 'opengrok
:type 'string)
(defcustom opengrok-jar "c:/home/bin/opengrok-0.11.1/lib/opengrok.jar"
"The location of file `opengrok.jar' containing the OpenGrok byte code."
:group 'opengrok
:type 'directory)
(defcustom opengrok-ctags-command "c:/home/bin/ctags.exe"
"Directory in which Exuberant Ctags lives."
:group 'opengrok
:type 'directory)
(defcustom opengrok-ctags-options "c:/home/etc/ctags.conf"
"File containing Exuberant Ctags command line options."
:group 'opengrok
:type 'directory)
(defcustom opengrok-index-include "-I *.c -I *.cpp -I *.h -I *.py -I *.cs -I *.java"
"OpenGrok option specifying file types to include in the index."
:group 'opengrok
:type 'string)
(defcustom opengrok-index-exclude "-i mweb_memdump.c"
"OpenGrok option specifying file types to exinclude from the index."
:group 'opengrok
:type 'string)
(defvar opengrok-mode-font-lock-keywords
'(
(": \\(.+\\): \\(?:Permission denied\\|No such \\(?:file or directory\\|device or address\\)\\)$"
1 grep-error-face)
("^OpenGrok[/a-zA-z]* started.*"
(0 '(face nil compilation-message nil help-echo nil mouse-face nil) t))
("^OpenGrok[/a-zA-z]* finished \\(?:(\\(matches found\\))\\|with \\(no matches found\\)\\).*"
(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))
("^OpenGrok[/a-zA-z]* \\(exited abnormally\\|interrupt\\|killed\\|terminated\\)\\(?:.*with code \\([0-9]+\\)\\)?.*"
(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)))
"Additional things to highlight in opengrok output.
This gets tacked on the end of the generated expressions.")
(defvar opengrok-create-project-buffer-name "*opengrok-create-project*"
"Name of the buffer which contains the output of an OpenGrok
create project invocation.")
(defvar opengrok-project-dir nil
"Directory containing an OpenGrok project.")
(defvar opengrok-configuration-file nil)
(defvar opengrok-find-marker-ring (make-ring opengrok-marker-ring-length)
"Ring of markers for locations at which \\[opengrok-find-path], \\[opengrok-find-defs],
or \\[opengrok-find-refs] was invoked.")
(defvar opengrok-last-buffer nil
"The most recent OpenGrok buffer.
A opengrok buffer becomes most recent when you select OpenGrok mode in it.
Notice that using \\[next-error] or \\[compile-goto-error] modifies
`compilation-last-buffer' rather than `opengrok-last-buffer'.")
(defun opengrok-find-path (str)
(interactive (opengrok-prompt "File"))
(opengrok-perform-search "-p" str))
(defun opengrok-find-path-sync (str)
(interactive (opengrok-prompt "File"))
(opengrok-perform-search "-p" str t))
(defun opengrok-find-defs (str)
(interactive (opengrok-prompt "Symbol definition"))
(opengrok-perform-search "-d" str))
(defun opengrok-find-refs (str)
(interactive (opengrok-prompt "Symbol reference"))
(opengrok-perform-search "-r" str))
(defun opengrok-find-full (str)
(interactive (opengrok-prompt "Full text"))
(opengrok-perform-search "-f" str))
(defadvice display-buffer (around prohibit-call-to-display-buffer)
"Prohibits the call to display-buffer"
(setq ad-return-value (selected-window)))
(defadvice set-window-start (around prohibit-call-to-set-window-start)
"Prohibits the call to set-window-start"
(setq ad-return-value 0))
(defun opengrok-perform-search (search-type search-str)
(or (file-exists-p opengrok-configuration-file) (error "No OpenGrok project found"))
(let ((cmd (concat "java -Xms128m -cp " opengrok-jar
" org.opensolaris.opengrok.search.Search"
" -R " opengrok-configuration-file
" " search-type " \"" search-str "\"")))
(ring-insert opengrok-find-marker-ring (point-marker))
(ad-activate 'display-buffer)
(ad-activate 'set-window-start)
(unwind-protect
(compilation-start cmd 'opengrok-mode)
(ad-deactivate 'display-buffer)
(ad-deactivate 'set-window-start))))
(defun opengrok-create-project ()
(interactive)
(or (file-exists-p opengrok-dir) (error "No source code directory specified"))
(set-process-sentinel
(start-process-shell-command
"opengrok-create-project" opengrok-create-project-buffer-name
(concat "java -Xms512m -cp " opengrok-jar
" org.opensolaris.opengrok.index.Indexer"
" -d " opengrok-project-dir
" -W " opengrok-configuration-file
" -s " opengrok-dir
" -c " opengrok-ctags-command
" " opengrok-index-include
" " opengrok-index-exclude)) 'opengrok-create-project-cb))
(defun opengrok-create-project-cb (process event)
"Sentinel called when the process that created a project signals."
(with-current-buffer (get-buffer opengrok-create-project-buffer-name)
(save-excursion
(goto-char (point-max))
(previous-line 15)
(if (re-search-forward "Optimizing the index" nil t)
(message "Successfully created OpenGrok project.")
(message "Failed to create OpenGrok project.")))))
(defun opengrok-filter ()
"Handle highlighting hits marked by XHTML tags in the OpenGrok output.
This function is called from `compilation-filter-hook'."
(save-excursion
(forward-line 0)
(let ((end (point)) beg)
(goto-char compilation-filter-start)
(forward-line 0)
(setq beg (point))
(when (< (point) end)
(setq end (copy-marker end))
(while (re-search-forward "
" end 1)
(replace-match "" t t))
(goto-char beg)
(while (re-search-forward "<b>\\(.*?\\)</b>" end 1)
(replace-match (propertize (match-string 1)
'face nil 'font-lock-face grep-match-face)
t t))
(goto-char beg)
(while (re-search-forward "</?b>" end 1)
(replace-match "" t t))
(goto-char beg)
(while (re-search-forward ": \\[...\\]" nil t)
(replace-match ":1:"))
(goto-char beg)
(while (re-search-forward " \\[" nil t)
(replace-match ":"))
(goto-char beg)
(while (re-search-forward "\\]$" nil t)
(replace-match ""))
(goto-char beg)
(while (re-search-forward "<" nil t)
(replace-match "<"))
(goto-char beg)
(while (re-search-forward ">" nil t)
(replace-match ">"))))))
(defun opengrok-number-of-hits ()
(with-current-buffer opengrok-last-buffer
(save-excursion
(goto-char (point-min))
(if (re-search-forward "of \\([0-9]+\\) total matching documents collected" nil t)
(string-to-number (match-string 1))
0))))
(defun opengrok-exit-message-function (status code msg)
(let ((hits 0))
(if (eq status 'exit)
(cond ((and (zerop code) (buffer-modified-p) (> (setq hits (opengrok-number-of-hits)) 0))
(if (eq hits 1) (opengrok-goto-first-hit)
(display-buffer opengrok-last-buffer))
'("finished (matches found)\n" . "matched"))
((or (not (buffer-modified-p)) (eq hits 0))
'("finished with no matches found\n" . "no match"))
(t
(cons msg code)))
(cons msg code))))
(defun opengrok-goto-first-hit ()
(ad-activate 'display-buffer)
(ad-activate 'set-window-start)
(unwind-protect
(next-error 1 t)
(ad-deactivate 'display-buffer)
(ad-deactivate 'set-window-start)))
(defun opengrok-pop-find-mark ()
"Pop back to where \\[opengrok-find-path], \\[opengrok-find-defs],
or \\[opengrok-find-refs] was last invoked."
(interactive)
(if (ring-empty-p opengrok-find-marker-ring)
(error "No previous locations for opengrok-find-* invocation"))
(let ((marker (ring-remove opengrok-find-marker-ring 0)))
(switch-to-buffer (or (marker-buffer marker)
(error "The marked buffer has been deleted")))
(goto-char (marker-position marker))
(set-marker marker nil nil)))
(defun opengrok-prompt (str)
(let* ((default (grep-tag-default))
(prompt (if (string= default "")
(format "%s: " str)
(format "%s (default %s): " str default))))
(list (read-string prompt nil nil default))))
(defun opengrok-change-dir (dir)
(interactive "DDirectory: ")
(setq opengrok-dir (convert-standard-filename (directory-file-name dir)))
(setq opengrok-project-dir (convert-standard-filename
(concat (file-name-as-directory opengrok-dir)
opengrok-project-dir-name)))
(setq opengrok-configuration-file (convert-standard-filename
(concat (file-name-as-directory opengrok-project-dir)
"configuration.xml")))
(setq opengrok-project-drive (substring opengrok-project-dir 0 2)))
(defvar opengrok-key-map (make-sparse-keymap)
"Keymap used in OpenGrok minor mode.")
(define-key opengrok-key-map "\e*" 'opengrok-pop-find-mark)
(define-key opengrok-key-map (kbd "C-,") 'opengrok-find-path)
(define-key opengrok-key-map "\e." 'opengrok-find-defs)
(define-key opengrok-key-map "\e," 'opengrok-find-refs)
(define-compilation-mode opengrok-mode "OpenGrok"
(setq opengrok-last-buffer (current-buffer))
(set (make-local-variable 'compilation-error-face)
grep-hit-face)
(set (make-local-variable 'compilation-disable-input) t)
(add-hook 'compilation-filter-hook 'opengrok-filter nil t)
(set (make-local-variable 'compilation-exit-message-function)
'opengrok-exit-message-function)
(set (make-local-variable 'comint-inhibit-carriage-motion) t))
(define-minor-mode opengrok-minor-mode
"Navigate source code with OpenGrok."
:global t
:init-value nil
:keymap opengrok-key-map
:group 'opengrok
(and opengrok-dir (file-exists-p opengrok-dir) (opengrok-change-dir opengrok-dir)))
(provide 'opengrok)