-;;; company.el --- Extensible inline text completion mechanism
+;;; company.el --- Modular in-buffer completion framework -*- lexical-binding: t -*-
;; Copyright (C) 2009-2013 Free Software Foundation, Inc.
;; Author: Nikolaj Schumacher
-;; Version: 0.5
+;; Maintainer: Dmitry Gutov <dgutov@yandex.ru>
+;; Version: 0.6.7
;; Keywords: abbrev, convenience, matching
-;; URL: http://nschum.de/src/emacs/company-mode/
+;; URL: http://company-mode.github.com/
;; Compatibility: GNU Emacs 22.x, GNU Emacs 23.x, GNU Emacs 24.x
;; This file is part of GNU Emacs.
;;
;;; Change Log:
;;
-;; Switching tags now works correctly in `company-etags'.
-;; Clang completions now include macros and are case-sensitive.
-;; Added `company-capf': completion adapter using
-;; `completion-at-point-functions'. (Stefan Monnier)
-;; `company-elisp' has some improvements.
-;; Instead of `overrriding-terminal-local-map', we're now using
-;; `emulation-mode-map-alists' (experimental). This largely means that when
-;; the completion keymap is active, other minor modes' keymaps are still
-;; used, so, for example, it's not as easy to circumvent `paredit-mode'
-;; accidentally when it's enabled.
-;; Fixed two old tooltip annoyances.
-;; Some performance improvements.
-;; `company-clang' now shows meta information, too.
-;; Candidates from grouped back-ends are merged more conservatively: only
-;; back-ends that return the same prefix at point are used.
-;; Loading of `nxml', `semantic', `pysmell' and `ropemacs' is now deferred.
-;; `company-pysmell' is not used by default anymore.
-;;
-;; 2010-02-24 (0.5)
-;; `company-ropemacs' now provides location and docs. (Fernando H. Silva)
-;; Added `company-with-candidate-inserted' macro.
-;; Added `company-clang' back-end.
-;; Added new mechanism for non-consecutive insertion.
-;; (So far only used by clang for ObjC.)
-;; The semantic back-end now shows meta information for local symbols.
-;; Added compatibility for CEDET in Emacs 23.2 and from CVS. (Oleg Andreev)
-;;
-;; 2009-05-07 (0.4.3)
-;; Added `company-other-backend'.
-;; Idle completion no longer interrupts multi-key command input.
-;; Added `company-ropemacs' and `company-pysmell' back-ends.
-;;
-;; 2009-04-25 (0.4.2)
-;; In C modes . and -> now count towards `company-minimum-prefix-length'.
-;; Reverted default front-end back to `company-preview-if-just-one-frontend'.
-;; The pseudo tooltip will no longer be clipped at the right window edge.
-;; Added `company-tooltip-minimum'.
-;; Windows compatibility fixes.
-;;
-;; 2009-04-19 (0.4.1)
-;; Added `global-company-mode'.
-;; Performance enhancements.
-;; Added `company-eclim' back-end.
-;; Added safer workaround for Emacs `posn-col-row' bug.
-;;
-;; 2009-04-18 (0.4)
-;; Automatic completion is now aborted if the prefix gets too short.
-;; 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'.
-;;
-;; 2009-04-15 (0.3.1)
-;; Added 'stop prefix to prevent dabbrev from completing inside of symbols.
-;; Fixed issues with tabbar-mode and line-spacing.
-;; Performance enhancements.
-;;
-;; 2009-04-12 (0.3)
-;; Added `company-begin-commands' option.
-;; Added abbrev, tempo and Xcode back-ends.
-;; Back-ends are now interactive. You can start them with M-x backend-name.
-;; Added `company-begin-with' for starting company from elisp-code.
-;; Added hooks.
-;; Added `company-require-match' and `company-auto-complete' options.
-;;
-;; 2009-04-05 (0.2.1)
-;; Improved Emacs Lisp back-end behavior for local variables.
-;; Added `company-elisp-detect-function-context' option.
-;; The mouse can now be used for selection.
-;;
-;; 2009-03-22 (0.2)
-;; Added `company-show-location'.
-;; Added etags back-end.
-;; Added work-around for end-of-buffer bug.
-;; Added `company-filter-candidates'.
-;; More local Lisp variables are now included in the candidates.
-;;
-;; 2009-03-21 (0.1.5)
-;; Fixed elisp documentation buffer always showing the same doc.
-;; Added `company-echo-strip-common-frontend'.
-;; Added `company-show-numbers' option and M-0 ... M-9 default bindings.
-;; Don't hide the echo message if it isn't shown.
-;;
-;; 2009-03-20 (0.1)
-;; Initial release.
+;; See NEWS.md in the repository.
;;; Code:
:group 'matching)
(defface company-tooltip
- '((t :background "yellow"
- :foreground "black"))
+ '((default :foreground "black")
+ (((class color) (min-colors 88) (background light))
+ (:background "cornsilk"))
+ (((class color) (min-colors 88) (background dark))
+ (:background "yellow")))
"Face used for the tool tip."
:group 'company)
(defface company-tooltip-selection
'((default :inherit company-tooltip)
- (((class color) (min-colors 88)) (:background "orange1"))
+ (((class color) (min-colors 88) (background light))
+ (:background "light blue"))
+ (((class color) (min-colors 88) (background dark))
+ (:background "orange1"))
(t (:background "green")))
"Face used for the selection in the tool tip."
:group 'company)
:group 'company)
(defface company-tooltip-common
- '((t :inherit company-tooltip
- :foreground "red"))
+ '((default :inherit company-tooltip)
+ (((background light))
+ :foreground "darkred")
+ (((background dark))
+ :foreground "red"))
"Face used for the common completion in the tool tip."
:group 'company)
(defface company-tooltip-common-selection
- '((t :inherit company-tooltip-selection
- :foreground "red"))
+ '((default :inherit company-tooltip-selection)
+ (((background light))
+ :foreground "darkred")
+ (((background dark))
+ :foreground "red"))
"Face used for the selected common completion in the tool tip."
:group 'company)
number where the completion candidate was defined.
`require-match': If this value is t, the user is not allowed to enter anything
-not offering as a candidate. Use with care! The default value nil gives the
+not offered as a candidate. Use with care! The default value nil gives the
user that choice with `company-require-match'. Return value 'never overrides
that option the other way around.
+`init': Called once for each buffer, the back-end can check for external
+programs and files and load any required libraries. Raising an error here will
+show up in message log once, and the backend will not be used for completion.
+
+`post-completion': Called after a completion candidate has been inserted into
+the buffer. The second argument is the candidate. Can be used to modify it,
+e.g. to expand a snippet.
+
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."
(defcustom company-completion-finished-hook nil
"Hook run when company successfully completes.
-The hook is called with the selected candidate as an argument."
+The hook is called with the selected candidate as an argument.
+
+If you indend to use it to post-process candidates from a specific back-end,
+consider using the `post-completion' command instead."
:group 'company
:type 'hook)
This can also be a function, which is called with the new input and should
return non-nil if company should auto-complete.
-A character that is part of a valid candidate never starts auto-completion."
+A character that is part of a valid candidate never triggers auto-completion."
:group 'company
:type '(choice (string :tag "Characters")
(set :tag "Syntax"
(define-key keymap "\C-g" 'company-abort)
(define-key keymap (kbd "M-n") 'company-select-next)
(define-key keymap (kbd "M-p") 'company-select-previous)
- (define-key keymap (kbd "<down>") 'company-select-next)
- (define-key keymap (kbd "<up>") '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 [down-mouse-1] 'ignore)
(define-key keymap [down-mouse-3] 'ignore)
(define-key keymap [mouse-1] 'company-complete-mouse)
(define-key keymap [up-mouse-1] 'ignore)
(define-key keymap [up-mouse-3] 'ignore)
(define-key keymap [return] 'company-complete-selection)
+ (define-key keymap (kbd "RET") 'company-complete-selection)
(define-key keymap [tab] 'company-complete-common)
+ (define-key keymap (kbd "TAB") 'company-complete-common)
(define-key keymap (kbd "<f1>") 'company-show-doc-buffer)
(define-key keymap "\C-w" 'company-show-location)
(define-key keymap "\C-s" 'company-search-candidates)
(company-cancel)
(kill-local-variable 'company-point)))
-(define-globalized-minor-mode global-company-mode company-mode
- (lambda () (unless (or noninteractive (eq (aref (buffer-name) 0) ?\s))
- (company-mode 1))))
+;;;###autoload
+(define-globalized-minor-mode global-company-mode company-mode company-mode-on)
+
+(defun company-mode-on ()
+ (unless (or noninteractive (eq (aref (buffer-name) 0) ?\s))
+ (company-mode 1)))
(defsubst company-assert-enabled ()
(unless company-mode
(apply 'company--multi-backend-adapter company-backend args)))
(defun company--multi-backend-adapter (backends command &rest args)
- (let ((backends (remove-if (lambda (b) (eq 'failed (get b 'company-init)))
- backends)))
+ (let ((backends (loop for b in backends
+ when (not (and (symbolp b)
+ (eq 'failed (get b 'company-init))))
+ collect b)))
(case command
(candidates
(loop for backend in backends
when (equal (funcall backend 'prefix)
(car args))
- nconc (apply backend 'candidates args)))
+ append (apply backend 'candidates args)))
(sorted nil)
(duplicates t)
(otherwise
"Non-nil, if explicit completion took place.")
(make-variable-buffer-local 'company--explicit-action)
+(defvar company--auto-completion nil
+ "Non-nil when current candidate is being completed automatically.
+Controlled by `company-auto-complete'.")
+
(defvar company--point-max nil)
(make-variable-buffer-local 'company--point-max)
(push (cons company-prefix company-candidates) company-candidates-cache)
;; Calculate common.
(let ((completion-ignore-case (company-call-backend 'ignore-case)))
- (setq company-common (try-completion company-prefix company-candidates)))
+ (setq company-common (company--safe-candidate
+ (try-completion company-prefix company-candidates))))
(when (eq company-common t)
(setq company-candidates nil)))
+(defun company--safe-candidate (str)
+ (or (company-call-backend 'crop str)
+ str))
+
(defun company-calculate-candidates (prefix)
(let ((candidates (cdr (assoc prefix company-candidates-cache)))
(ignore-case (company-call-backend 'ignore-case)))
(while c2
(setcdr c2 (progn (while (equal (pop c2) (car c2)))
c2)))))))
- (if (and candidates
- (or (cdr candidates)
- (not (eq t (compare-strings (car candidates) nil nil
- prefix nil nil ignore-case)))))
- ;; Don't start when already completed and unique.
- candidates
- ;; Not the right place? maybe when setting?
- (and company-candidates t))))
+ (when candidates
+ (if (or (cdr candidates)
+ (not (eq t (compare-strings (car candidates) nil nil
+ prefix nil nil ignore-case))))
+ candidates
+ ;; Already completed and unique; don't start.
+ t))))
(defun company-idle-begin (buf win tick pos)
(and company-mode
(defun company-manual-begin ()
(interactive)
(setq company--explicit-action t)
- (company-auto-begin))
+ (unwind-protect
+ (company-auto-begin)
+ (unless company-candidates
+ (setq company--explicit-action nil))))
(defun company-other-backend (&optional backward)
(interactive (list current-prefix-arg))
;; auto-complete
(save-excursion
(goto-char company-point)
- (company-complete-selection)
+ (let ((company--auto-completion t))
+ (company-complete-selection))
nil))
((and (company--string-incremental-p company-prefix new-prefix)
(company-require-match-p))
(defun company--good-prefix-p (prefix)
(and (or (company-explicit-action-p)
- (>= (or (cdr-safe prefix) (length prefix))
- company-minimum-prefix-length))
+ (unless (eq prefix 'stop)
+ (>= (or (cdr-safe prefix) (length prefix))
+ company-minimum-prefix-length)))
(stringp (or (car-safe prefix) prefix))))
(defun company--continue ()
(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))))
+ (company--unread-last-input))
(defvar company-search-map
(let ((i 0)
(set-char-table-range (nth 1 keymap) (cons #x100 (max-char))
'company-search-printing-char)
(with-no-warnings
- ;; obselete in Emacs 23
+ ;; obsolete in Emacs 23
(let ((l (generic-character-list))
(table (nth 1 keymap)))
(while l
(when (company-manual-begin)
(company-set-selection (1- company-selection))))
+(defun company-select-next-or-abort ()
+ "Select the next candidate if more than one, else abort
+and invoke the normal binding."
+ (interactive)
+ (if (> company-candidates-length 1)
+ (company-select-next)
+ (company-abort)
+ (company--unread-last-input)))
+
+(defun company-select-previous-or-abort ()
+ "Select the previous candidate if more than one, else abort
+and invoke the normal binding."
+ (interactive)
+ (if (> company-candidates-length 1)
+ (company-select-previous)
+ (company-abort)
+ (company--unread-last-input)))
+
(defun company-select-mouse (event)
"Select the candidate picked by the mouse."
(interactive "e")
"Complete the selected candidate."
(interactive)
(when (company-manual-begin)
- (company-finish (nth company-selection company-candidates))))
+ (let ((result (nth company-selection company-candidates)))
+ (when company--auto-completion
+ (setq result (company--safe-candidate result)))
+ (company-finish result))))
(defun company-complete-common ()
"Complete the common part of all candidates."
(while (memq (setq cmd (key-binding (vector (list (read-event)))))
company--electric-commands)
(call-interactively cmd))
- (when last-input-event
- (clear-this-command-keys t)
- (setq unread-command-events (list last-input-event)))))))
+ (company--unread-last-input)))))
+
+(defun company--unread-last-input ()
+ (when last-input-event
+ (clear-this-command-keys t)
+ (setq unread-command-events (list last-input-event))))
(defun company-show-doc-buffer ()
"Temporarily show a buffer with the complete documentation for the selection."
(setq company-backend backend)
;; Return non-nil if active.
(or (company-manual-begin)
- (error "Cannot complete at point")))
+ (progn
+ (setq company-backend nil)
+ (error "Cannot complete at point"))))
(defun company-begin-with (candidates
&optional prefix-length require-match callback)
args))
(overlay-put ov 'company-column column)
- (overlay-put ov 'company-height (abs height))
- (overlay-put ov 'window (selected-window))))))
+ (overlay-put ov 'company-height height)))))
(defun company-pseudo-tooltip-show-at-point (pos)
(let ((col-row (company--col-row pos)))
(height (overlay-get company-pseudo-tooltip-overlay 'company-height)))
(overlay-put company-pseudo-tooltip-overlay 'company-before
(apply 'company--replacement-string
- (company--create-lines selection height)
+ (company--create-lines selection (abs height))
(overlay-get company-pseudo-tooltip-overlay
'company-replacement-args)))))
(overlay-get company-pseudo-tooltip-overlay 'company-before))
(overlay-put company-pseudo-tooltip-overlay 'window (selected-window))))
+(defun company-pseudo-tooltip-guard ()
+ (buffer-substring-no-properties
+ (point) (overlay-start company-pseudo-tooltip-overlay)))
+
(defun company-pseudo-tooltip-frontend (command)
- "A `company-mode' front-end similar to a tool-tip but based on overlays."
+ "`company-mode' front-end similar to a tool-tip but based on overlays."
(case command
(pre-command (company-pseudo-tooltip-hide-temporarily))
(post-command
0))
(new-height (company--pseudo-tooltip-height)))
(unless (and (>= (* old-height new-height) 0)
- (>= (abs old-height) (abs new-height)))
+ (>= (abs old-height) (abs new-height))
+ (equal (company-pseudo-tooltip-guard)
+ (overlay-get company-pseudo-tooltip-overlay
+ 'company-guard)))
;; Redraw needed.
(company-pseudo-tooltip-show-at-point (- (point)
- (length company-prefix)))))
+ (length company-prefix)))
+ (overlay-put company-pseudo-tooltip-overlay
+ 'company-guard (company-pseudo-tooltip-guard))))
(company-pseudo-tooltip-unhide))
(hide (company-pseudo-tooltip-hide)
(setq company-tooltip-offset 0))
(setq company-preview-overlay nil)))
(defun company-preview-frontend (command)
- "A `company-mode' front-end showing the selection as if it had been inserted."
+ "`company-mode' front-end showing the selection as if it had been inserted."
(case command
(pre-command (company-preview-hide))
(post-command (company-preview-show-at-point (point)))
(company-echo-show)))
(defun company-echo-frontend (command)
- "A `company-mode' front-end showing the candidates in the echo area."
+ "`company-mode' front-end showing the candidates in the echo area."
(case command
(post-command (company-echo-show-soon 'company-echo-format))
(hide (company-echo-hide))))
(defun company-echo-strip-common-frontend (command)
- "A `company-mode' front-end showing the candidates in the echo area."
+ "`company-mode' front-end showing the candidates in the echo area."
(case command
(post-command (company-echo-show-soon 'company-echo-strip-common-format))
(hide (company-echo-hide))))
(defun company-echo-metadata-frontend (command)
- "A `company-mode' front-end showing the documentation in the echo area."
+ "`company-mode' front-end showing the documentation in the echo area."
(case command
(post-command (company-echo-show-when-idle 'company-fetch-metadata))
(hide (company-echo-hide))))
-;; templates ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(autoload 'company-template-declare-template "company-template")
-
(provide 'company)
;;; company.el ends here