]> code.delx.au - gnu-emacs-elpa/blobdiff - company-eclim.el
Support c++-mode in company-clang; templatify calls in C and C++
[gnu-emacs-elpa] / company-eclim.el
index db486c180bab5193fdcb4f8d8c91d88991daac3c..864f550ed23dfce74156dee7c61bdbdcc30241e5 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
 
 ;; 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:
 ;;
+;; 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)
+(require 'company-template)
 (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"
 (defcustom company-eclim-executable
   (or (executable-find "eclim") (company-eclim-executable-find))
   "Location of eclim executable."
-  :group 'company
   :type 'file)
 
 (defcustom company-eclim-auto-save t
   "Determines whether to save the buffer when retrieving completions.
 eclim can only complete correctly when the buffer has been saved."
-  :group 'company
   :type '(choice (const :tag "Off" nil)
                  (const :tag "On" t)))
 
@@ -55,34 +63,29 @@ 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-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)
 
-(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))
-
 (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)))
-          (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 ()
-  (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)
@@ -93,11 +96,13 @@ eclim can only complete correctly when the buffer has been saved."
     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")
@@ -109,23 +114,39 @@ eclim can only complete correctly when the buffer has been saved."
         (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
-          (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))
-    (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 (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."
@@ -139,9 +160,13 @@ Completions only work correctly when the buffer has been saved.
                  (not (company-in-string-or-comment))
                  (or (company-grab-symbol) 'stop)))
     (candidates (company-eclim--candidates arg))
-    (meta (cadr (assoc arg company-eclim--doc)))
+    (meta (company-eclim--meta arg))
     ;; 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