;; findclass.el - bindings for the findclass tool ;; ;; Author: Michael Bayne ;; Version: 1.0 ;; URL: http://github.com/samskivert/findclass ;; Compatibility: GNU Emacs 22.x, GNU Emacs 23.x ;; ;; This file is NOT part of GNU Emacs. ;; ;;; Commentary: ;; ;; Configure findclass for use in Java mode by adding the following to your .emacs ;; file (customizing key bindings to your preference, naturally): ;; ;; (load "path/to/findclass.el") ;; (defun findclass-java-mode-hook () ;; (define-key java-mode-map "\C-c\C-i" 'import-class-at-symbol) ;; (define-key java-mode-map "\C-c\C-j" 'open-class-at-symbol) ;; ) ;; (add-hook 'java-mode-hook 'findclass-java-mode-hook) ;; ;; findclass also works with Scala and ActionScript, so do the same for those ;; modes. ;;; Code: (defvar findclass-jar "~/bin/findclass.jar" "The location of the findclass.jar.") (defun open-class-at-symbol (class) "Locates and opens a buffer with the class identified by the symbol under the point as its argument." (interactive (list (read-from-minibuffer "Class: " (thing-at-point 'symbol)))) (let* ((rebuild (if current-prefix-arg "-rebuild" "")) (output (runfind class rebuild)) ) (if (string= (car output) "nomatch") (message (format "No match for class: %s" class)) (find-file (car (cdr output))) (goto-line (string-to-number (car (cdr (cdr output))))) ) ) ) (defun import-class-at-symbol (class &optional arg) "Locates the class identified by the symbol under the point and inserts an import statement for that class in the appropriate position." (interactive (list (read-from-minibuffer "Class: " (thing-at-point 'symbol)))) ;; save the current buffer (if needed) because findclass will read the file ;; from the file-system to determine where to insert the import (if (buffer-modified-p) (save-buffer)) (let* ((term (if (string= mode-name "Scala") "" ";")) (spoint (point)) ;; save the point (rebuild (if current-prefix-arg "-rebuild" "")) (output (runfind class (concat rebuild " -import"))) ) (if (string= (car output) "nomatch") (message (format "No match for class: %s" class))) (if (string= (car output) "notneeded") (message (format "%s is already imported." class))) (if (string= (car output) "match") (let ((mclass (car (cdr output))) (mline (car (cdr (cdr output)))) (mblank (car (cdr (cdr (cdr output))))) (madjust 0) (mneedadjust nil)) ;; go to our insertion line (goto-line (string-to-number mline)) (setq mneedadjust (<= (point) spoint)) ;; insert the import statment and any necessary blank lines (if (string= mblank "preblank") (progn (insert "\n") (setq madjust (1+ madjust)))) (insert (concat "import " mclass term "\n")) (setq madjust (+ madjust (length mclass))) (setq madjust (+ madjust 8)) ; 'import \n' (setq madjust (+ madjust (length term))) ; optional semicolon (if (string= mblank "postblank") (progn (insert "\n") (setq madjust (1+ madjust)))) ;; finally adjust the point (if necessary) and restore it (if mneedadjust (setq spoint (+ spoint madjust))) (goto-char spoint) (message (format "Imported: %s" mclass)) ) ) ) ) (defun filter (condp lst) (delq nil (mapcar (lambda (x) (and (funcall condp x) x)) lst))) (defun iswarn (line) (and (> (length line) 4) (string= (substring line 0 4) "WARN"))) (defun runfind (class args) (let* ((command (concat "java -jar " findclass-jar " " args " " class " " (buffer-file-name))) (cmdlines (split-string (shell-command-to-string command) "\n")) (warns (filter 'iswarn cmdlines)) (output (split-string (car (filter (lambda (l) (not (iswarn l))) cmdlines)))) ) (if (not (zerop (length warns))) (mapcar 'message warns)) output))