## 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
(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")
(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))
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.
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"
,@(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)
;; 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")
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