cases (except for `duplicates' and `sorted'), the first non-nil value among
all the backends is returned.
-The group can also contain keywords. Currently, `:with' and `:sorted'
+The group can also contain keywords. Currently, `:with' and `:separate'
keywords are defined. If the group contains keyword `:with', the backends
listed after this keyword are ignored for the purpose of the `prefix'
-command. If the group contains keyword `:sorted', the final list of
-candidates is not sorted after concatenation.
+command. If the group contains keyword `:separate', the candidates that
+come from different backends are sorted separately in the combined list.
Asynchronous backends
=====================
(let ((backends (cl-loop for b in backends
when (not (and (symbolp b)
(eq 'failed (get b 'company-init))))
- collect b)))
+ collect b))
+ (separate (memq :separate backends)))
(when (eq command 'prefix)
(setq backends (butlast backends (length (member :with backends)))))
- (unless (memq command '(sorted))
- (setq backends (cl-delete-if #'keywordp backends)))
+ (setq backends (cl-delete-if #'keywordp backends))
(pcase command
(`candidates
- (company--multi-backend-adapter-candidates backends (car args)))
- (`sorted (memq :sorted backends))
- (`duplicates t)
+ (company--multi-backend-adapter-candidates backends (car args) separate))
+ (`sorted separate)
+ (`duplicates (not separate))
((or `prefix `ignore-case `no-cache `require-match)
(let (value)
(cl-dolist (backend backends)
(car backends))))
(apply backend command args))))))))
-(defun company--multi-backend-adapter-candidates (backends prefix)
- (let ((pairs (cl-loop for backend in (cdr backends)
+(defun company--multi-backend-adapter-candidates (backends prefix separate)
+ (let ((pairs (cl-loop for backend in backends
when (equal (company--prefix-str
(funcall backend 'prefix))
prefix)
collect (cons (funcall backend 'candidates prefix)
- (let ((b backend))
- (lambda (candidates)
- (mapcar
- (lambda (str)
- (propertize str 'company-backend b))
- candidates)))))))
- (when (equal (company--prefix-str (funcall (car backends) 'prefix)) prefix)
- ;; Small perf optimization: don't tag the candidates received
- ;; from the first backend in the group.
- (push (cons (funcall (car backends) 'candidates prefix)
- 'identity)
- pairs))
+ (company--multi-candidates-mapper
+ backend
+ separate
+ ;; Small perf optimization: don't tag the
+ ;; candidates received from the first
+ ;; backend in the group.
+ (not (eq backend (car backends))))))))
(company--merge-async pairs (lambda (values) (apply #'append values)))))
+(defun company--multi-candidates-mapper (backend separate tag)
+ (lambda (candidates)
+ (when separate
+ (let ((company-backend backend))
+ (setq candidates
+ (company--preprocess-candidates candidates))))
+ (when tag
+ (setq candidates
+ (mapcar
+ (lambda (str)
+ (propertize str 'company-backend backend))
+ candidates)))
+ candidates))
+
(defun company--merge-async (pairs merger)
(let ((async (cl-loop for pair in pairs
thereis