+ (unless (company-keep this-command)
+ (condition-case err
+ (progn
+ (setq company--this-command this-command)
+ (unless (equal (point) company-point)
+ (company-begin))
+ (when company-candidates
+ (company-call-frontends 'post-command))
+ (when (numberp company-idle-delay)
+ (setq company-timer
+ (run-with-timer company-idle-delay nil 'company-idle-begin
+ (current-buffer) (selected-window)
+ (buffer-chars-modified-tick) (point)))))
+ (error (message "Company: An error occurred in post-command")
+ (message "%s" (error-message-string err))
+ (company-cancel))))
+ (company-install-map))
+
+;;; search ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar company-search-string nil)
+(make-variable-buffer-local 'company-search-string)
+
+(defvar company-search-lighter " Search: \"\"")
+(make-variable-buffer-local 'company-search-lighter)
+
+(defvar company-search-old-map nil)
+(make-variable-buffer-local 'company-search-old-map)
+
+(defvar company-search-old-selection 0)
+(make-variable-buffer-local 'company-search-old-selection)
+
+(defun company-search (text lines)
+ (let ((quoted (regexp-quote text))
+ (i 0))
+ (dolist (line lines)
+ (when (string-match quoted line (length company-prefix))
+ (return i))
+ (incf i))))
+
+(defun company-search-printing-char ()
+ (interactive)
+ (company-search-assert-enabled)
+ (setq company-search-string
+ (concat (or company-search-string "") (string last-command-event))
+ company-search-lighter (concat " Search: \"" company-search-string
+ "\""))
+ (let ((pos (company-search company-search-string
+ (nthcdr company-selection company-candidates))))
+ (if (null pos)
+ (ding)
+ (company-set-selection (+ company-selection pos) t))))
+
+(defun company-search-repeat-forward ()
+ "Repeat the incremental search in completion candidates forward."
+ (interactive)
+ (company-search-assert-enabled)
+ (let ((pos (company-search company-search-string
+ (cdr (nthcdr company-selection
+ company-candidates)))))
+ (if (null pos)
+ (ding)
+ (company-set-selection (+ company-selection pos 1) t))))
+
+(defun company-search-repeat-backward ()
+ "Repeat the incremental search in completion candidates backwards."
+ (interactive)
+ (company-search-assert-enabled)
+ (let ((pos (company-search company-search-string
+ (nthcdr (- company-candidates-length
+ company-selection)
+ (reverse company-candidates)))))
+ (if (null pos)
+ (ding)
+ (company-set-selection (- company-selection pos 1) t))))
+
+(defun company-create-match-predicate ()
+ (setq company-candidates-predicate
+ `(lambda (candidate)
+ ,(if company-candidates-predicate
+ `(and (string-match ,company-search-string candidate)
+ (funcall ,company-candidates-predicate
+ candidate))
+ `(string-match ,company-search-string candidate))))
+ (company-update-candidates
+ (company-apply-predicate company-candidates company-candidates-predicate))
+ ;; Invalidate cache.
+ (setq company-candidates-cache (cons company-prefix company-candidates)))
+
+(defun company-filter-printing-char ()
+ (interactive)
+ (company-search-assert-enabled)
+ (company-search-printing-char)
+ (company-create-match-predicate)
+ (company-call-frontends 'update))
+
+(defun company-search-kill-others ()
+ "Limit the completion candidates to the ones matching the search string."
+ (interactive)
+ (company-search-assert-enabled)
+ (company-create-match-predicate)
+ (company-search-mode 0)
+ (company-call-frontends 'update))
+
+(defun company-search-abort ()
+ "Abort searching the completion candidates."
+ (interactive)
+ (company-search-assert-enabled)
+ (company-set-selection company-search-old-selection t)
+ (company-search-mode 0))
+
+(defun company-search-other-char ()
+ (interactive)
+ (company-search-assert-enabled)
+ (company-search-mode 0)
+ (when last-input-event
+ (clear-this-command-keys t)
+ (setq unread-command-events (list last-input-event))))
+
+(defvar company-search-map
+ (let ((i 0)
+ (keymap (make-keymap)))
+ (if (fboundp 'max-char)
+ (set-char-table-range (nth 1 keymap) (cons #x100 (max-char))
+ 'company-search-printing-char)
+ (with-no-warnings
+ ;; obselete in Emacs 23
+ (let ((l (generic-character-list))
+ (table (nth 1 keymap)))
+ (while l
+ (set-char-table-default table (car l) 'company-search-printing-char)
+ (setq l (cdr l))))))
+ (define-key keymap [t] 'company-search-other-char)
+ (while (< i ?\s)
+ (define-key keymap (make-string 1 i) 'company-search-other-char)
+ (incf i))
+ (while (< i 256)
+ (define-key keymap (vector i) 'company-search-printing-char)
+ (incf i))
+ (let ((meta-map (make-sparse-keymap)))
+ (define-key keymap (char-to-string meta-prefix-char) meta-map)
+ (define-key keymap [escape] meta-map))
+ (define-key keymap (vector meta-prefix-char t) 'company-search-other-char)
+ (define-key keymap "\e\e\e" 'company-search-other-char)
+ (define-key keymap [escape escape escape] 'company-search-other-char)
+
+ (define-key keymap "\C-g" 'company-search-abort)
+ (define-key keymap "\C-s" 'company-search-repeat-forward)
+ (define-key keymap "\C-r" 'company-search-repeat-backward)
+ (define-key keymap "\C-o" 'company-search-kill-others)
+ keymap)
+ "Keymap used for incrementally searching the completion candidates.")
+
+(define-minor-mode company-search-mode
+ "Search mode for completion candidates.
+Don't start this directly, use `company-search-candidates' or
+`company-filter-candidates'."
+ nil company-search-lighter nil
+ (if company-search-mode
+ (if (company-manual-begin)
+ (progn
+ (setq company-search-old-selection company-selection)
+ (company-call-frontends 'update))
+ (setq company-search-mode nil))
+ (kill-local-variable 'company-search-string)
+ (kill-local-variable 'company-search-lighter)
+ (kill-local-variable 'company-search-old-selection)
+ (company-enable-overriding-keymap company-active-map)))
+
+(defsubst company-search-assert-enabled ()
+ (company-assert-enabled)
+ (unless company-search-mode
+ (company-uninstall-map)
+ (error "Company not in search mode")))
+
+(defun company-search-candidates ()
+ "Start searching the completion candidates incrementally.
+
+\\<company-search-map>Search can be controlled with the commands:
+- `company-search-repeat-forward' (\\[company-search-repeat-forward])
+- `company-search-repeat-backward' (\\[company-search-repeat-backward])
+- `company-search-abort' (\\[company-search-abort])
+
+Regular characters are appended to the search string.
+
+The command `company-search-kill-others' (\\[company-search-kill-others]) uses
+ the search string to limit the completion candidates."
+ (interactive)
+ (company-search-mode 1)
+ (company-enable-overriding-keymap company-search-map))
+
+(defvar company-filter-map
+ (let ((keymap (make-keymap)))
+ (define-key keymap [remap company-search-printing-char]
+ 'company-filter-printing-char)
+ (set-keymap-parent keymap company-search-map)
+ keymap)
+ "Keymap used for incrementally searching the completion candidates.")
+
+(defun company-filter-candidates ()
+ "Start filtering the completion candidates incrementally.
+This works the same way as `company-search-candidates' immediately
+followed by `company-search-kill-others' after each input."
+ (interactive)
+ (company-search-mode 1)
+ (company-enable-overriding-keymap company-filter-map))