]> code.delx.au - gnu-emacs-elpa/blobdiff - company.el
Backquote "company-mode"
[gnu-emacs-elpa] / company.el
index 81ecb6c225ca618d9e537ed6d4c01386a5a3a0cb..0e809974ecfbee073d46389c7fec44e4ad8c22da 100644 (file)
@@ -1,28 +1,28 @@
-;;; company.el --- extensible inline text completion mechanism
-;;
-;; Copyright (C) 2009 Nikolaj Schumacher
-;;
-;; Author: Nikolaj Schumacher <bugs * nschum de>
-;; Version: 0.4.3
-;; Keywords: abbrev, convenience, matchis
-;; URL: http://nschum.de/src/emacs/company/
-;; Compatibility: GNU Emacs 22.x, GNU Emacs 23.x
-;;
-;; This file is NOT part of GNU Emacs.
-;;
-;; This program is free software; you can redistribute it and/or
-;; modify it under the terms of the GNU General Public License
-;; as published by the Free Software Foundation; either version 2
-;; of the License, or (at your option) any later version.
-;;
-;; This program is distributed in the hope that it will be useful,
+;;; company.el --- Extensible inline text completion mechanism
+
+;; Copyright (C) 2009-2012  Free Software Foundation, Inc.
+
+;; Author: Nikolaj Schumacher
+;; Version: 0.5
+;; Keywords: abbrev, convenience, matching
+;; URL: http://nschum.de/src/emacs/company-mode/
+;; Compatibility: GNU Emacs 22.x, GNU Emacs 23.x, GNU Emacs 24.x
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
-;;
+
 ;; You should have received a copy of the GNU General Public License
-;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
-;;
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
 ;;; Commentary:
 ;;
 ;; Company is a modular completion mechanism.  Modules for retrieving completion
 ;;
 ;; (defun company-my-backend (command &optional arg &rest ignored)
 ;;   (case command
-;;     ('prefix (when (looking-back "foo\\>")
-;;                (match-string 0)))
-;;     ('candidates (list "foobar" "foobaz" "foobarbaz"))
-;;     ('meta (format "This value is named %s" arg))))
+;;     (prefix (when (looking-back "foo\\>")
+;;               (match-string 0)))
+;;     (candidates (list "foobar" "foobaz" "foobarbaz"))
+;;     (meta (format "This value is named %s" arg))))
 ;;
 ;; Sometimes it is a good idea to mix two back-ends together, for example to
 ;; enrich gtags with dabbrev-code results (to emulate local variables):
 ;;
 ;;; 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.
+;;
+;; 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.
+;;    Added compatibility for CEDET in Emacs 23.2 and from CVS.  (Oleg Andreev)
 ;;
 ;; 2009-05-07 (0.4.3)
 ;;    Added `company-other-backend'.
 ;;
 ;; 2009-03-20 (0.1)
 ;;    Initial release.
-;;
+
 ;;; Code:
 
 (eval-when-compile (require 'cl))
   "Extensible inline text completion mechanism"
   :group 'abbrev
   :group 'convenience
-  :group 'maching)
+  :group 'matching)
 
 (defface company-tooltip
   '((t :background "yellow"
        :foreground "black"))
-  "*Face used for the tool tip."
+  "Face used for the tool tip."
   :group 'company)
 
 (defface company-tooltip-selection
   '((default :inherit company-tooltip)
     (((class color) (min-colors 88)) (:background "orange1"))
     (t (:background "green")))
-  "*Face used for the selection in the tool tip."
+  "Face used for the selection in the tool tip."
   :group 'company)
 
 (defface company-tooltip-mouse
   '((default :inherit highlight))
-  "*Face used for the tool tip item under the mouse."
+  "Face used for the tool tip item under the mouse."
   :group 'company)
 
 (defface company-tooltip-common
   '((t :inherit company-tooltip
        :foreground "red"))
-  "*Face used for the common completion in the tool tip."
+  "Face used for the common completion in the tool tip."
   :group 'company)
 
 (defface company-tooltip-common-selection
   '((t :inherit company-tooltip-selection
        :foreground "red"))
-  "*Face used for the selected common completion in the tool tip."
+  "Face used for the selected common completion in the tool tip."
   :group 'company)
 
 (defface company-preview
   '((t :background "blue4"
        :foreground "wheat"))
-  "*Face used for the completion preview."
+  "Face used for the completion preview."
   :group 'company)
 
 (defface company-preview-common
   '((t :inherit company-preview
        :foreground "red"))
-  "*Face used for the common part of the completion preview."
+  "Face used for the common part of the completion preview."
   :group 'company)
 
 (defface company-preview-search
   '((t :inherit company-preview
        :background "blue1"))
-  "*Face used for the search string in the completion preview."
+  "Face used for the search string in the completion preview."
   :group 'company)
 
 (defface company-echo nil
-  "*Face used for completions in the echo area."
+  "Face used for completions in the echo area."
   :group 'company)
 
 (defface company-echo-common
   '((((background dark)) (:foreground "firebrick1"))
     (((background light)) (:background "firebrick4")))
-  "*Face used for the common part of completions in the echo area."
+  "Face used for the common part of completions in the echo area."
   :group 'company)
 
 (defun company-frontends-set (variable value)
 (defcustom company-frontends '(company-pseudo-tooltip-unless-just-one-frontend
                                company-preview-if-just-one-frontend
                                company-echo-metadata-frontend)
-  "*The list of active front-ends (visualizations).
+  "The list of active front-ends (visualizations).
 Each front-end is a function that takes one argument.  It is called with
 one of the following arguments:
 
@@ -261,18 +278,19 @@ The visualized data is stored in `company-prefix', `company-candidates',
                          (function :tag "custom function" nil))))
 
 (defcustom company-tooltip-limit 10
-  "*The maximum number of candidates in the tool tip"
+  "The maximum number of candidates in the tool tip"
   :group 'company
   :type 'integer)
 
 (defcustom company-tooltip-minimum 6
-  "*The minimum height of the tool tip.
+  "The minimum height of the tool tip.
 If this many lines are not available, prefer to display the tooltip above."
   :group 'company
   :type 'integer)
 
 (defvar company-safe-backends
   '((company-abbrev . "Abbrev")
+    (company-clang . "clang")
     (company-css . "CSS")
     (company-dabbrev . "dabbrev for plain text")
     (company-dabbrev-code . "dabbrev for code")
@@ -300,13 +318,35 @@ If this many lines are not available, prefer to display the tooltip above."
                         (assq backend company-safe-backends))
                 (return t))))))
 
