]> code.delx.au - gnu-emacs-elpa/blobdiff - company.el
Fixed when tooltip was too short to display number of remaining items.
[gnu-emacs-elpa] / company.el
index adb0d46116838748063a0906c1a03c9172f79915..e5c81dc075f99d85391515cc309103c0a4149e81 100644 (file)
@@ -69,6 +69,8 @@
 ;;
 ;;; Change Log:
 ;;
+;;    Added option `company-dabbrev-time-limit'.
+;;    `company-backends' now supports merging back-ends.
 ;;    Added back-end `company-dabbrev-code' for generic code.
 ;;    Fixed `company-begin-with'.
 ;;
@@ -243,11 +245,40 @@ The visualized data is stored in `company-prefix', `company-candidates',
                                 company-preview-if-just-one-frontend)
                          (function :tag "custom function" nil))))
 
+(defvar company-safe-backends
+  '((company-abbrev . "Abbrev")
+    (company-css . "CSS")
+    (company-dabbrev . "dabbrev for plain text")
+    (company-dabbrev-code . "dabbrev for code")
+    (company-elisp . "Emacs Lisp")
+    (company-etags . "etags")
+    (company-files . "Files")
+    (company-gtags . "GNU Global")
+    (company-ispell . "ispell")
+    (company-nxml . "nxml")
+    (company-oddmuse . "Oddmuse")
+    (company-semantic . "CEDET Semantic")
+    (company-tempo . "Tempo templates")
+    (company-xcode . "Xcode")))
+(put 'company-safe-backends 'risky-local-variable t)
+
+(defun company-safe-backends-p (backends)
+  (and (consp backends)
+       (not (dolist (backend backends)
+              (unless (if (consp backend)
+                          (company-safe-backends-p backend)
+                        (assq backend company-safe-backends))
+                (return t))))))
+
 (defcustom company-backends '(company-elisp company-nxml company-css
-                              company-semantic company-xcode company-gtags
-                              company-etags company-oddmuse company-files
-                              company-dabbrev-code company-dabbrev)
+                              company-semantic company-xcode
+                              (company-gtags company-etags company-dabbrev-code)
+                              company-oddmuse company-files company-dabbrev)
   "*The list of active back-ends (completion engines).
+Each list elements can itself be a list of back-ends.  In that case their
+completions are merged.  Otherwise only the first matching back-end returns
+results.
+
 Each back-end is a function that takes a variable number of arguments.
 The first argument is the command requested from the back-end.  It is one
 of the following:
