]> code.delx.au - gnu-emacs-elpa/blob - company.el
e479fa49008f6e53201e442fee1556e569f1980c
[gnu-emacs-elpa] / company.el
1 ;;; company.el --- extensible inline text completion mechanism
2 ;;
3 ;; Copyright (C) 2009 Nikolaj Schumacher
4 ;;
5 ;; Author: Nikolaj Schumacher <bugs * nschum de>
6 ;; Version:
7 ;; Keywords: abbrev, convenience, matchis
8 ;; URL: http://nschum.de/src/emacs/company/
9 ;; Compatibility: GNU Emacs 23.x
10 ;;
11 ;; This file is NOT part of GNU Emacs.
12 ;;
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.
17 ;;
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.
22 ;;
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/>.
25 ;;
26 ;;; Commentary:
27 ;;
28 ;;; Change Log:
29 ;;
30 ;; Initial release.
31 ;;
32 ;;; Code:
33
34 (eval-when-compile (require 'cl))
35
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$")
41
42 (defgroup company nil
43 ""
44 :group 'abbrev
45 :group 'convenience
46 :group 'maching)
47
48 (defface company-tooltip
49 '((t :background "yellow"
50 :foreground "black"))
51 "*"
52 :group 'company)
53
54 (defface company-tooltip-selection
55 '((t :background "orange1"
56 :foreground "black"))
57 "*"
58 :group 'company)
59
60 (defface company-tooltip-common
61 '((t :inherit company-tooltip
62 :foreground "red"))
63 "*"
64 :group 'company)
65
66 (defface company-tooltip-common-selection
67 '((t :inherit company-tooltip-selection
68 :foreground "red"))
69 "*"
70 :group 'company)
71
72 (defcustom company-tooltip-limit 10
73 "*"
74 :group 'company
75 :type 'integer)
76
77 (defface company-preview
78 '((t :background "blue4"
79 :foreground "wheat"))
80 "*"
81 :group 'company)
82
83 (defface company-preview-common
84 '((t :inherit company-preview
85 :foreground "red"))
86 "*"
87 :group 'company)
88
89 (defface company-echo nil
90 "*"
91 :group 'company)
92
93 (defface company-echo-common
94 '((((background dark)) (:foreground "firebrick1"))
95 (((background light)) (:background "firebrick4")))
96 "*"
97 :group 'company)
98
99 (defun company-frontends-set (variable value)
100 ;; uniquify
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))
114 (when (memq f value)
115 (setq value (append (delq f value) (list f)))))
116 (set variable value))
117
118 (defcustom company-frontends '(company-pseudo-tooltip-unless-just-one-frontend
119 company-preview-if-just-one-frontend
120 company-echo-metadata-frontend)
121 "*"
122 :set 'company-frontends-set
123 :group 'company
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))))
133
134 (defcustom company-backends '(company-elisp company-nxml company-css
135 company-semantic company-oddmuse
136 company-dabbrev)
137 "*"
138 :group 'company
139 :type '(repeat (function :tag "function" nil)))
140
141 (defcustom company-minimum-prefix-length 3
142 "*"
143 :group 'company
144 :type '(integer :tag "prefix length"))
145
146 (defvar company-timer nil)
147
148 (defun company-timer-set (variable value)
149 (set variable value)
150 (when company-timer (cancel-timer company-timer))
151 (when (numberp value)
152 (setq company-timer (run-with-idle-timer value t 'company-idle-begin))))
153
154 (defcustom company-idle-delay .7
155 "*"
156 :set 'company-timer-set
157 :group 'company
158 :type '(choice (const :tag "never (nil)" nil)
159 (const :tag "immediate (t)" t)
160 (number :tag "seconds")))
161
162 ;;; mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
163
164 (defvar company-mode-map
165 (let ((keymap (make-sparse-keymap)))
166 (define-key keymap (kbd "M-n") 'company-select-next)
167 (define-key keymap (kbd "M-p") 'company-select-previous)
168 (define-key keymap (kbd "M-<return>") 'company-complete-selection)
169 (define-key keymap "\t" 'company-complete)
170 (define-key keymap (kbd "<f1>") 'company-show-doc-buffer)
171 keymap))
172
173 ;;;###autoload
174 (define-minor-mode company-mode
175 ""
176 nil " comp" company-mode-map
177 (if company-mode
178 (progn
179 (add-hook 'pre-command-hook 'company-pre-command nil t)
180 (add-hook 'post-command-hook 'company-post-command nil t)
181 (company-timer-set 'company-idle-delay
182 company-idle-delay))
183 (remove-hook 'pre-command-hook 'company-pre-command t)
184 (remove-hook 'post-command-hook 'company-post-command t)
185 (company-cancel)
186 (kill-local-variable 'company-point)))
187
188 ;;; backends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
189
190 (defun company-grab (regexp &optional expression)
191 (when (looking-back regexp)
192 (or (match-string-no-properties (or expression 0)) "")))
193
194 (defun company-in-string-or-comment (&optional point)
195 (let ((pos (syntax-ppss)))
196 (or (nth 3 pos) (nth 4 pos) (nth 7 pos))))
197
198 ;;; completion mechanism ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
199
200 (defvar company-backend nil)
201 (make-variable-buffer-local 'company-backend)
202
203 (defvar company-prefix nil)
204 (make-variable-buffer-local 'company-prefix)
205
206 (defvar company-candidates nil)
207 (make-variable-buffer-local 'company-candidates)
208
209 (defvar company-candidates-cache nil)
210 (make-variable-buffer-local 'company-candidates-cache)
211
212 (defvar company-common nil)
213 (make-variable-buffer-local 'company-common)
214
215 (defvar company-selection 0)
216 (make-variable-buffer-local 'company-selection)
217
218 (defvar company-selection-changed nil)
219 (make-variable-buffer-local 'company-selection-changed)
220
221 (defvar company-point nil)
222 (make-variable-buffer-local 'company-point)
223
224 (defvar company-disabled-backends nil)
225
226 (defsubst company-strip-prefix (str)
227 (substring str (length company-prefix)))
228
229 (defsubst company-reformat (candidate)
230 ;; company-ispell needs this, because the results are always lower-case
231 ;; It's mory efficient to fix it only when they are displayed.
232 (concat company-prefix (substring candidate (length company-prefix))))
233
234 (defsubst company-should-complete (prefix)
235 (and (eq company-idle-delay t)
236 (>= (length prefix) company-minimum-prefix-length)))
237
238 (defsubst company-call-frontends (command)
239 (dolist (frontend company-frontends)
240 (funcall frontend command)))
241
242 (defsubst company-calculate-candidates (prefix)
243 (or (setq company-candidates (cdr (assoc prefix company-candidates-cache)))
244 (let ((len (length prefix))
245 (completion-ignore-case (funcall company-backend 'ignore-case))
246 prev)
247 (dotimes (i len)
248 (when (setq prev (cdr (assoc (substring prefix 0 (- len i))
249 company-candidates-cache)))
250 (setq company-candidates (all-completions prefix prev))
251 (return t))))
252 (progn
253 (setq company-candidates (funcall company-backend 'candidates prefix))
254 (unless (funcall company-backend 'sorted)
255 (setq company-candidates (sort company-candidates 'string<)))))
256 (unless (assoc prefix company-candidates-cache)
257 (push (cons prefix company-candidates) company-candidates-cache))
258 (setq company-selection 0
259 company-prefix prefix)
260 (let ((completion-ignore-case (funcall company-backend 'ignore-case)))
261 (setq company-common (try-completion company-prefix company-candidates)))
262 (when (eq company-common t)
263 (setq company-candidates nil))
264 company-candidates)
265
266 (defun company-idle-begin ()
267 (and company-mode
268 (not company-candidates)
269 (not (equal (point) company-point))
270 (let ((company-idle-delay t))
271 (company-begin)
272 (company-post-command))))
273
274 (defun company-manual-begin ()
275 (and company-mode
276 (not company-candidates)
277 (let ((company-idle-delay t)
278 (company-minimum-prefix-length 0))
279 (company-begin)))
280 ;; Return non-nil if active.
281 company-candidates)
282
283 (defun company-continue ()
284 (when company-candidates
285 (let ((new-prefix (funcall company-backend 'prefix)))
286 (unless (and (= (- (point) (length new-prefix))
287 (- company-point (length company-prefix)))
288 (or (equal company-prefix new-prefix)
289 (company-calculate-candidates new-prefix)))
290 (setq company-candidates nil)))))
291
292 (defun company-begin ()
293 (company-continue)
294 (unless company-candidates
295 (let (prefix)
296 (dolist (backend company-backends)
297 (unless (fboundp backend)
298 (ignore-errors (require backend nil t)))
299 (if (fboundp backend)
300 (when (setq prefix (funcall backend 'prefix))
301 (when (company-should-complete prefix)
302 (setq company-backend backend)
303 (company-calculate-candidates prefix))
304 (return prefix))
305 (unless (memq backend company-disabled-backends)
306 (push backend company-disabled-backends)
307 (message "Company back-end '%s' could not be initialized"
308 backend))))))
309 (if company-candidates
310 (progn
311 (setq company-point (point))
312 (company-call-frontends 'update))
313 (company-cancel)))
314
315 (defun company-cancel ()
316 (setq company-backend nil
317 company-prefix nil
318 company-candidates nil
319 company-candidates-cache nil
320 company-common nil
321 company-selection 0
322 company-selection-changed nil
323 company-point nil)
324 (company-call-frontends 'hide))
325
326 (defun company-abort ()
327 (company-cancel)
328 ;; Don't start again, unless started manually.
329 (setq company-point (point)))
330
331 (defun company-pre-command ()
332 (unless (eq this-command 'company-show-doc-buffer)
333 (condition-case err
334 (when company-candidates
335 (company-call-frontends 'pre-command))
336 (error (message "Company: An error occurred in pre-command")
337 (message "%s" (error-message-string err))
338 (company-cancel)))))
339
340 (defun company-post-command ()
341 (unless (eq this-command 'company-show-doc-buffer)
342 (condition-case err
343 (progn
344 (unless (equal (point) company-point)
345 (company-begin))
346 (when company-candidates
347 (company-call-frontends 'post-command)))
348 (error (message "Company: An error occurred in post-command")
349 (message "%s" (error-message-string err))
350 (company-cancel)))))
351
352 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
353
354 (defun company-select-next ()
355 (interactive)
356 (when (company-manual-begin)
357 (setq company-selection (min (1- (length company-candidates))
358 (1+ company-selection))
359 company-selection-changed t))
360 (company-call-frontends 'update))
361
362 (defun company-select-previous ()
363 (interactive)
364 (when (company-manual-begin)
365 (setq company-selection (max 0 (1- company-selection))
366 company-selection-changed t))
367 (company-call-frontends 'update))
368
369 (defun company-complete-selection ()
370 (interactive)
371 (when (company-manual-begin)
372 (insert (company-strip-prefix (nth company-selection company-candidates)))
373 (company-abort)))
374
375 (defun company-complete-common ()
376 (interactive)
377 (when (company-manual-begin)
378 (insert (company-strip-prefix company-common))))
379
380 (defun company-complete ()
381 (interactive)
382 (when (company-manual-begin)
383 (if (or company-selection-changed
384 (eq last-command 'company-complete-common))
385 (call-interactively 'company-complete-selection)
386 (call-interactively 'company-complete-common)
387 (setq this-command 'company-complete-common))))
388
389 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
390
391 (defconst company-space-strings-limit 100)
392
393 (defconst company-space-strings
394 (let (lst)
395 (dotimes (i company-space-strings-limit)
396 (push (make-string (- company-space-strings-limit 1 i) ?\ ) lst))
397 (apply 'vector lst)))
398
399 (defsubst company-space-string (len)
400 (if (< len company-space-strings-limit)
401 (aref company-space-strings len)
402 (make-string len ?\ )))
403
404 (defsubst company-safe-substring (str from &optional to)
405 (let ((len (length str)))
406 (if (> from len)
407 ""
408 (if (and to (> to len))
409 (concat (substring str from)
410 (company-space-string (- to len)))
411 (substring str from to)))))
412
413 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
414
415 (defvar company-last-metadata nil)
416 (make-variable-buffer-local 'company-last-metadata)
417
418 (defun company-fetch-metadata ()
419 (let ((selected (nth company-selection company-candidates)))
420 (unless (equal selected (car company-last-metadata))
421 (setq company-last-metadata
422 (cons selected (funcall company-backend 'meta selected))))
423 (cdr company-last-metadata)))
424
425 (defun company-doc-buffer (&optional string)
426 (with-current-buffer (get-buffer-create "*Company meta-data*")
427 (erase-buffer)
428 (current-buffer)))
429
430 (defun company-show-doc-buffer ()
431 (interactive)
432 (when company-candidates
433 (save-window-excursion
434 (let* ((selected (nth company-selection company-candidates))
435 (buffer (funcall company-backend 'doc-buffer selected)))
436 (if (not buffer)
437 (error "No documentation available.")
438 (display-buffer buffer)
439 (read-event)
440 (when last-input-event
441 (clear-this-command-keys t)
442 (setq unread-command-events (list last-input-event))))))))
443
444 ;;; pseudo-tooltip ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
445
446 (defvar company-pseudo-tooltip-overlay nil)
447 (make-variable-buffer-local 'company-pseudo-tooltip-overlay)
448
449 (defvar company-tooltip-offset 0)
450 (make-variable-buffer-local 'company-tooltip-offset)
451
452 (defun company-pseudo-tooltip-update-offset (selection num-lines limit)
453
454 (decf limit 2)
455 (setq company-tooltip-offset
456 (max (min selection company-tooltip-offset)
457 (- selection -1 limit)))
458
459 (when (<= company-tooltip-offset 1)
460 (incf limit)
461 (setq company-tooltip-offset 0))
462
463 (when (>= company-tooltip-offset (- num-lines limit 1))
464 (incf limit)
465 (when (= selection (1- num-lines))
466 (setq company-tooltip-offset (max (1- company-tooltip-offset) 0))))
467
468 limit)
469
470 ;;; propertize
471
472 (defun company-fill-propertize (line width selected)
473 (setq line (company-safe-substring line 0 width))
474 (add-text-properties 0 width
475 (list 'face (if selected
476 'company-tooltip-selection
477 'company-tooltip)) line)
478 (add-text-properties 0 (length company-common)
479 (list 'face (if selected
480 'company-tooltip-common-selection
481 'company-tooltip-common)) line)
482 line)
483
484 ;;; replace
485
486 (defun company-buffer-lines (beg end)
487 (goto-char beg)
488 (let ((row (cdr (posn-col-row (posn-at-point))))
489 lines)
490 (while (< (point) end)
491 (move-to-window-line (incf row))
492 (push (buffer-substring beg (min end (1- (point)))) lines)
493 (setq beg (point)))
494 (nreverse lines)))
495
496 (defun company-modify-line (old new offset)
497 (concat (company-safe-substring old 0 offset)
498 new
499 (company-safe-substring old (+ offset (length new)))))
500
501 (defun company-replacement-string (old lines column nl)
502 (let (new)
503 ;; Inject into old lines.
504 (while old
505 (push (company-modify-line (pop old) (pop lines) column) new))
506 ;; Append whole new lines.
507 (while lines
508 (push (company-modify-line "" (pop lines) column) new))
509 (concat (when nl "\n")
510 (mapconcat 'identity (nreverse new) "\n")
511 "\n")))
512
513 (defun company-create-lines (column lines selection)
514
515 (let ((limit (max company-tooltip-limit 3))
516 (len (length lines))
517 width
518 lines-copy
519 previous
520 remainder
521 new)
522
523 ;; Scroll to offset.
524 (setq limit (company-pseudo-tooltip-update-offset selection len limit))
525
526 (when (> company-tooltip-offset 0)
527 (setq previous (format "...(%d)" company-tooltip-offset)))
528
529 (setq remainder (- len limit company-tooltip-offset)
530 remainder (when (> remainder 0)
531 (setq remainder (format "...(%d)" remainder))))
532
533 (decf selection company-tooltip-offset)
534 (setq width (min (length previous) (length remainder))
535 lines (nthcdr company-tooltip-offset lines)
536 len (min limit (length lines))
537 lines-copy lines)
538
539 (dotimes (i len)
540 (setq width (max (length (pop lines-copy)) width)))
541 (setq width (min width (- (window-width) column)))
542
543 (when previous
544 (push (propertize (company-safe-substring previous 0 width)
545 'face 'company-tooltip)
546 new))
547
548 (dotimes (i len)
549 (push (company-fill-propertize (company-reformat (pop lines))
550 width (equal i selection))
551 new))
552
553 (when remainder
554 (push (propertize (company-safe-substring remainder 0 width)
555 'face 'company-tooltip)
556 new))
557
558 (setq lines (nreverse new))))
559
560 ;; show
561
562 (defun company-pseudo-tooltip-show (row column lines selection)
563 (company-pseudo-tooltip-hide)
564 (unless lines (error "No text provided"))
565 (save-excursion
566
567 (move-to-column 0)
568
569 (let* ((lines (company-create-lines column lines selection))
570 (nl (< (move-to-window-line row) row))
571 (beg (point))
572 (end (save-excursion
573 (move-to-window-line (min (window-height)
574 (+ row company-tooltip-limit)))
575 (point)))
576 (old-string (company-buffer-lines beg end))
577 str)
578
579 (setq company-pseudo-tooltip-overlay (make-overlay beg end))
580
581 (overlay-put company-pseudo-tooltip-overlay 'company-old old-string)
582 (overlay-put company-pseudo-tooltip-overlay 'company-column column)
583 (overlay-put company-pseudo-tooltip-overlay 'company-nl nl)
584 (overlay-put company-pseudo-tooltip-overlay 'company-before
585 (company-replacement-string old-string lines column nl))
586
587 (overlay-put company-pseudo-tooltip-overlay 'window (selected-window)))))
588
589 (defun company-pseudo-tooltip-show-at-point (pos)
590 (let ((col-row (posn-col-row (posn-at-point pos))))
591 (company-pseudo-tooltip-show (1+ (cdr col-row)) (car col-row)
592 company-candidates company-selection)))
593
594 (defun company-pseudo-tooltip-edit (lines selection)
595 (let* ((old-string (overlay-get company-pseudo-tooltip-overlay 'company-old))
596 (column (overlay-get company-pseudo-tooltip-overlay 'company-column))
597 (nl (overlay-get company-pseudo-tooltip-overlay 'company-nl))
598 (lines (company-create-lines column lines selection)))
599 (overlay-put company-pseudo-tooltip-overlay 'company-before
600 (company-replacement-string old-string lines column nl))))
601
602 (defun company-pseudo-tooltip-hide ()
603 (when company-pseudo-tooltip-overlay
604 (delete-overlay company-pseudo-tooltip-overlay)
605 (setq company-pseudo-tooltip-overlay nil)))
606
607 (defun company-pseudo-tooltip-hide-temporarily ()
608 (when (overlayp company-pseudo-tooltip-overlay)
609 (overlay-put company-pseudo-tooltip-overlay 'invisible nil)
610 (overlay-put company-pseudo-tooltip-overlay 'before-string nil)))
611
612 (defun company-pseudo-tooltip-unhide ()
613 (when company-pseudo-tooltip-overlay
614 (overlay-put company-pseudo-tooltip-overlay 'invisible t)
615 (overlay-put company-pseudo-tooltip-overlay 'before-string
616 (overlay-get company-pseudo-tooltip-overlay 'company-before))))
617
618 (defun company-pseudo-tooltip-frontend (command)
619 (case command
620 ('pre-command (company-pseudo-tooltip-hide-temporarily))
621 ('post-command
622 (unless (overlayp company-pseudo-tooltip-overlay)
623 (company-pseudo-tooltip-show-at-point (- (point)
624 (length company-prefix))))
625 (company-pseudo-tooltip-unhide))
626 ('hide (company-pseudo-tooltip-hide)
627 (setq company-tooltip-offset 0))
628 ('update (when (overlayp company-pseudo-tooltip-overlay)
629 (company-pseudo-tooltip-edit company-candidates
630 company-selection)))))
631
632 (defun company-pseudo-tooltip-unless-just-one-frontend (command)
633 (unless (and (eq command 'post-command)
634 (not (cdr company-candidates)))
635 (company-pseudo-tooltip-frontend command)))
636
637 ;;; overlay ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
638
639 (defvar company-preview-overlay nil)
640 (make-variable-buffer-local 'company-preview-overlay)
641
642 (defun company-preview-show-at-point (pos)
643 (company-preview-hide)
644
645 (setq company-preview-overlay (make-overlay pos pos))
646
647 (let ((completion (company-strip-prefix (nth company-selection
648 company-candidates))))
649 (and (equal pos (point))
650 (not (equal completion ""))
651 (add-text-properties 0 1 '(cursor t) completion))
652
653 (setq completion (propertize completion 'face 'company-preview))
654 (add-text-properties 0 (- (length company-common) (length company-prefix))
655 '(face company-preview-common) completion)
656
657 (overlay-put company-preview-overlay 'after-string completion)
658 (overlay-put company-preview-overlay 'window (selected-window))))
659
660 (defun company-preview-hide ()
661 (when company-preview-overlay
662 (delete-overlay company-preview-overlay)
663 (setq company-preview-overlay nil)))
664
665 (defun company-preview-frontend (command)
666 (case command
667 ('pre-command (company-preview-hide))
668 ('post-command (company-preview-show-at-point (point)))
669 ('hide (company-preview-hide))))
670
671 (defun company-preview-if-just-one-frontend (command)
672 (unless (and (eq command 'post-command)
673 (cdr company-candidates))
674 (company-preview-frontend command)))
675
676 ;;; echo ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
677
678 (defvar company-echo-last-msg nil)
679 (make-variable-buffer-local 'company-echo-last-msg)
680
681 (defun company-echo-refresh ()
682 (let ((message-log-max nil))
683 (if company-echo-last-msg
684 (message "%s" company-echo-last-msg)
685 (message ""))))
686
687 (defun company-echo-show (candidates)
688
689 ;; Roll to selection.
690 (setq candidates (nthcdr company-selection candidates))
691
692 (let ((limit (window-width (minibuffer-window)))
693 (len -1)
694 comp msg)
695 (while candidates
696 (setq comp (company-reformat (pop candidates))
697 len (+ len 1 (length comp)))
698 (if (>= len limit)
699 (setq candidates nil)
700 (setq comp (propertize comp 'face 'company-echo))
701 (add-text-properties 0 (length company-common)
702 '(face company-echo-common) comp)
703 (push comp msg)))
704
705 (setq company-echo-last-msg (mapconcat 'identity (nreverse msg) " "))
706 (company-echo-refresh)))
707
708 (defun company-echo-frontend (command)
709 (case command
710 ('pre-command (company-echo-refresh))
711 ('post-command (company-echo-show company-candidates))
712 ('hide (setq company-echo-last-msg nil))))
713
714 (defun company-echo-metadata-frontend (command)
715 (case command
716 ('pre-command (company-echo-refresh))
717 ('post-command (setq company-echo-last-msg (company-fetch-metadata))
718 (company-echo-refresh))
719 ('hide (setq company-echo-last-msg nil))))
720
721
722 (provide 'company)
723 ;;; company.el ends here