-(defcustom company-backends '(company-elisp company-nxml company-css
-                              company-eclim company-semantic company-xcode
-                              company-ropemacs
+(defun company-capf (command &optional arg &rest args)
+  "Adapter for Company completion to use `completion-at-point-functions'."
+  (interactive (list 'interactive))
+  (case command
+    (interactive (company-begin-backend 'company-capf))
+    (prefix
+     (let ((res (run-hook-wrapped 'completion-at-point-functions
+                                  ;; Ignore misbehaving functions.
+                                  #'completion--capf-wrapper 'optimist)))
+       (when (consp res)
+         (if (> (nth 1 res) (point))
+             'stop
+           (buffer-substring-no-properties (nth 0 res) (point))))))
+    (candidates
+     (let ((res (run-hook-wrapped 'completion-at-point-functions
+                                  ;; Ignore misbehaving functions.
+                                  #'completion--capf-wrapper 'optimist)))
+       (when (consp res)
+         (all-completions arg (nth 2 res)
+                          (plist-get (nthcdr 3 res) :predicate)))))))
+
+(defcustom company-backends '(;; company-capf ;FIXME: Untested!
+                              company-elisp company-nxml company-css
+                              company-eclim company-semantic company-clang
+                              company-xcode company-ropemacs
                               (company-gtags company-etags company-dabbrev-code
                                company-pysmell company-keywords)
                               company-oddmuse company-files company-dabbrev)
-  "*The list of active back-ends (completion engines).
+  "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.
@@ -318,7 +358,7 @@ 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:
 
-'prefix: The back-end should return the text to be completed.  It must be
+`prefix': The back-end should return the text to be completed.  It must be
 text immediately before `point'.  Returning nil passes control to the next
 back-end.  The function should return 'stop if it should complete but cannot
 \(e.g. if it is in the middle of a string\).  If the returned value is only
@@ -326,33 +366,33 @@ part of the prefix (e.g. the part after \"->\" in C), the back-end may return a
 cons of prefix and prefix length, which is then used in the
 `company-minimum-prefix-length' test.
 
-'candidates: The second argument is the prefix to be completed.  The
+`candidates': The second argument is the prefix to be completed.  The
 return value should be a list of candidates that start with the prefix.
 
 Optional commands:
 
-'sorted: The back-end may return t here to indicate that the candidates
+`sorted': The back-end may return t here to indicate that the candidates
 are sorted and will not need to be sorted again.
 
-'duplicates: If non-nil, company will take care of removing duplicates
+`duplicates': If non-nil, company will take care of removing duplicates
 from the list.
 
-'no-cache: Usually company doesn't ask for candidates again as completion
+`no-cache': Usually company doesn't ask for candidates again as completion
 progresses, unless the back-end returns t for this command.  The second
 argument is the latest prefix.
 
-'meta: The second argument is a completion candidate.  The back-end should
+`meta': The second argument is a completion candidate.  The back-end should
 return a (short) documentation string for it.
 
-'doc-buffer: The second argument is a completion candidate.  The back-end should
-create a buffer (preferably with `company-doc-buffer'), fill it with
-documentation and return it.
+`doc-buffer': The second argument is a completion candidate.
+The back-end should create a buffer (preferably with `company-doc-buffer'),
+fill it with documentation and return it.
 
-'location: The second argument is a completion candidate.  The back-end can
+`location': The second argument is a completion candidate.  The back-end can
 return the cons of buffer and buffer location, or of file and line
 number where the completion candidate was defined.
 
-'require-match: If this value is t, the user is not allowed to enter anything
+`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
 user that choice with `company-require-match'.  Return value 'never overrides
 that option the other way around.
@@ -377,32 +417,32 @@ does not know about.  It should also be callable interactively and use
 (put 'company-backends 'safe-local-variable 'company-safe-backends-p)
 
 (defcustom company-completion-started-hook nil
-  "*Hook run when company starts completing.
+  "Hook run when company starts completing.
 The hook is called with one argument that is non-nil if the completion was
 started manually."
   :group 'company
   :type 'hook)
 
 (defcustom company-completion-cancelled-hook nil
-  "*Hook run when company cancels completing.
+  "Hook run when company cancels completing.
 The hook is called with one argument that is non-nil if the completion was
 aborted manually."
   :group 'company
   :type 'hook)
 
 (defcustom company-completion-finished-hook nil
-  "*Hook run when company successfully completes.
+  "Hook run when company successfully completes.
 The hook is called with the selected candidate as an argument."
   :group 'company
   :type 'hook)
 
 (defcustom company-minimum-prefix-length 3
-  "*The minimum prefix length for automatic completion."
+  "The minimum prefix length for automatic completion."
   :group 'company
   :type '(integer :tag "prefix length"))
 
 (defcustom company-require-match 'company-explicit-action-p
-  "*If enabled, disallow non-matching input.
+  "If enabled, disallow non-matching input.
 This can be a function do determine if a match is required.
 
 This can be overridden by the back-end, if it returns t or 'never to
@@ -455,7 +495,7 @@ A character that is part of a valid candidate never starts auto-completion."
                  (function :tag "Predicate function")))
 
 (defcustom company-idle-delay .7
-  "*The idle delay in seconds until automatic completions starts.
+  "The idle delay in seconds until automatic completions starts.
 A value of nil means never complete automatically, t means complete
 immediately when a prefix of `company-minimum-prefix-length' is reached."
   :group 'company
@@ -464,7 +504,7 @@ immediately when a prefix of `company-minimum-prefix-length' is reached."
                  (number :tag "seconds")))
 
 (defcustom company-begin-commands t
-  "*A list of commands following which company will start completing.
+  "A list of commands following which company will start completing.
 If this is t, it will complete after any command.  See `company-idle-delay'.
 
 Alternatively any command with a non-nil 'company-begin property is treated as
@@ -475,13 +515,13 @@ if it was on this list."
                  (repeat :tag "Commands" function)))
 
 (defcustom company-show-numbers nil
-  "*If enabled, show quick-access numbers for the first ten candidates."
+  "If enabled, show quick-access numbers for the first ten candidates."
   :group 'company
   :type '(choice (const :tag "off" nil)
                  (const :tag "on" t)))
 
 (defvar company-end-of-buffer-workaround t
-  "*Work around a visualization bug when completing at the end of the buffer.
+  "Work around a visualization bug when completing at the end of the buffer.
 The work-around consists of adding a newline.")
 
 ;;; mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -503,8 +543,8 @@ The work-around consists of adding a newline.")
     (define-key keymap [mouse-3] 'company-select-mouse)
     (define-key keymap [up-mouse-1] 'ignore)
     (define-key keymap [up-mouse-3] 'ignore)
-    (define-key keymap "\C-m" 'company-complete-selection)
-    (define-key keymap "\t" 'company-complete-common)
+    (define-key keymap [return] 'company-complete-selection)
+    (define-key keymap [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)
@@ -525,14 +565,17 @@ The work-around consists of adding a newline.")
 
   (if (or (symbolp backend)
           (functionp backend))
-      (if (ignore-errors (funcall backend 'init) t)
-          (put backend 'company-init t)
-        (put backend 'company-init 'failed)
-        (unless (memq backend company--disabled-backends)
-          (message "Company back-end '%s' could not be initialized"
-                   backend)
-          (push backend company--disabled-backends))
-        nil)
+      (condition-case err
+          (progn
+            (funcall backend 'init)
+            (put backend 'company-init t))
+        (error
+         (put backend 'company-init 'failed)
+         (unless (memq backend company--disabled-backends)
+           (message "Company back-end '%s' could not be initialized:\n%s"
+                    backend (error-message-string err)))
+         (push backend company--disabled-backends)
+         nil))
     (mapc 'company-init-backend backend)))
 
 (defvar company-default-lighter " company")
@@ -542,7 +585,7 @@ The work-around consists of adding a newline.")
 
 ;;;###autoload
 (define-minor-mode company-mode
-  "\"complete anything\"; in in-buffer completion framework.
+  "\"complete anything\"; is an in-buffer completion framework.
 Completion starts automatically, depending on the values
 `company-idle-delay' and `company-minimum-prefix-length'.
 
@@ -586,31 +629,28 @@ keymap during active completions (`company-active-map'):
 
 ;;; keymaps ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defvar company-overriding-keymap-bound nil)
-(make-variable-buffer-local 'company-overriding-keymap-bound)
-
-(defvar company-old-keymap nil)
-(make-variable-buffer-local 'company-old-keymap)
-
 (defvar company-my-keymap nil)
 (make-variable-buffer-local 'company-my-keymap)
 
+(defvar company-emulation-alist '((t . nil)))
+
 (defsubst company-enable-overriding-keymap (keymap)
-  (setq company-my-keymap keymap)
-  (when company-overriding-keymap-bound
-    (company-uninstall-map)))
+  (company-uninstall-map)
+  (setq company-my-keymap keymap))
+
+(defun company-ensure-emulation-alist ()
+  (unless (eq 'company-emulation-alist (car emulation-mode-map-alists))
+    (setq emulation-mode-map-alists
+          (cons 'company-emulation-alist
+                (delq 'company-emulation-alist emulation-mode-map-alists)))))
 
 (defun company-install-map ()
-  (unless (or company-overriding-keymap-bound
+  (unless (or (cdar company-emulation-alist)
               (null company-my-keymap))
-    (setq company-old-keymap overriding-terminal-local-map
-          overriding-terminal-local-map company-my-keymap
-          company-overriding-keymap-bound t)))
+    (setf (cdar company-emulation-alist) company-my-keymap)))
 
 (defun company-uninstall-map ()
-  (when (eq overriding-terminal-local-map company-my-keymap)
-    (setq overriding-terminal-local-map company-old-keymap
-          company-overriding-keymap-bound nil)))
+  (setf (cdar company-emulation-alist) nil))
 
 ;; Hack:
 ;; Emacs calculates the active keymaps before reading the event.  That means we
@@ -684,11 +724,11 @@ keymap during active completions (`company-active-map'):
 
 (defun company--multi-backend-adapter (backends command &rest args)
   (case command
-    ('candidates
+    (candidates
      (apply 'append (mapcar (lambda (backend) (apply backend command args))
                             backends)))
-    ('sorted nil)
-    ('duplicates t)
+    (sorted nil)
+    (duplicates t)
     (otherwise
      (let (value)
        (dolist (backend backends)
@@ -742,6 +782,19 @@ keymap during active completions (`company-active-map'):
 (defsubst company-strip-prefix (str)
   (substring str (length company-prefix)))
 
+(defmacro company-with-candidate-inserted (candidate &rest body)
+  "Evaluate BODY with CANDIDATE temporarily inserted.
+This is a tool for back-ends that need candidates inserted before they
+can retrieve meta-data for them."
+  (declare (indent 1))
+  `(let ((inhibit-modification-hooks t)
+         (inhibit-point-motion-hooks t)
+         (modified-p (buffer-modified-p)))
+     (insert (company-strip-prefix ,candidate))
+     (unwind-protect
+         (progn ,@body)
+       (delete-region company-point (point)))))
+
 (defun company-explicit-action-p ()
   "Return whether explicit completion action was taken by the user."
   (or company--explicit-action
@@ -1000,7 +1053,9 @@ keymap during active completions (`company-active-map'):
                 company-backend backend
                 c (company-calculate-candidates prefix))
           ;; t means complete/unique.  We don't start, so no hooks.
-          (when (consp c)
+          (if (not (consp c))
+              (when company--explicit-action
+                (message "No completion found"))
             (setq company-prefix prefix)
             (when (symbolp backend)
               (setq company-lighter (concat " " (symbol-name backend))))
@@ -1011,15 +1066,15 @@ keymap during active completions (`company-active-map'):
         (return c)))))
 
 (defun company-begin ()
-  (setq company-candidates
-        (or (and company-candidates (company--continue))
-            (and (company--should-complete) (company--begin-new))))
+  (or (and company-candidates (company--continue))
+      (and (company--should-complete) (company--begin-new)))
   (when company-candidates
     (when (and company-end-of-buffer-workaround (eobp))
       (save-excursion (insert "\n"))
       (setq company-added-newline (buffer-chars-modified-tick)))
     (setq company-point (point)
           company--point-max (point-max))
+    (company-ensure-emulation-alist)
     (company-enable-overriding-keymap company-active-map)
     (company-call-frontends 'update)))
 
@@ -1033,7 +1088,10 @@ keymap during active completions (`company-active-map'):
        (set-buffer-modified-p nil))
   (when company-prefix
     (if (stringp result)
-        (run-hook-with-args 'company-completion-finished-hook result)
+        (progn
+          (company-call-backend 'pre-completion result)
+          (run-hook-with-args 'company-completion-finished-hook result)
+          (company-call-backend 'post-completion result))
       (run-hook-with-args 'company-completion-cancelled-hook result)))
   (setq company-added-newline nil
         company-backend nil
@@ -1400,19 +1458,24 @@ To show the number next to the candidates in some back-ends, enable
     (erase-buffer)
     (current-buffer)))
 
+(defvar company--electric-commands
+  '(scroll-other-window scroll-other-window-down)
+  "List of Commands that won't break out of electric commands.")
+
 (defmacro company--electric-do (&rest body)
   (declare (indent 0) (debug t))
   `(when (company-manual-begin)
      (save-window-excursion
        (let ((height (window-height))
-             (row (company--row)))
+             (row (company--row))
+             cmd)
          ,@body
          (and (< (window-height) height)
               (< (- (window-height) row 2) company-tooltip-limit)
               (recenter (- (window-height) row 2)))
-         (while (eq 'scroll-other-window
-                    (key-binding (vector (list (read-event)))))
-           (call-interactively 'scroll-other-window))
+         (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)))))))
@@ -1421,9 +1484,12 @@ To show the number next to the candidates in some back-ends, enable
   "Temporarily show a buffer with the complete documentation for the selection."
   (interactive)
   (company--electric-do
-    (let ((selected (nth company-selection company-candidates)))
-      (display-buffer (or (company-call-backend 'doc-buffer selected)
-                          (error "No documentation available")) t))))
+    (let* ((selected (nth company-selection company-candidates))
+           (doc-buffer (or (company-call-backend 'doc-buffer selected)
+                           (error "No documentation available"))))
+      (with-current-buffer doc-buffer
+        (goto-char (point-min)))
+      (display-buffer doc-buffer t))))
 (put 'company-show-doc-buffer 'company-keep t)
 
 (defun company-show-location ()
@@ -1436,9 +1502,12 @@ To show the number next to the candidates in some back-ends, enable
            (buffer (or (and (bufferp (car location)) (car location))
                        (find-file-noselect (car location) t))))
       (with-selected-window (display-buffer buffer t)
-        (if (bufferp (car location))
-            (goto-char pos)
-          (goto-line pos))
+        (save-restriction
+          (widen)
+          (if (bufferp (car location))
+              (goto-char pos)
+            (goto-char (point-min))
+            (forward-line (1- pos))))
         (set-window-start nil (point))))))
 (put 'company-show-location 'company-keep t)
 
@@ -1761,8 +1830,8 @@ Returns a negative number if the tooltip should be displayed above point."
 (defun company-pseudo-tooltip-frontend (command)
   "A `company-mode' front-end similar to a tool-tip but based on overlays."
   (case command
-    ('pre-command (company-pseudo-tooltip-hide-temporarily))
-    ('post-command
+    (pre-command (company-pseudo-tooltip-hide-temporarily))
+    (post-command
      (let ((old-height (if (overlayp company-pseudo-tooltip-overlay)
                            (overlay-get company-pseudo-tooltip-overlay
                                         'company-height)
@@ -1774,11 +1843,11 @@ Returns a negative number if the tooltip should be displayed above point."
          (company-pseudo-tooltip-show-at-point (- (point)
                                                   (length company-prefix)))))
      (company-pseudo-tooltip-unhide))
-    ('hide (company-pseudo-tooltip-hide)
-           (setq company-tooltip-offset 0))
-    ('update (when (overlayp company-pseudo-tooltip-overlay)
-               (company-pseudo-tooltip-edit company-candidates
-                                            company-selection)))))
+    (hide (company-pseudo-tooltip-hide)
+          (setq company-tooltip-offset 0))
+    (update (when (overlayp company-pseudo-tooltip-overlay)
+              (company-pseudo-tooltip-edit company-candidates
+                                           company-selection)))))
 
 (defun company-pseudo-tooltip-unless-just-one-frontend (command)
   "`company-pseudo-tooltip-frontend', but not shown for single candidates."
@@ -1826,9 +1895,9 @@ Returns a negative number if the tooltip should be displayed above point."
 (defun company-preview-frontend (command)
   "A `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)))
-    ('hide (company-preview-hide))))
+    (pre-command (company-preview-hide))
+    (post-command (company-preview-show-at-point (point)))
+    (hide (company-preview-hide))))
 
 (defun company-preview-if-just-one-frontend (command)
   "`company-preview-frontend', but only shown for single candidates."
@@ -1841,10 +1910,6 @@ Returns a negative number if the tooltip should be displayed above point."
 (defvar company-echo-last-msg nil)
 (make-variable-buffer-local 'company-echo-last-msg)
 
-(defvar company-echo-timer nil)
-
-(defvar company-echo-delay .1)
-
 (defun company-echo-show (&optional getter)
   (when getter
     (setq company-echo-last-msg (funcall getter)))
@@ -1856,8 +1921,16 @@ Returns a negative number if the tooltip should be displayed above point."
 (defsubst company-echo-show-soon (&optional getter)
   (when company-echo-timer
     (cancel-timer company-echo-timer))
-  (setq company-echo-timer (run-with-timer company-echo-delay nil
-                                           'company-echo-show getter)))
+  (setq company-echo-timer (run-with-timer 0 nil 'company-echo-show getter)))
+
+(defsubst company-echo-show-when-idle (&optional getter)
+  (when (sit-for .01)
+    (company-echo-show getter)))
+
+(defsubst company-echo-show-when-not-busy (&optional getter)
+  "Run `company-echo-show' with arg GETTER once Emacs isn't busy."
+  (when (sit-for company-echo-delay)
+    (company-echo-show getter)))
 
 (defun company-echo-format ()
 
@@ -1915,8 +1988,6 @@ Returns a negative number if the tooltip should be displayed above point."
             "}")))
 
 (defun company-echo-hide ()
-  (when company-echo-timer
-    (cancel-timer company-echo-timer))
   (unless (equal company-echo-last-msg "")
     (setq company-echo-last-msg "")
     (company-echo-show)))
@@ -1924,23 +1995,24 @@ Returns a negative number if the tooltip should be displayed above point."
 (defun company-echo-frontend (command)
   "A `company-mode' front-end showing the candidates in the echo area."
   (case command
-    ('pre-command (company-echo-show-soon))
-    ('post-command (company-echo-show-soon 'company-echo-format))
-    ('hide (company-echo-hide))))
+    (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."
   (case command
-    ('pre-command (company-echo-show-soon))
-    ('post-command (company-echo-show-soon 'company-echo-strip-common-format))
-    ('hide (company-echo-hide))))
+    (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."
   (case command
-    ('pre-command (company-echo-show-soon))
-    ('post-command (company-echo-show-soon 'company-fetch-metadata))
-    ('hide (company-echo-hide))))
+    (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