;;; company.el --- Modular text completion framework -*- lexical-binding: t -*-
-;; Copyright (C) 2009-2014 Free Software Foundation, Inc.
+;; Copyright (C) 2009-2015 Free Software Foundation, Inc.
;; Author: Nikolaj Schumacher
;; Maintainer: Dmitry Gutov <dgutov@yandex.ru>
;; URL: http://company-mode.github.io/
-;; Version: 0.8.8-cvs
+;; Version: 0.8.9-cvs
;; Keywords: abbrev, convenience, matching
;; Package-Requires: ((emacs "24.1") (cl-lib "0.5"))
(put 'company-backends 'safe-local-variable 'company-safe-backends-p)
(defcustom company-transformers nil
- "Functions to change the list of candidates received from backends,
-after sorting and removal of duplicates (if appropriate).
-Each function gets called with the return value of the previous one."
+ "Functions to change the list of candidates received from backends.
+
+Each function gets called with the return value of the previous one.
+The first one gets passed the list of candidates, already sorted and
+without duplicates."
:type '(choice
(const :tag "None" nil)
(const :tag "Sort by occurrence" (company-sort-by-occurrence))
(define-key keymap (kbd "M-p") 'company-select-previous)
(define-key keymap (kbd "<down>") 'company-select-next-or-abort)
(define-key keymap (kbd "<up>") 'company-select-previous-or-abort)
+ (define-key keymap [remap scroll-up-command] 'company-next-page)
+ (define-key keymap [remap scroll-down-command] 'company-previous-page)
(define-key keymap [down-mouse-1] 'ignore)
(define-key keymap [down-mouse-3] 'ignore)
(define-key keymap [mouse-1] 'company-complete-mouse)
(symbol-name backend))))
(setq company-lighter (format " company-<%s>" name)))))))
-(defun company-apply-predicate (candidates predicate)
- (let (new)
- (dolist (c candidates)
- (when (funcall predicate c)
- (push c new)))
- (nreverse new)))
-
(defun company-update-candidates (candidates)
(setq company-candidates-length (length candidates))
(if (> company-selection 0)
(cl-return t)))))
(progn
;; No cache match, call the backend.
- (setq candidates (company--fetch-candidates prefix))
- ;; Save in cache (without the predicate applied).
+ (setq candidates (company--preprocess-candidates
+ (company--fetch-candidates prefix)))
+ ;; Save in cache.
(push (cons prefix candidates) company-candidates-cache)))
- (setq candidates (company--process-candidates candidates))
+ ;; Only now apply the predicate and transformers.
+ (setq candidates (company--postprocess-candidates candidates))
(when candidates
(if (or (cdr candidates)
(not (eq t (compare-strings (car candidates) nil nil
;; or the fetcher called us back right away.
(setq res candidates)
(setq company-backend backend
- company-candidates-cache (list (cons prefix candidates)))
+ company-candidates-cache
+ (list (cons prefix
+ (company--preprocess-candidates candidates))))
(company-idle-begin buf win tick pt)))))
;; FIXME: Relying on the fact that the callers
;; will interpret nil as "do nothing" is shaky.
(or res
(progn (setq res 'done) nil)))))
-(defun company--process-candidates (candidates)
- (when company-candidates-predicate
- (setq candidates
- (company-apply-predicate candidates
- company-candidates-predicate)))
+(defun company--preprocess-candidates (candidates)
(unless (company-call-backend 'sorted)
- (setq candidates (sort (copy-sequence candidates) 'string<)))
+ (setq candidates (sort candidates 'string<)))
(when (company-call-backend 'duplicates)
(company--strip-duplicates candidates))
+ candidates)
+
+(defun company--postprocess-candidates (candidates)
+ (when (or company-candidates-predicate company-transformers)
+ (setq candidates (copy-sequence candidates)))
+ (when company-candidates-predicate
+ (setq candidates (cl-delete-if-not company-candidates-predicate candidates)))
(company--transform-candidates candidates))
(defun company--strip-duplicates (candidates)
- (let ((c2 candidates))
+ (let ((c2 candidates)
+ (annos 'unk))
(while c2
(setcdr c2
- (let ((str (car c2))
- (anno 'unk))
- (pop c2)
+ (let ((str (pop c2)))
(while (let ((str2 (car c2)))
(if (not (equal str str2))
- nil
- (when (eq anno 'unk)
- (setq anno (company-call-backend
- 'annotation str)))
- (equal anno
- (company-call-backend
- 'annotation str2))))
+ (progn
+ (setq annos 'unk)
+ nil)
+ (when (eq annos 'unk)
+ (setq annos (list (company-call-backend
+ 'annotation str))))
+ (let ((anno2 (company-call-backend
+ 'annotation str2)))
+ (if (member anno2 annos)
+ t
+ (push anno2 annos)
+ nil))))
(pop c2))
c2)))))
(defvar-local company-search-string "")
-(defvar-local company-search-lighter " Search: \"\"")
+(defvar company-search-lighter '(" "
+ (company-search-filtering "Filter" "Search")
+ ": \""
+ company-search-string
+ "\""))
(defvar-local company-search-filtering nil
"Non-nil to filter the completion candidates by the search string")
(let* ((pos (company--search new (nthcdr company-selection company-candidates))))
(if (null pos)
(ding)
- (setq company-search-string new
- company-search-lighter (format " %s: \"%s\""
- (if company-search-filtering
- "Filter"
- "Search")
- new))
+ (setq company-search-string new)
(company-set-selection (+ company-selection pos) t))))
(defun company--search-assert-input ()
(defun company-search-delete-char ()
(interactive)
(company--search-assert-enabled)
- (unless (string= company-search-string "")
+ (if (string= company-search-string "")
+ (ding)
(let ((ss (substring company-search-string 0 -1)))
(when company-search-filtering
(company--search-update-predicate ss))
(if (company-manual-begin)
(progn
(setq company--search-old-selection company-selection)
- (company-call-frontends 'update))
+ (company-call-frontends 'update)
+ (company-enable-overriding-keymap company-search-map))
(setq company-search-mode nil))
(kill-local-variable 'company-search-string)
- (kill-local-variable 'company-search-lighter)
(kill-local-variable 'company-search-filtering)
(kill-local-variable 'company--search-old-selection)
(when company-backend
The command `company-search-toggle-filtering' (\\[company-search-toggle-filtering])
uses the search string to filter the completion candidates."
(interactive)
- (company-search-mode 1)
- (company-enable-overriding-keymap company-search-map))
+ (company-search-mode 1))
(defvar company-filter-map
(let ((keymap (make-keymap)))
(company-abort)
(company--unread-last-input)))
+(defun company-next-page ()
+ "Select the candidate one page further."
+ (interactive)
+ (when (company-manual-begin)
+ (company-set-selection (+ company-selection
+ company-tooltip-limit))))
+
+(defun company-previous-page ()
+ "Select the candidate one page earlier."
+ (interactive)
+ (when (company-manual-begin)
+ (company-set-selection (- company-selection
+ company-tooltip-limit))))
+
(defvar company-pseudo-tooltip-overlay)
(defvar company-tooltip-offset)
(dotimes (_ len)
(let* ((value (pop lines-copy))
(annotation (company-call-backend 'annotation value)))
- (setq value (company--clean-string value))
+ (setq value (company--clean-string (company-reformat value)))
(when annotation
(when company-tooltip-align-annotations
;; `lisp-completion-at-point' adds a space.
(dotimes (i len)
(let* ((item (pop items))
- (str (company-reformat (car item)))
+ (str (car item))
(annotation (cdr item))
(right (company-space-string company-tooltip-margin))
(width width))