@@ -292,7 +323,20 @@ The back-end should return nil for all commands it does not support or
 does not know about.  It should also be callable interactively and use
 `company-begin-backend' to start itself in that case."
   :group 'company
-  :type '(repeat (function :tag "function" nil)))
+  :type `(repeat
+          (choice
+           :tag "Back-end"
+           ,@(mapcar (lambda (b) `(const :tag ,(cdr b) ,(car b)))
+                     company-safe-backends)
+           (symbol :tag "User defined")
+           (repeat :tag "Merged Back-ends"
+                   (choice :tag "Back-end"
+                           ,@(mapcar (lambda (b)
+                                       `(const :tag ,(cdr b) ,(car b)))
+                                     company-safe-backends)
+                           (symbol :tag "User defined"))))))
+
+(put 'company-backends 'safe-local-variable 'company-safe-backend-p)
 
 (defcustom company-completion-started-hook nil
   "*Hook run when company starts completing.
@@ -435,14 +479,17 @@ The work-around consists of adding a newline.")
   "Keymap that is enabled during an active completion.")
 
 (defun company-init-backend (backend)
-  (when (symbolp backend)
-    (unless (fboundp backend)
-      (ignore-errors (require backend nil t)))
-    (if (and (fboundp backend)
-             (ignore-errors (funcall backend 'init) t))
-        (put backend 'company-init t)
-      (message "Company back-end '%s' could not be initialized"
-               backend))))
+  (and (symbolp backend)
+       (not (fboundp backend))
+       (ignore-errors (require backend nil t)))
+
+  (if (or (symbolp backend)
+          (functionp backend))
+      (if (ignore-errors (funcall backend 'init) t)
+          (put backend 'company-init t)
+        (message "Company back-end '%s' could not be initialized"
+                 backend))
+    (mapc 'company-init-backend backend)))
 
 ;;;###autoload
 (define-minor-mode company-mode
@@ -549,10 +596,27 @@ keymap during active completions (`company-active-map'):
 
 (defun company-in-string-or-comment ()
   (let ((ppss (syntax-ppss)))
-    (or (nth 3 ppss) (nth 4 ppss) (nth 7 ppss))))
+    (or (car (setq ppss (nthcdr 3 ppss)))
+        (car (setq ppss (cdr ppss)))
+        (nth 3 ppss))))
 
 (defun company-call-backend (&rest args)
-  (apply 'company-backend args))
+  (if (functionp company-backend)
+      (apply company-backend args)
+    (apply 'company--multi-backend-adapter company-backend args)))
+
+(defun company--multi-backend-adapter (backends command &rest args)
+  (case command
+    ('candidates
+     (apply 'append (mapcar (lambda (backend) (apply backend command args))
+                            backends)))
+    ('sorted nil)
+    ('duplicates t)
+    (otherwise
+     (let (value)
+       (dolist (backend backends)
+         (when (setq value (apply backend command args))
+           (return value)))))))
 
 ;;; completion mechanism ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -757,34 +821,34 @@ keymap during active completions (`company-active-map'):
     ;; Don't complete existing candidates, fetch new ones.
     (setq company-candidates-cache nil))
   (let ((new-prefix (company-call-backend 'prefix)))
-    (unless (and (= (- (point) (length new-prefix))
-                    (- company-point (length company-prefix)))
-                 (or (equal company-prefix new-prefix)
-                     (let ((c (company-calculate-candidates new-prefix)))
-                       ;; t means complete/unique.
-                       (if (eq c t)
-                           (progn (company-cancel new-prefix) t)
-                         (when (consp c)
-                           (setq company-prefix new-prefix)
-                           (company-update-candidates c)
-                           t)))))
-      (if (company-auto-complete-p company-point (point))
-          (save-excursion
-            (goto-char company-point)
-            (company-complete-selection)
-            (setq company-candidates nil))
-        (if (not (and (company-incremental-p company-prefix new-prefix)
-                      (company-require-match-p)))
-            (progn
-              (when (equal company-prefix (car company-candidates))
-                ;; cancel, but last input was actually success
-                (company-cancel company-prefix))
-              (setq company-candidates nil))
-          (backward-delete-char (length new-prefix))
-          (insert company-prefix)
-          (ding)
-          (message "Matching input is required")))
-      company-candidates)))
+    (if (= (- (point) (length new-prefix))
+           (- company-point (length company-prefix)))
+        (unless (or (equal company-prefix new-prefix)
+                    (let ((c (company-calculate-candidates new-prefix)))
+                      ;; t means complete/unique.
+                      (if (eq c t)
+                          (progn (company-cancel new-prefix) t)
+                        (when (consp c)
+                          (setq company-prefix new-prefix)
+                          (company-update-candidates c)
+                          t))))
+          (if (not (and (company-incremental-p company-prefix new-prefix)
+                        (company-require-match-p)))
+              (progn
+                (when (equal company-prefix (car company-candidates))
+                  ;; cancel, but last input was actually success
+                  (company-cancel company-prefix))
+                (setq company-candidates nil))
+            (backward-delete-char (length new-prefix))
+            (insert company-prefix)
+            (ding)
+            (message "Matching input is required")))
+      (when (company-auto-complete-p company-point (point))
+        (save-excursion
+          (goto-char company-point)
+          (company-complete-selection)))
+      (setq company-candidates nil))
+    company-candidates))
 
 (defun company-begin ()
   (when (and (not (and company-candidates (company-continue)))
@@ -794,9 +858,14 @@ keymap during active completions (`company-active-map'):
                            ;; prefer manual override
                            (list company-backend)
                          company-backends))
-        (when (and (get backend 'company-init)
-                   (functionp backend)
-                   (setq prefix (funcall backend 'prefix)))
+        (setq prefix
+              (if (or (symbolp backend)
+                      (functionp backend))
+                  (when (or (not (symbolp backend))
+                            (get backend 'company-init))
+                    (funcall backend 'prefix))
+                (company--multi-backend-adapter backend 'prefix)))
+        (when prefix
           (when (and (stringp prefix)
                      (>= (length prefix) company-minimum-prefix-length))
             (setq company-backend backend
@@ -1412,7 +1481,7 @@ Example:
                       (setq remainder (format "...(%d)" remainder))))
 
     (decf selection company-tooltip-offset)
-    (setq width (min (length previous) (length remainder))
+    (setq width (max (length previous) (length remainder))
           lines (nthcdr company-tooltip-offset company-candidates)
           len (min limit len)
           lines-copy lines)