]> code.delx.au - gnu-emacs-elpa/commitdiff
Support the keyword :with
authorDmitry Gutov <dgutov@yandex.ru>
Sun, 16 Mar 2014 03:57:56 +0000 (05:57 +0200)
committerDmitry Gutov <dgutov@yandex.ru>
Sun, 16 Mar 2014 04:11:11 +0000 (06:11 +0200)
Closes #79

NEWS.md
company-tests.el
company-yasnippet.el
company.el

diff --git a/NEWS.md b/NEWS.md
index 3b4ae780caa55077849550658cc7f58dee79f3b9..8ee50e03984e51b441077eb01b3dee988e5c2e2c 100644 (file)
--- a/NEWS.md
+++ b/NEWS.md
@@ -2,6 +2,8 @@
 
 ## Next
 
+* Group of back-ends can now contain keyword `:with`, which makes all back-ends
+  after it to be skipped for prefix calculation.
 * New function `company-version`.
 * New bundled back-end `company-yasnippet`.
 * Completion candidates returned from grouped back-ends are tagged to remember
index 4ac59909256e1834db9ecf2b0033abb5f853e9e5..5a2608632ffb0009a2b3f7f8d3deef3cd3156460 100644 (file)
       (should (equal "13" (company-call-backend 'post-completion (nth 2 candidates))))
       (should (equal "42" (company-call-backend 'post-completion (nth 3 candidates)))))))
 
+(ert-deftest company-multi-backend-handles-keyword-with ()
+  (let ((primo (lambda (command &optional arg)
+                 (case command
+                   (prefix "a")
+                   (candidates '("abb" "abc" "abd")))))
+        (secundo (lambda (command &optional arg)
+                   (case command
+                     (prefix "a")
+                     (candidates '("acc" "acd"))))))
+    (let ((company-backend (list 'ignore 'ignore :with secundo)))
+      (should (null (company-call-backend 'prefix))))
+    (let ((company-backend (list 'ignore primo :with secundo)))
+      (should (equal "a" (company-call-backend 'prefix)))
+      (should (equal '("abb" "abc" "abd" "acc" "acd")
+                     (company-call-backend 'candidates "a"))))))
+
 (ert-deftest company-begin-backend-failure-doesnt-break-company-backends ()
   (with-temp-buffer
     (insert "a")
index 27c6812c71cf154e8c9c8cda8c42f6e9e71df6bd..ae370c78feca440e0eb64cc024604e3fd88fb111 100644 (file)
 (defun company-yasnippet (command &optional arg &rest ignore)
   "`company-mode' back-end for `yasnippet'.
 
-This back-end is supposed to be used in a particular way:
+This back-end should be used with care, because as long as there are
+snippets defined for the current major mode, this back-end will always
+shadow back-ends that come after it.  Recommended usages:
 
-* In a buffer-local value of `company-backends'.
-* Grouped with a backend or several that provide actual text completions.
-
-Neither condition is mandatory, but as long as there are snippets defined
-for the current major mode, this back-end will always shadow back-ends that
-come after it. So any other back-ends intended to be used in the current
-buffer should be grouped with it.  Example config:
+* In a buffer-local value of `company-backends', grouped with a back-end or
+  several that provide actual text completions.
 
   (add-hook 'js-mode-hook
             (lambda ()
               (set (make-local-variable 'company-backends)
-                   '((company-dabbrev-code company-yasnippet))))"
+                   '((company-dabbrev-code company-yasnippet)))))
+
+* After keyword `:with', grouped with other back-ends.
+
+  (push '(company-semantic :with company-yasnippet) company-backends)
+
+* Not in `company-backends', just bound to a key.
+
+  (global-set-key (kbd \"C-c y\") 'company-yasnippet)
+"
   (interactive (list 'interactive))
   (case command
     (interactive (company-begin-backend 'company-yasnippet))
index da2e9406a666d397a4eada62fc56f110def44723..a148fa57e584b5c2b7904929b6dfe408703e0bc7 100644 (file)
@@ -306,9 +306,6 @@ If this many lines are not available, prefer to display the tooltip above."
                                company-keywords)
                               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.
 
 `company-begin-backend' can be used to start a specific back-end,
 `company-other-backend' will skip to the next matching back-end in the list.
@@ -383,7 +380,22 @@ modify it, e.g. to expand a snippet.
 
 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."
+`company-begin-backend' to start itself in that case.
+
+Grouped back-ends:
+
+An element of `company-backends' can also itself be a list of back-ends,
+then it's considered to be a \"grouped\" back-end.
+
+When possible, commands taking a candidate as an argument are dispatched to
+the back-end it came from.  In other cases, the first non-nil value among
+all the back-ends is returned.
+
+The latter is the case for the `prefix' command.  But if the group contains
+the keyword `:with', the back-ends after it are ignored for this command.
+
+The completions from back-ends in a group are merged (but only from those
+that return the same `prefix')."
   :type `(repeat
           (choice
            :tag "Back-end"
@@ -395,6 +407,7 @@ does not know about.  It should also be callable interactively and use
                            ,@(mapcar (lambda (b)
                                        `(const :tag ,(cdr b) ,(car b)))
                                      company-safe-backends)
+                           (const :tag "With" :with)
                            (symbol :tag "User defined"))))))
 
 (put 'company-backends 'safe-local-variable 'company-safe-backends-p)
@@ -587,7 +600,9 @@ The work-around consists of adding a newline.")
    ;; No initialization for lambdas.
    ((functionp backend) t)
    (t ;; Must be a list.
-    (mapc 'company-init-backend backend))))
+    (dolist (b backend)
+      (unless (keywordp b)
+        (company-init-backend b))))))
 
 (defvar company-default-lighter " company")
 
@@ -776,6 +791,10 @@ means that `company-mode' is always turned on except in `message-mode' buffers."
                         when (not (and (symbolp b)
                                        (eq 'failed (get b 'company-init))))
                         collect b)))
+    (setq backends
+          (if (eq command 'prefix)
+              (butlast backends (length (member :with backends)))
+            (delq :with backends)))
     (case command
       (candidates
        ;; Small perf optimization: don't tag the candidates received