;;
;;; 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'.
;;
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:
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.
"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
(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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 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)))
;; 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
(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)