]> code.delx.au - gnu-emacs-elpa/blobdiff - packages/company/company-eclim.el
Sync with yasnippet/master
[gnu-emacs-elpa] / packages / company / company-eclim.el
index 2bbe99e46f935721642324d9326ce89af8000da6..70db7c31b10c52c014323b2224fb7be014e51a27 100644 (file)
@@ -1,6 +1,6 @@
-;;; company-eclim.el --- A company-mode completion back-end for eclim.
+;;; company-eclim.el --- company-mode completion back-end for Eclim
 
 
-;; Copyright (C) 2009, 2011  Free Software Foundation, Inc.
+;; Copyright (C) 2009, 2011, 2013  Free Software Foundation, Inc.
 
 ;; Author: Nikolaj Schumacher
 
 
 ;; Author: Nikolaj Schumacher
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
 
-
 ;;; Commentary:
 ;;; Commentary:
-;; 
+;;
+;; Using `emacs-eclim' together with (or instead of) this back-end is
+;; recommended, as it allows you to use other Eclim features.
+;;
+;; The alternative back-end provided by `emacs-eclim' uses `yasnippet'
+;; instead of `company-template' to expand function calls, and it supports
+;; some languages other than Java.
 
 ;;; Code:
 
 (require 'company)
 
 ;;; Code:
 
 (require 'company)
+(require 'company-template)
 (eval-when-compile (require 'cl))
 
 (eval-when-compile (require 'cl))
 
+(defgroup company-eclim nil
+  "Completion back-end for Eclim."
+  :group 'company)
+
 (defun company-eclim-executable-find ()
   (let (file)
     (dolist (eclipse-root '("/Applications/eclipse" "/usr/lib/eclipse"
 (defun company-eclim-executable-find ()
   (let (file)
     (dolist (eclipse-root '("/Applications/eclipse" "/usr/lib/eclipse"
 
 (defcustom company-eclim-executable
   (or (executable-find "eclim") (company-eclim-executable-find))
 
 (defcustom company-eclim-executable
   (or (executable-find "eclim") (company-eclim-executable-find))
-  "*Location of eclim executable."
-  :group 'company
+  "Location of eclim executable."
   :type 'file)
 
 (defcustom company-eclim-auto-save t
   :type 'file)
 
 (defcustom company-eclim-auto-save t
-  "*Determines whether to save the buffer when retrieving completions.
+  "Determines whether to save the buffer when retrieving completions.
 eclim can only complete correctly when the buffer has been saved."
 eclim can only complete correctly when the buffer has been saved."
-  :group 'company
   :type '(choice (const :tag "Off" nil)
                  (const :tag "On" t)))
 
   :type '(choice (const :tag "Off" nil)
                  (const :tag "On" t)))
 
@@ -55,34 +63,32 @@ eclim can only complete correctly when the buffer has been saved."
 (defvar company-eclim--project-dir 'unknown)
 (make-variable-buffer-local 'company-eclim--project-dir)
 
 (defvar company-eclim--project-dir 'unknown)
 (make-variable-buffer-local 'company-eclim--project-dir)
 
-(defvar company-eclim--project-name 'unknown)
+(defvar company-eclim--project-name nil)
 (make-variable-buffer-local 'company-eclim--project-name)
 
 (defvar company-eclim--doc nil)
 (make-variable-buffer-local 'company-eclim--doc)
 
 (make-variable-buffer-local 'company-eclim--project-name)
 
 (defvar company-eclim--doc nil)
 (make-variable-buffer-local 'company-eclim--doc)
 
-(defun company-eclim--buffer-lines ()
-  (goto-char (point-max))
-  (let (lines)
-    (while (= 0 (forward-line -1))
-      (push (buffer-substring-no-properties (point-at-bol) (point-at-eol))
-            lines))
-    lines))
+(declare-function json-read "json")
+(defvar json-array-type)
 
 (defun company-eclim--call-process (&rest args)
   (let ((coding-system-for-read 'utf-8)
         res)
 
 (defun company-eclim--call-process (&rest args)
   (let ((coding-system-for-read 'utf-8)
         res)
+    (require 'json)
     (with-temp-buffer
       (if (= 0 (setq res (apply 'call-process company-eclim-executable nil t nil
                                 "-command" args)))
     (with-temp-buffer
       (if (= 0 (setq res (apply 'call-process company-eclim-executable nil t nil
                                 "-command" args)))
-          (company-eclim--buffer-lines)
+          (let ((json-array-type 'list))
+            (goto-char (point-min))
+            (unless (eobp)
+              (json-read)))
         (message "Company-eclim command failed with error %d:\n%s" res
                  (buffer-substring (point-min) (point-max)))
         nil))))
 
 (defun company-eclim--project-list ()
         (message "Company-eclim command failed with error %d:\n%s" res
                  (buffer-substring (point-min) (point-max)))
         nil))))
 
 (defun company-eclim--project-list ()
-  (mapcar (lambda (line) (nreverse (split-string line " *- *" nil)))
-          (company-eclim--call-process "project_list")))
+  (company-eclim--call-process "project_list"))
 
 (defun company-eclim--project-dir ()
   (if (eq company-eclim--project-dir 'unknown)
 
 (defun company-eclim--project-dir ()
   (if (eq company-eclim--project-dir 'unknown)
@@ -93,39 +99,64 @@ eclim can only complete correctly when the buffer has been saved."
     company-eclim--project-dir))
 
 (defun company-eclim--project-name ()
     company-eclim--project-dir))
 
 (defun company-eclim--project-name ()
-  (if (eq company-eclim--project-name 'unknown)
-      (setq company-eclim--project-name
-            (car (cddr (assoc (company-eclim--project-dir)
-                              (company-eclim--project-list)))))
-    company-eclim--project-name))
+  (or company-eclim--project-name
+      (let ((dir (company-eclim--project-dir)))
+        (when dir
+          (setq company-eclim--project-name
+                (loop for project in (company-eclim--project-list)
+                      when (equal (cdr (assoc 'path project)) dir)
+                      return (cdr (assoc 'name project))))))))
 
 (defun company-eclim--candidates (prefix)
   (interactive "d")
   (let ((project-file (file-relative-name buffer-file-name
 
 (defun company-eclim--candidates (prefix)
   (interactive "d")
   (let ((project-file (file-relative-name buffer-file-name
-                                          (company-eclim--project-dir)))
-        (project-name (company-eclim--project-name)))
+                                          (company-eclim--project-dir))))
     (when company-eclim-auto-save
       (when (buffer-modified-p)
         (basic-save-buffer))
       ;; FIXME: Sometimes this isn't finished when we complete.
       (company-eclim--call-process "java_src_update"
     (when company-eclim-auto-save
       (when (buffer-modified-p)
         (basic-save-buffer))
       ;; FIXME: Sometimes this isn't finished when we complete.
       (company-eclim--call-process "java_src_update"
-                                  "-p" (company-eclim--project-name)
-                                  "-f" project-file))
+                                   "-p" (company-eclim--project-name)
+                                   "-f" project-file))
     (setq company-eclim--doc
     (setq company-eclim--doc
-          (mapcar (lambda (line)
-                    (cdr (split-string line "|" nil)))
-                  (company-eclim--call-process
-                   "java_complete" "-p" (company-eclim--project-name)
-                   "-f" project-file
-                   "-o" (number-to-string (1- (point)))
-                   "-e" "utf-8"
-                   "-l" "standard"))))
+          (make-hash-table :test 'equal))
+    (dolist (item (cdr (assoc 'completions
+                              (company-eclim--call-process
+                               "java_complete" "-p" (company-eclim--project-name)
+                               "-f" project-file
+                               "-o" (number-to-string
+                                     (company-eclim--search-point prefix))
+                               "-e" "utf-8"
+                               "-l" "standard"))))
+      (let* ((meta (cdr (assoc 'info item)))
+             (completion meta))
+        (when (string-match " [:-]" completion)
+          (setq completion (substring completion 0 (match-beginning 0))))
+        (puthash completion meta company-eclim--doc))))
   (let ((completion-ignore-case nil))
   (let ((completion-ignore-case nil))
-    (all-completions prefix (mapcar 'car company-eclim--doc))))
+    (all-completions prefix company-eclim--doc)))
+
+(defun company-eclim--search-point (prefix)
+  (if (or (plusp (length prefix)) (eq (char-before) ?.))
+      (1- (point))
+    (point)))
+
+(defun company-eclim--meta (candidate)
+  (gethash candidate company-eclim--doc))
+
+(defun company-eclim--prefix ()
+  (let ((prefix (company-grab-symbol)))
+    (when prefix
+      ;; Completion candidates for annotations don't include '@'.
+      (when (eq ?@ (string-to-char prefix))
+        (setq prefix (substring prefix 1)))
+      prefix)))
 
 (defun company-eclim (command &optional arg &rest ignored)
 
 (defun company-eclim (command &optional arg &rest ignored)
-  "A `company-mode' completion back-end for eclim.
-eclim provides access to Eclipse Java IDE features for other editors.
+  "`company-mode' completion back-end for Eclim.
+Eclim provides access to Eclipse Java IDE features for other editors.
+
+Eclim version 1.7.13 or newer (?) is required.
 
 Completions only work correctly when the buffer has been saved.
 `company-eclim-auto-save' determines whether to do this automatically."
 
 Completions only work correctly when the buffer has been saved.
 `company-eclim-auto-save' determines whether to do this automatically."
@@ -137,11 +168,15 @@ Completions only work correctly when the buffer has been saved.
                  company-eclim-executable
                  (company-eclim--project-name)
                  (not (company-in-string-or-comment))
                  company-eclim-executable
                  (company-eclim--project-name)
                  (not (company-in-string-or-comment))
-                 (or (company-grab-symbol) 'stop)))
+                 (or (company-eclim--prefix) 'stop)))
     (candidates (company-eclim--candidates arg))
     (candidates (company-eclim--candidates arg))
-    (meta (cadr (assoc arg company-eclim--doc)))
+    (meta (company-eclim--meta arg))
     ;; because "" doesn't return everything
     ;; because "" doesn't return everything
-    (no-cache (equal arg ""))))
+    (no-cache (equal arg ""))
+    (crop (when (string-match "(" arg)
+            (substring arg 0 (match-beginning 0))))
+    (post-completion (when (string-match "([^)]" arg)
+                       (company-template-c-like-templatify arg)))))
 
 (provide 'company-eclim)
 ;;; company-eclim.el ends here
 
 (provide 'company-eclim)
 ;;; company-eclim.el ends here