1 ;;; company.el --- extensible inline text completion mechanism
3 ;; Copyright (C) 2009 Nikolaj Schumacher
5 ;; Author: Nikolaj Schumacher <bugs * nschum de>
7 ;; Keywords: abbrev, convenience, matchis
8 ;; URL: http://nschum.de/src/emacs/company/
9 ;; Compatibility: GNU Emacs 23.x
11 ;; This file is NOT part of GNU Emacs.
13 ;; This program is free software; you can redistribute it and/or
14 ;; modify it under the terms of the GNU General Public License
15 ;; as published by the Free Software Foundation; either version 2
16 ;; of the License, or (at your option) any later version.
18 ;; This program is distributed in the hope that it will be useful,
19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ;; GNU General Public License for more details.
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
34 (eval-when-compile (require 'cl))
36 (add-to-list 'debug-ignored-errors
37 "^Pseudo tooltip frontend cannot be used twice$")
38 (add-to-list 'debug-ignored-errors "^Preview frontend cannot be used twice$")
39 (add-to-list 'debug-ignored-errors "^Echo area cannot be used twice$")
40 (add-to-list 'debug-ignored-errors "^No documentation available$")
48 (defface company-tooltip
49 '((t :background "yellow"
54 (defface company-tooltip-selection
55 '((t :background "orange1"
60 (defface company-tooltip-common
61 '((t :inherit company-tooltip
66 (defface company-tooltip-common-selection
67 '((t :inherit company-tooltip-selection
72 (defcustom company-tooltip-limit 10
77 (defface company-preview
78 '((t :background "blue4"
83 (defface company-preview-common
84 '((t :inherit company-preview
89 (defface company-echo nil
93 (defface company-echo-common
94 '((((background dark)) (:foreground "firebrick1"))
95 (((background light)) (:background "firebrick4")))
99 (defun company-frontends-set (variable value)
101 (let ((remainder value))
102 (setcdr remainder (delq (car remainder) (cdr remainder))))
103 (and (memq 'company-pseudo-tooltip-unless-just-one-frontend value)
104 (memq 'company-pseudo-tooltip-frontend value)
105 (error "Pseudo tooltip frontend cannot be used twice"))
106 (and (memq 'company-preview-if-just-one-frontend value)
107 (memq 'company-preview-frontend value)
108 (error "Preview frontend cannot be used twice"))
109 (and (memq 'company-echo value)
110 (memq 'company-echo-metadata-frontend value)
111 (error "Echo area cannot be used twice"))
112 ;; preview must come last
113 (dolist (f '(company-preview-if-just-one-frontend company-preview-frontend))
115 (setq value (append (delq f value) (list f)))))
116 (set variable value))
118 (defcustom company-frontends '(company-pseudo-tooltip-unless-just-one-frontend
119 company-preview-if-just-one-frontend
120 company-echo-metadata-frontend)
122 :set 'company-frontends-set
124 :type '(repeat (choice (const :tag "echo" company-echo-frontend)
125 (const :tag "pseudo tooltip"
126 company-pseudo-tooltip-frontend)
127 (const :tag "pseudo tooltip, multiple only"
128 company-pseudo-tooltip-unless-just-one-frontend)
129 (const :tag "preview" company-preview-frontend)
130 (const :tag "preview, unique only"
131 company-preview-if-just-one-frontend)
132 (function :tag "custom function" nil))))
134 (defcustom company-backends '(company-elisp company-nxml company-css
135 company-semantic company-gtags company-oddmuse
136 company-files company-dabbrev)
139 :type '(repeat (function :tag "function" nil)))
141 (defcustom company-minimum-prefix-length 3
144 :type '(integer :tag "prefix length"))
146 (defcustom company-idle-delay .7
149 :type '(choice (const :tag "never (nil)" nil)
150 (const :tag "immediate (t)" t)
151 (number :tag "seconds")))
153 ;;; mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
155 (defvar company-mode-map (make-sparse-keymap))
157 (defvar company-active-map
158 (let ((keymap (make-sparse-keymap)))
159 (define-key keymap (kbd "M-n") 'company-select-next)
160 (define-key keymap (kbd "M-p") 'company-select-previous)
161 (define-key keymap "\C-m" 'company-complete-selection)
162 (define-key keymap "\t" 'company-complete-common)
163 (define-key keymap (kbd "<f1>") 'company-show-doc-buffer)
164 (define-key keymap "\C-s" 'company-search-candidates)
168 (define-minor-mode company-mode
170 nil " comp" company-mode-map
173 (add-hook 'pre-command-hook 'company-pre-command nil t)
174 (add-hook 'post-command-hook 'company-post-command nil t))
175 (remove-hook 'pre-command-hook 'company-pre-command t)
176 (remove-hook 'post-command-hook 'company-post-command t)
178 (kill-local-variable 'company-point)))
180 ;;; keymaps ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
182 (defvar company-overriding-keymap-bound nil)
183 (make-variable-buffer-local 'company-overriding-keymap-bound)
185 (defvar company-old-keymap nil)
186 (make-variable-buffer-local 'company-old-keymap)
188 (defvar company-my-keymap nil)
189 (make-variable-buffer-local 'company-my-keymap)
191 (defsubst company-enable-overriding-keymap (keymap)
192 (setq company-my-keymap keymap)
193 (when company-overriding-keymap-bound
194 (company-uninstall-map)))
196 (defun company-install-map ()
197 (unless (or company-overriding-keymap-bound
198 (null company-my-keymap))
199 (setq company-old-keymap overriding-terminal-local-map
200 overriding-terminal-local-map company-my-keymap
201 company-overriding-keymap-bound t)))
203 (defun company-uninstall-map ()
204 (when (and company-overriding-keymap-bound
205 (eq overriding-terminal-local-map company-my-keymap))
206 (setq overriding-terminal-local-map company-old-keymap
207 company-overriding-keymap-bound nil)))
210 ;; Emacs calculates the active keymaps before reading the event. That means we
211 ;; cannot change the keymap from a timer. So we send a bogus command.
212 (defun company-ignore ()
215 (global-set-key '[31415926] 'company-ignore)
217 (defun company-input-noop ()
218 (push 31415926 unread-command-events))
220 ;;; backends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
222 (defun company-grab (regexp &optional expression)
223 (when (looking-back regexp)
224 (or (match-string-no-properties (or expression 0)) "")))
226 (defun company-in-string-or-comment (&optional point)
227 (let ((pos (syntax-ppss)))
228 (or (nth 3 pos) (nth 4 pos) (nth 7 pos))))
230 ;;; completion mechanism ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
232 (defvar company-backend nil)
233 (make-variable-buffer-local 'company-backend)
235 (defvar company-prefix nil)
236 (make-variable-buffer-local 'company-prefix)
238 (defvar company-candidates nil)
239 (make-variable-buffer-local 'company-candidates)
241 (defvar company-candidates-length nil)
242 (make-variable-buffer-local 'company-candidates-length)
244 (defvar company-candidates-cache nil)
245 (make-variable-buffer-local 'company-candidates-cache)
247 (defvar company-candidates-predicate nil)
248 (make-variable-buffer-local 'company-candidates-predicate)
250 (defvar company-common nil)
251 (make-variable-buffer-local 'company-common)
253 (defvar company-selection 0)
254 (make-variable-buffer-local 'company-selection)
256 (defvar company-selection-changed nil)
257 (make-variable-buffer-local 'company-selection-changed)
259 (defvar company-point nil)
260 (make-variable-buffer-local 'company-point)
262 (defvar company-timer nil)
264 (defvar company-disabled-backends nil)
266 (defsubst company-strip-prefix (str)
267 (substring str (length company-prefix)))
269 (defsubst company-reformat (candidate)
270 ;; company-ispell needs this, because the results are always lower-case
271 ;; It's mory efficient to fix it only when they are displayed.
272 (concat company-prefix (substring candidate (length company-prefix))))
274 (defsubst company-should-complete (prefix)
275 (and (eq company-idle-delay t)
276 (>= (length prefix) company-minimum-prefix-length)))
278 (defsubst company-call-frontends (command)
279 (dolist (frontend company-frontends)
281 (funcall frontend command)
282 (error (error "Company: Front-end %s error \"%s\" on command %s"
283 frontend (error-message-string err) command)))))
285 (defsubst company-set-selection (selection &optional force-update)
286 (setq selection (max 0 (min (1- company-candidates-length) selection)))
287 (when (or force-update (not (equal selection company-selection)))
288 (setq company-selection selection
289 company-selection-changed t)
290 (company-call-frontends 'update)))
292 (defun company-apply-predicate (candidates predicate)
294 (dolist (c candidates)
295 (when (funcall predicate c)
299 (defun company-update-candidates (candidates)
300 (setq company-candidates-length (length candidates))
301 (if (> company-selection 0)
302 ;; Try to restore the selection
303 (let ((selected (nth company-selection company-candidates)))
304 (setq company-selection 0
305 company-candidates candidates)
307 (while (and candidates (string< (pop candidates) selected))
308 (incf company-selection))
310 ;; Make sure selection isn't out of bounds.
311 (setq company-selection (min (1- company-candidates-length)
312 company-selection)))))
313 (setq company-selection 0
314 company-candidates candidates))
316 (let ((completion-ignore-case (funcall company-backend 'ignore-case)))
317 (setq company-common (try-completion company-prefix company-candidates)))
318 (when (eq company-common t)
319 (setq company-candidates nil)))
321 (defsubst company-calculate-candidates (prefix)
322 (setq company-prefix prefix)
323 (company-update-candidates
324 (or (cdr (assoc prefix company-candidates-cache))
325 (when company-candidates-cache
326 (let ((len (length prefix))
327 (completion-ignore-case (funcall company-backend 'ignore-case))
330 (when (setq prev (cdr (assoc (substring prefix 0 (- len i))
331 company-candidates-cache)))
332 (return (all-completions prefix prev))))))
333 (let ((candidates (funcall company-backend 'candidates prefix)))
334 (when company-candidates-predicate
336 (company-apply-predicate candidates
337 company-candidates-predicate)))
338 (unless (funcall company-backend 'sorted)
339 (setq candidates (sort candidates 'string<)))
341 (unless (assoc prefix company-candidates-cache)
342 (push (cons prefix company-candidates) company-candidates-cache))
345 (defun company-idle-begin (buf win tick pos)
347 (eq buf (current-buffer))
348 (eq win (selected-window))
349 (eq tick (buffer-chars-modified-tick))
351 (not company-candidates)
352 (not (equal (point) company-point))
353 (let ((company-idle-delay t))
355 (when company-candidates
357 (company-post-command)))))
359 (defun company-manual-begin ()
361 (not company-candidates)
362 (let ((company-idle-delay t)
363 (company-minimum-prefix-length 0))
365 ;; Return non-nil if active.
368 (defun company-continue ()
369 (when company-candidates
370 (when (funcall company-backend 'no-cache company-prefix)
371 ;; Don't complete existing candidates, fetch new ones.
372 (setq company-candidates-cache nil))
373 (let ((new-prefix (funcall company-backend 'prefix)))
374 (unless (and (= (- (point) (length new-prefix))
375 (- company-point (length company-prefix)))
376 (or (equal company-prefix new-prefix)
377 (company-calculate-candidates new-prefix)))
378 (setq company-candidates nil)))))
380 (defun company-begin ()
381 (if (or buffer-read-only overriding-terminal-local-map overriding-local-map)
382 ;; Don't complete in these cases.
383 (setq company-candidates nil)
385 (unless company-candidates
387 (dolist (backend company-backends)
388 (unless (fboundp backend)
389 (ignore-errors (require backend nil t)))
390 (if (fboundp backend)
391 (when (setq prefix (funcall backend 'prefix))
392 (when (company-should-complete prefix)
393 (setq company-backend backend)
394 (company-calculate-candidates prefix))
396 (unless (memq backend company-disabled-backends)
397 (push backend company-disabled-backends)
398 (message "Company back-end '%s' could not be initialized"
400 (if company-candidates
402 (setq company-point (point))
403 (company-enable-overriding-keymap company-active-map)
404 (company-call-frontends 'update))
407 (defun company-cancel ()
408 (setq company-backend nil
410 company-candidates nil
411 company-candidates-length nil
412 company-candidates-cache nil
413 company-candidates-predicate nil
416 company-selection-changed nil
419 (cancel-timer company-timer))
420 (company-search-mode 0)
421 (company-call-frontends 'hide)
422 (company-enable-overriding-keymap nil))
424 (defun company-abort ()
426 ;; Don't start again, unless started manually.
427 (setq company-point (point)))
429 (defun company-pre-command ()
430 (unless (eq this-command 'company-show-doc-buffer)
432 (when company-candidates
433 (company-call-frontends 'pre-command))
434 (error (message "Company: An error occurred in pre-command")
435 (message "%s" (error-message-string err))
438 (cancel-timer company-timer))
439 (company-uninstall-map))
441 (defun company-post-command ()
442 (unless (eq this-command 'company-show-doc-buffer)
445 (unless (equal (point) company-point)
447 (when company-candidates
448 (company-call-frontends 'post-command))
449 (when (numberp company-idle-delay)
451 (run-with-timer company-idle-delay nil 'company-idle-begin
452 (current-buffer) (selected-window)
453 (buffer-chars-modified-tick) (point)))))
454 (error (message "Company: An error occurred in post-command")
455 (message "%s" (error-message-string err))
457 (company-install-map))
459 ;;; search ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
461 (defvar company-search-string nil)
462 (make-variable-buffer-local 'company-search-string)
464 (defvar company-search-lighter " Search: \"\"")
465 (make-variable-buffer-local 'company-search-lighter)
467 (defvar company-search-old-map nil)
468 (make-variable-buffer-local 'company-search-old-map)
470 (defvar company-search-old-selection 0)
471 (make-variable-buffer-local 'company-search-old-selection)
473 (defun company-search (text lines)
474 (let ((quoted (regexp-quote text))
477 (when (string-match quoted line (length company-prefix))
481 (defun company-search-printing-char ()
483 (setq company-search-string
484 (concat (or company-search-string "") (string last-command-event))
485 company-search-lighter (concat " Search: \"" company-search-string
487 (let ((pos (company-search company-search-string
488 (nthcdr company-selection company-candidates))))
491 (company-set-selection (+ company-selection pos) t))))
493 (defun company-search-repeat-forward ()
495 (let ((pos (company-search company-search-string
496 (cdr (nthcdr company-selection
497 company-candidates)))))
500 (company-set-selection (+ company-selection pos 1) t))))
502 (defun company-search-repeat-backward ()
504 (let ((pos (company-search company-search-string
505 (nthcdr (- company-candidates-length
507 (reverse company-candidates)))))
510 (company-set-selection (- company-selection pos 1) t))))
512 (defun company-search-kill-others ()
514 (let ((predicate `(lambda (candidate)
515 (string-match ,company-search-string candidate))))
516 (setq company-candidates-predicate predicate)
517 (company-update-candidates (company-apply-predicate company-candidates
519 (company-search-mode 0)
520 (company-call-frontends 'update)))
522 (defun company-search-abort ()
524 (company-set-selection company-search-old-selection t)
525 (company-search-mode 0))
527 (defun company-search-other-char ()
529 (company-search-mode 0)
530 (when last-input-event
531 (clear-this-command-keys t)
532 (setq unread-command-events (list last-input-event))))
534 (defvar company-search-map
536 (keymap (make-keymap)))
537 (set-char-table-range (nth 1 keymap) (cons #x100 (max-char))
538 'company-search-printing-char)
539 (define-key keymap [t] 'company-search-other-char)
541 (define-key keymap (make-string 1 i) 'company-search-other-char)
544 (define-key keymap (vector i) 'company-search-printing-char)
546 (let ((meta-map (make-sparse-keymap)))
547 (define-key keymap (char-to-string meta-prefix-char) meta-map)
548 (define-key keymap [escape] meta-map))
549 (define-key keymap (vector meta-prefix-char t) 'company-search-other-char)
550 (define-key keymap "\e\e\e" 'company-search-other-char)
551 (define-key keymap [escape escape escape] 'company-search-other-char)
553 (define-key keymap "\C-g" 'company-search-abort)
554 (define-key keymap "\C-s" 'company-search-repeat-forward)
555 (define-key keymap "\C-r" 'company-search-repeat-backward)
556 (define-key keymap "\C-o" 'company-search-kill-others)
559 (define-minor-mode company-search-mode
561 nil company-search-lighter nil
562 (if company-search-mode
563 (if (company-manual-begin)
565 (setq company-search-old-selection company-selection)
566 (company-enable-overriding-keymap company-search-map)
567 (company-call-frontends 'update))
568 (setq company-search-mode nil))
569 (kill-local-variable 'company-search-string)
570 (kill-local-variable 'company-search-lighter)
571 (kill-local-variable 'company-search-old-selection)
572 (company-enable-overriding-keymap company-active-map)))
574 (defun company-search-candidates ()
576 (company-search-mode 1))
578 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
580 (defun company-select-next ()
582 (when (company-manual-begin)
583 (company-set-selection (1+ company-selection))))
585 (defun company-select-previous ()
587 (when (company-manual-begin)
588 (company-set-selection (1- company-selection))))
590 (defun company-complete-selection ()
592 (when (company-manual-begin)
593 (insert (company-strip-prefix (nth company-selection company-candidates)))
596 (defun company-complete-common ()
598 (when (company-manual-begin)
599 (insert (company-strip-prefix company-common))))
601 (defun company-complete ()
603 (when (company-manual-begin)
604 (if (or company-selection-changed
605 (eq last-command 'company-complete-common))
606 (call-interactively 'company-complete-selection)
607 (call-interactively 'company-complete-common)
608 (setq this-command 'company-complete-common))))
610 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
612 (defconst company-space-strings-limit 100)
614 (defconst company-space-strings
616 (dotimes (i company-space-strings-limit)
617 (push (make-string (- company-space-strings-limit 1 i) ?\ ) lst))
618 (apply 'vector lst)))
620 (defsubst company-space-string (len)
621 (if (< len company-space-strings-limit)
622 (aref company-space-strings len)
623 (make-string len ?\ )))
625 (defsubst company-safe-substring (str from &optional to)
626 (let ((len (length str)))
629 (if (and to (> to len))
630 (concat (substring str from)
631 (company-space-string (- to len)))
632 (substring str from to)))))
634 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
636 (defvar company-last-metadata nil)
637 (make-variable-buffer-local 'company-last-metadata)
639 (defun company-fetch-metadata ()
640 (let ((selected (nth company-selection company-candidates)))
641 (unless (equal selected (car company-last-metadata))
642 (setq company-last-metadata
643 (cons selected (funcall company-backend 'meta selected))))
644 (cdr company-last-metadata)))
646 (defun company-doc-buffer (&optional string)
647 (with-current-buffer (get-buffer-create "*Company meta-data*")
651 (defun company-show-doc-buffer ()
653 (when company-candidates
654 (save-window-excursion
655 (let* ((height (window-height))
656 (row (cdr (posn-col-row (posn-at-point))))
657 (selected (nth company-selection company-candidates))
658 (buffer (funcall company-backend 'doc-buffer selected)))
660 (error "No documentation available.")
661 (display-buffer buffer)
662 (and (< (window-height) height)
663 (< (- (window-height) row 2) company-tooltip-limit)
664 (recenter (- (window-height) row 2)))
665 (while (eq 'scroll-other-window
666 (key-binding (vector (list (read-event)))))
667 (scroll-other-window))
668 (when last-input-event
669 (clear-this-command-keys t)
670 (setq unread-command-events (list last-input-event))))))))
672 ;;; pseudo-tooltip ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
674 (defvar company-pseudo-tooltip-overlay nil)
675 (make-variable-buffer-local 'company-pseudo-tooltip-overlay)
677 (defvar company-tooltip-offset 0)
678 (make-variable-buffer-local 'company-tooltip-offset)
680 (defun company-pseudo-tooltip-update-offset (selection num-lines limit)
683 (setq company-tooltip-offset
684 (max (min selection company-tooltip-offset)
685 (- selection -1 limit)))
687 (when (<= company-tooltip-offset 1)
689 (setq company-tooltip-offset 0))
691 (when (>= company-tooltip-offset (- num-lines limit 1))
693 (when (= selection (1- num-lines))
694 (decf company-tooltip-offset)
695 (when (<= company-tooltip-offset 1)
696 (setq company-tooltip-offset 0)
703 (defsubst company-round-tab (arg)
704 (* (/ (+ arg tab-width) tab-width) tab-width))
706 (defun company-untabify (str)
707 (let* ((pieces (split-string str "\t"))
710 (setcar copy (company-safe-substring
711 (car copy) 0 (company-round-tab (string-width (car copy)))))
713 (apply 'concat pieces)))
715 (defun company-fill-propertize (line width selected)
716 (setq line (company-safe-substring line 0 width))
717 (add-text-properties 0 width (list 'face 'company-tooltip) line)
718 (add-text-properties 0 (length company-common)
719 (list 'face 'company-tooltip-common) line)
721 (if (and company-search-string
722 (string-match (regexp-quote company-search-string) line
723 (length company-prefix)))
725 (add-text-properties (match-beginning 0) (match-end 0)
726 '(face company-tooltip-selection) line)
727 (when (< (match-beginning 0) (length company-common))
728 (add-text-properties (match-beginning 0) (length company-common)
729 '(face company-tooltip-common-selection)
731 (add-text-properties 0 width '(face company-tooltip-selection) line)
732 (add-text-properties 0 (length company-common)
733 (list 'face 'company-tooltip-common-selection)
739 (defun company-buffer-lines (beg end)
741 (let ((row (cdr (posn-col-row (posn-at-point))))
743 (while (and (equal (move-to-window-line (incf row)) row)
745 (push (buffer-substring beg (min end (1- (point)))) lines)
748 (push (buffer-substring beg end) lines))
751 (defsubst company-modify-line (old new offset)
752 (concat (company-safe-substring old 0 offset)
754 (company-safe-substring old (+ offset (length new)))))
756 (defun company-replacement-string (old lines column nl)
758 ;; Inject into old lines.
760 (push (company-modify-line (pop old) (pop lines) column) new))
761 ;; Append whole new lines.
763 (push (concat (company-space-string column) (pop lines)) new))
764 (concat (when nl "\n")
765 (mapconcat 'identity (nreverse new) "\n")
768 (defun company-create-lines (column selection limit)
770 (let ((len company-candidates-length)
779 (setq limit (company-pseudo-tooltip-update-offset selection len limit))
781 (when (> company-tooltip-offset 0)
782 (setq previous (format "...(%d)" company-tooltip-offset)))
784 (setq remainder (- len limit company-tooltip-offset)
785 remainder (when (> remainder 0)
786 (setq remainder (format "...(%d)" remainder))))
788 (decf selection company-tooltip-offset)
789 (setq width (min (length previous) (length remainder))
790 lines (nthcdr company-tooltip-offset company-candidates)
795 (setq width (max (length (pop lines-copy)) width)))
796 (setq width (min width (- (window-width) column)))
799 (push (propertize (company-safe-substring previous 0 width)
800 'face 'company-tooltip)
804 (push (company-fill-propertize (company-reformat (pop lines))
805 width (equal i selection))
809 (push (propertize (company-safe-substring remainder 0 width)
810 'face 'company-tooltip)
813 (setq lines (nreverse new))))
817 (defsubst company-pseudo-tooltip-height ()
818 "Calculate the appropriate tooltip height."
819 (max 3 (min company-tooltip-limit
821 (count-lines (window-start) (point-at-bol))))))
823 (defun company-pseudo-tooltip-show (row column selection)
824 (company-pseudo-tooltip-hide)
829 (let* ((height (company-pseudo-tooltip-height))
830 (lines (company-create-lines column selection height))
831 (nl (< (move-to-window-line row) row))
834 (move-to-window-line (+ row height))
837 (mapcar 'company-untabify (company-buffer-lines beg end)))
840 (setq company-pseudo-tooltip-overlay (make-overlay beg end))
842 (overlay-put company-pseudo-tooltip-overlay 'company-old old-string)
843 (overlay-put company-pseudo-tooltip-overlay 'company-column column)
844 (overlay-put company-pseudo-tooltip-overlay 'company-nl nl)
845 (overlay-put company-pseudo-tooltip-overlay 'company-before
846 (company-replacement-string old-string lines column nl))
847 (overlay-put company-pseudo-tooltip-overlay 'company-height height)
849 (overlay-put company-pseudo-tooltip-overlay 'window (selected-window)))))
851 (defun company-pseudo-tooltip-show-at-point (pos)
852 (let ((col-row (posn-col-row (posn-at-point pos))))
853 (company-pseudo-tooltip-show (1+ (cdr col-row)) (car col-row) company-selection)))
855 (defun company-pseudo-tooltip-edit (lines selection)
856 (let* ((old-string (overlay-get company-pseudo-tooltip-overlay 'company-old))
857 (column (overlay-get company-pseudo-tooltip-overlay 'company-column))
858 (nl (overlay-get company-pseudo-tooltip-overlay 'company-nl))
859 (height (overlay-get company-pseudo-tooltip-overlay 'company-height))
860 (lines (company-create-lines column selection height)))
861 (overlay-put company-pseudo-tooltip-overlay 'company-before
862 (company-replacement-string old-string lines column nl))))
864 (defun company-pseudo-tooltip-hide ()
865 (when company-pseudo-tooltip-overlay
866 (delete-overlay company-pseudo-tooltip-overlay)
867 (setq company-pseudo-tooltip-overlay nil)))
869 (defun company-pseudo-tooltip-hide-temporarily ()
870 (when (overlayp company-pseudo-tooltip-overlay)
871 (overlay-put company-pseudo-tooltip-overlay 'invisible nil)
872 (overlay-put company-pseudo-tooltip-overlay 'before-string nil)))
874 (defun company-pseudo-tooltip-unhide ()
875 (when company-pseudo-tooltip-overlay
876 (overlay-put company-pseudo-tooltip-overlay 'invisible t)
877 (overlay-put company-pseudo-tooltip-overlay 'before-string
878 (overlay-get company-pseudo-tooltip-overlay 'company-before))))
880 (defun company-pseudo-tooltip-frontend (command)
882 ('pre-command (company-pseudo-tooltip-hide-temporarily))
884 (unless (and (overlayp company-pseudo-tooltip-overlay)
885 (equal (overlay-get company-pseudo-tooltip-overlay
887 (company-pseudo-tooltip-height)))
889 (company-pseudo-tooltip-show-at-point (- (point)
890 (length company-prefix))))
891 (company-pseudo-tooltip-unhide))
892 ('hide (company-pseudo-tooltip-hide)
893 (setq company-tooltip-offset 0))
894 ('update (when (overlayp company-pseudo-tooltip-overlay)
895 (company-pseudo-tooltip-edit company-candidates
896 company-selection)))))
898 (defun company-pseudo-tooltip-unless-just-one-frontend (command)
899 (unless (and (eq command 'post-command)
900 (not (cdr company-candidates)))
901 (company-pseudo-tooltip-frontend command)))
903 ;;; overlay ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
905 (defvar company-preview-overlay nil)
906 (make-variable-buffer-local 'company-preview-overlay)
908 (defun company-preview-show-at-point (pos)
909 (company-preview-hide)
911 (setq company-preview-overlay (make-overlay pos pos))
913 (let ((completion (company-strip-prefix (nth company-selection
914 company-candidates))))
915 (and (equal pos (point))
916 (not (equal completion ""))
917 (add-text-properties 0 1 '(cursor t) completion))
919 (setq completion (propertize completion 'face 'company-preview))
920 (add-text-properties 0 (- (length company-common) (length company-prefix))
921 '(face company-preview-common) completion)
923 (overlay-put company-preview-overlay 'after-string completion)
924 (overlay-put company-preview-overlay 'window (selected-window))))
926 (defun company-preview-hide ()
927 (when company-preview-overlay
928 (delete-overlay company-preview-overlay)
929 (setq company-preview-overlay nil)))
931 (defun company-preview-frontend (command)
933 ('pre-command (company-preview-hide))
934 ('post-command (company-preview-show-at-point (point)))
935 ('hide (company-preview-hide))))
937 (defun company-preview-if-just-one-frontend (command)
938 (unless (and (eq command 'post-command)
939 (cdr company-candidates))
940 (company-preview-frontend command)))
942 ;;; echo ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
944 (defvar company-echo-last-msg nil)
945 (make-variable-buffer-local 'company-echo-last-msg)
947 (defvar company-echo-timer nil)
949 (defvar company-echo-delay .1)
951 (defun company-echo-show (&optional getter)
953 (setq company-echo-last-msg (funcall getter)))
954 (let ((message-log-max nil))
955 (if company-echo-last-msg
956 (message "%s" company-echo-last-msg)
959 (defsubst company-echo-show-soon (&optional getter)
960 (when company-echo-timer
961 (cancel-timer company-echo-timer))
962 (setq company-echo-timer (run-with-timer company-echo-delay nil
963 'company-echo-show getter)))
965 (defun company-echo-format ()
967 (let ((limit (window-width (minibuffer-window)))
969 ;; Roll to selection.
970 (candidates (nthcdr company-selection company-candidates))
974 (setq comp (company-reformat (pop candidates))
975 len (+ len 1 (length comp)))
977 (setq candidates nil)
978 (setq comp (propertize comp 'face 'company-echo))
979 (add-text-properties 0 (length company-common)
980 '(face company-echo-common) comp)
983 (mapconcat 'identity (nreverse msg) " ")))
985 (defun company-echo-hide ()
986 (when company-echo-timer
987 (cancel-timer company-echo-timer))
988 (setq company-echo-last-msg "")
991 (defun company-echo-frontend (command)
993 ('pre-command (company-echo-show-soon))
994 ('post-command (company-echo-show-soon 'company-echo-format))
995 ('hide (company-echo-hide))))
997 (defun company-echo-metadata-frontend (command)
999 ('pre-command (company-echo-show-soon))
1000 ('post-command (company-echo-show-soon 'company-fetch-metadata))
1001 ('hide (company-echo-hide))))
1004 ;;; company.el ends here