]> rtime.felk.cvut.cz Git - sojka/company-mode.git/blob - company.el
Don't hide the echo message if it isn't shown.
[sojka/company-mode.git] / 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: 0.1
7 ;; Keywords: abbrev, convenience, matchis
8 ;; URL: http://nschum.de/src/emacs/company/
9 ;; Compatibility: GNU Emacs 22.x, 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 ;; Company is a modular completion mechanism.  Modules for retrieving completion
29 ;; candidates are called back-ends, modules for displaying them are front-ends.
30 ;;
31 ;; Company comes with many back-ends, e.g. `company-elisp'.  These are
32 ;; distributed in individual files and can be used individually.
33 ;;
34 ;; Place company.el and the back-ends you want to use in a directory and add the
35 ;; following to your .emacs:
36 ;; (add-to-list 'load-path "/path/to/company")
37 ;; (autoload 'company-mode "company" nil t)
38 ;;
39 ;; Enable company-mode with M-x company-mode.  For further information look at
40 ;; the documentation for `company-mode' (C-h f company-mode RET)
41 ;;
42 ;; To write your own back-end, look at the documentation for `company-backends'.
43 ;; Here is a simple example completing "foo":
44 ;;
45 ;; (defun company-my-backend (command &optional arg &rest ignored)
46 ;;   (case command
47 ;;     ('prefix (when (looking-back "foo\\>")
48 ;;                (match-string 0)))
49 ;;     ('candidates (list "foobar" "foobaz" "foobarbaz"))
50 ;;     ('meta (format "This value is named %s" arg))))
51 ;;
52 ;; Known Issues:
53 ;; When point is at the very end of the buffer, the pseudo-tooltip appears very
54 ;; wrong.
55 ;;
56 ;;; Change Log:
57 ;;
58 ;;    Don't hide the echo message if it isn't shown.
59 ;;
60 ;; 2009-03-20 (0.1)
61 ;;    Initial release.
62 ;;
63 ;;; Code:
64
65 (eval-when-compile (require 'cl))
66
67 (add-to-list 'debug-ignored-errors
68              "^Pseudo tooltip frontend cannot be used twice$")
69 (add-to-list 'debug-ignored-errors "^Preview frontend cannot be used twice$")
70 (add-to-list 'debug-ignored-errors "^Echo area cannot be used twice$")
71 (add-to-list 'debug-ignored-errors "^No documentation available$")
72 (add-to-list 'debug-ignored-errors "^Company not enabled$")
73 (add-to-list 'debug-ignored-errors "^Company not in search mode$")
74
75 (defgroup company nil
76   "Extensible inline text completion mechanism"
77   :group 'abbrev
78   :group 'convenience
79   :group 'maching)
80
81 (defface company-tooltip
82   '((t :background "yellow"
83        :foreground "black"))
84   "*Face used for the tool tip."
85   :group 'company)
86
87 (defface company-tooltip-selection
88   '((default :inherit company-tooltip)
89     (((class color) (min-colors 88)) (:background "orange1"))
90     (t (:background "green")))
91   "*Face used for the selection in the tool tip."
92   :group 'company)
93
94 (defface company-tooltip-common
95   '((t :inherit company-tooltip
96        :foreground "red"))
97   "*Face used for the common completion in the tool tip."
98   :group 'company)
99
100 (defface company-tooltip-common-selection
101   '((t :inherit company-tooltip-selection
102        :foreground "red"))
103   "*Face used for the selected common completion in the tool tip."
104   :group 'company)
105
106 (defcustom company-tooltip-limit 10
107   "*The maximum number of candidates in the tool tip"
108   :group 'company
109   :type 'integer)
110
111 (defface company-preview
112   '((t :background "blue4"
113        :foreground "wheat"))
114   "*Face used for the completion preview."
115   :group 'company)
116
117 (defface company-preview-common
118   '((t :inherit company-preview
119        :foreground "red"))
120   "*Face used for the common part of the completion preview."
121   :group 'company)
122
123 (defface company-echo nil
124   "*Face used for completions in the echo area."
125   :group 'company)
126
127 (defface company-echo-common
128   '((((background dark)) (:foreground "firebrick1"))
129     (((background light)) (:background "firebrick4")))
130   "*Face used for the common part of completions in the echo area."
131   :group 'company)
132
133 (defun company-frontends-set (variable value)
134   ;; uniquify
135   (let ((remainder value))
136     (setcdr remainder (delq (car remainder) (cdr remainder))))
137   (and (memq 'company-pseudo-tooltip-unless-just-one-frontend value)
138        (memq 'company-pseudo-tooltip-frontend value)
139        (error "Pseudo tooltip frontend cannot be used twice"))
140   (and (memq 'company-preview-if-just-one-frontend value)
141        (memq 'company-preview-frontend value)
142        (error "Preview frontend cannot be used twice"))
143   (and (memq 'company-echo value)
144        (memq 'company-echo-metadata-frontend value)
145        (error "Echo area cannot be used twice"))
146   ;; preview must come last
147   (dolist (f '(company-preview-if-just-one-frontend company-preview-frontend))
148     (when (memq f value)
149       (setq value (append (delq f value) (list f)))))
150   (set variable value))
151
152 (defcustom company-frontends '(company-pseudo-tooltip-unless-just-one-frontend
153                                company-preview-if-just-one-frontend
154                                company-echo-metadata-frontend)
155   "*The list of active front-ends (visualizations).
156 Each front-end is a function that takes one argument.  It is called with
157 one of the following arguments:
158
159 'show: When the visualization should start.
160
161 'hide: When the visualization should end.
162
163 'update: When the data has been updated.
164
165 'pre-command: Before every command that is executed while the
166 visualization is active.
167
168 'post-command: After every command that is executed while the
169 visualization is active.
170
171 The visualized data is stored in `company-prefix', `company-candidates',
172 `company-common', `company-selection', `company-point' and
173 `company-search-string'."
174   :set 'company-frontends-set
175   :group 'company
176   :type '(repeat (choice (const :tag "echo" company-echo-frontend)
177                          (const :tag "pseudo tooltip"
178                                 company-pseudo-tooltip-frontend)
179                          (const :tag "pseudo tooltip, multiple only"
180                                 company-pseudo-tooltip-unless-just-one-frontend)
181                          (const :tag "preview" company-preview-frontend)
182                          (const :tag "preview, unique only"
183                                 company-preview-if-just-one-frontend)
184                          (function :tag "custom function" nil))))
185
186 (defcustom company-backends '(company-elisp company-nxml company-css
187                               company-semantic company-gtags company-oddmuse
188                               company-files company-dabbrev)
189   "*The list of active back-ends (completion engines).
190 Each back-end is a function that takes a variable number of arguments.
191 The first argument is the command requested from the back-end.  It is one
192 of the following:
193
194 'prefix: The back-end should return the text to be completed.  It must be
195 text immediately before `point'.  Returning nil passes control to the next
196 back-end.
197
198 'candidates: The second argument is the prefix to be completed.  The
199 return value should be a list of candidates that start with the prefix.
200
201 Optional commands:
202
203 'sorted: The back-end may return t here to indicate that the candidates
204 are sorted and will not need to be sorted again.
205
206 'no-cache: Usually company doesn't ask for candidates again as completion
207 progresses, unless the back-end returns t for this command.  The second
208 argument is the latest prefix.
209
210 'meta: The second argument is a completion candidate.  The back-end should
211 return a (short) documentation string for it.
212
213 'doc-buffer: The second argument is a completion candidate.  The back-end should
214 create a buffer (preferably with `company-doc-buffer'), fill it with
215 documentation and return it.
216
217 The back-end should return nil for all commands it does not support or
218 does not know about."
219   :group 'company
220   :type '(repeat (function :tag "function" nil)))
221
222 (defcustom company-minimum-prefix-length 3
223   "*The minimum prefix length for automatic completion."
224   :group 'company
225   :type '(integer :tag "prefix length"))
226
227 (defcustom company-idle-delay .7
228   "*The idle delay in seconds until automatic completions starts.
229 A value of nil means never complete automatically, t means complete
230 immediately when a prefix of `company-minimum-prefix-length' is reached."
231   :group 'company
232   :type '(choice (const :tag "never (nil)" nil)
233                  (const :tag "immediate (t)" t)
234                  (number :tag "seconds")))
235
236 ;;; mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
237
238 (defvar company-mode-map (make-sparse-keymap)
239   "Keymap used by `company-mode'.")
240
241 (defvar company-active-map
242   (let ((keymap (make-sparse-keymap)))
243     (define-key keymap (kbd "M-n") 'company-select-next)
244     (define-key keymap (kbd "M-p") 'company-select-previous)
245     (define-key keymap (kbd "<down>") 'company-select-next)
246     (define-key keymap (kbd "<up>") 'company-select-previous)
247     (define-key keymap "\C-m" 'company-complete-selection)
248     (define-key keymap "\t" 'company-complete-common)
249     (define-key keymap (kbd "<f1>") 'company-show-doc-buffer)
250     (define-key keymap "\C-s" 'company-search-candidates)
251     keymap)
252   "Keymap that is enabled during an active completion.")
253
254 ;;;###autoload
255 (define-minor-mode company-mode
256   "\"complete anything\"; in in-buffer completion framework.
257 Completion starts automatically, depending on the values
258 `company-idle-delay' and `company-minimum-prefix-length'
259
260 Completion can be controlled with the commands:
261 `company-complete-common', `company-complete-selection', `company-complete',
262 `company-select-next', `company-select-previous'.
263
264 Completions can be searched with `company-search-candidates'.
265
266 The completion data is retrieved using `company-backends' and displayed using
267 `company-frontends'.
268
269 regular keymap:
270
271 \\{company-mode-map}
272 keymap during active completions:
273
274 \\{company-active-map}"
275   nil " comp" company-mode-map
276   (if company-mode
277       (progn
278         (add-hook 'pre-command-hook 'company-pre-command nil t)
279         (add-hook 'post-command-hook 'company-post-command nil t))
280     (remove-hook 'pre-command-hook 'company-pre-command t)
281     (remove-hook 'post-command-hook 'company-post-command t)
282     (company-cancel)
283     (kill-local-variable 'company-point)))
284
285 ;;; keymaps ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
286
287 (defvar company-overriding-keymap-bound nil)
288 (make-variable-buffer-local 'company-overriding-keymap-bound)
289
290 (defvar company-old-keymap nil)
291 (make-variable-buffer-local 'company-old-keymap)
292
293 (defvar company-my-keymap nil)
294 (make-variable-buffer-local 'company-my-keymap)
295
296 (defsubst company-enable-overriding-keymap (keymap)
297   (setq company-my-keymap keymap)
298   (when company-overriding-keymap-bound
299     (company-uninstall-map)))
300
301 (defun company-install-map ()
302   (unless (or company-overriding-keymap-bound
303               (null company-my-keymap))
304     (setq company-old-keymap overriding-terminal-local-map
305           overriding-terminal-local-map company-my-keymap
306           company-overriding-keymap-bound t)))
307
308 (defun company-uninstall-map ()
309   (when (and company-overriding-keymap-bound
310              (eq overriding-terminal-local-map company-my-keymap))
311     (setq overriding-terminal-local-map company-old-keymap
312           company-overriding-keymap-bound nil)))
313
314 ;; Hack:
315 ;; Emacs calculates the active keymaps before reading the event.  That means we
316 ;; cannot change the keymap from a timer.  So we send a bogus command.
317 (defun company-ignore ()
318   (interactive))
319
320 (global-set-key '[31415926] 'company-ignore)
321
322 (defun company-input-noop ()
323   (push 31415926 unread-command-events))
324
325 ;;; backends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
326
327 (defun company-grab (regexp &optional expression)
328   (when (looking-back regexp)
329     (or (match-string-no-properties (or expression 0)) "")))
330
331 (defun company-in-string-or-comment (&optional point)
332   (let ((pos (syntax-ppss)))
333     (or (nth 3 pos) (nth 4 pos) (nth 7 pos))))
334
335 ;;; completion mechanism ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
336
337 (defvar company-backend nil)
338 (make-variable-buffer-local 'company-backend)
339
340 (defvar company-prefix nil)
341 (make-variable-buffer-local 'company-prefix)
342
343 (defvar company-candidates nil)
344 (make-variable-buffer-local 'company-candidates)
345
346 (defvar company-candidates-length nil)
347 (make-variable-buffer-local 'company-candidates-length)
348
349 (defvar company-candidates-cache nil)
350 (make-variable-buffer-local 'company-candidates-cache)
351
352 (defvar company-candidates-predicate nil)
353 (make-variable-buffer-local 'company-candidates-predicate)
354
355 (defvar company-common nil)
356 (make-variable-buffer-local 'company-common)
357
358 (defvar company-selection 0)
359 (make-variable-buffer-local 'company-selection)
360
361 (defvar company-selection-changed nil)
362 (make-variable-buffer-local 'company-selection-changed)
363
364 (defvar company-point nil)
365 (make-variable-buffer-local 'company-point)
366
367 (defvar company-timer nil)
368
369 (defvar company-disabled-backends nil)
370
371 (defsubst company-strip-prefix (str)
372   (substring str (length company-prefix)))
373
374 (defsubst company-reformat (candidate)
375   ;; company-ispell needs this, because the results are always lower-case
376   ;; It's mory efficient to fix it only when they are displayed.
377   (concat company-prefix (substring candidate (length company-prefix))))
378
379 (defsubst company-should-complete (prefix)
380   (and (eq company-idle-delay t)
381        (>= (length prefix) company-minimum-prefix-length)))
382
383 (defsubst company-call-frontends (command)
384   (dolist (frontend company-frontends)
385     (condition-case err
386         (funcall frontend command)
387       (error (error "Company: Front-end %s error \"%s\" on command %s"
388                     frontend (error-message-string err) command)))))
389
390 (defsubst company-set-selection (selection &optional force-update)
391   (setq selection (max 0 (min (1- company-candidates-length) selection)))
392   (when (or force-update (not (equal selection company-selection)))
393     (setq company-selection selection
394           company-selection-changed t)
395     (company-call-frontends 'update)))
396
397 (defun company-apply-predicate (candidates predicate)
398   (let (new)
399     (dolist (c candidates)
400       (when (funcall predicate c)
401         (push c new)))
402     (nreverse new)))
403
404 (defun company-update-candidates (candidates)
405   (setq company-candidates-length (length candidates))
406   (if (> company-selection 0)
407       ;; Try to restore the selection
408       (let ((selected (nth company-selection company-candidates)))
409         (setq company-selection 0
410               company-candidates candidates)
411         (when selected
412           (while (and candidates (string< (pop candidates) selected))
413             (incf company-selection))
414           (unless candidates
415             ;; Make sure selection isn't out of bounds.
416             (setq company-selection (min (1- company-candidates-length)
417                                          company-selection)))))
418     (setq company-selection 0
419           company-candidates candidates))
420   ;; Calculate common.
421   (let ((completion-ignore-case (funcall company-backend 'ignore-case)))
422     (setq company-common (try-completion company-prefix company-candidates)))
423   (when (eq company-common t)
424     (setq company-candidates nil)))
425
426 (defsubst company-calculate-candidates (prefix)
427   (setq company-prefix prefix)
428   (company-update-candidates
429    (or (cdr (assoc prefix company-candidates-cache))
430        (when company-candidates-cache
431          (let ((len (length prefix))
432                (completion-ignore-case (funcall company-backend 'ignore-case))
433                prev)
434            (dotimes (i len)
435              (when (setq prev (cdr (assoc (substring prefix 0 (- len i))
436                                           company-candidates-cache)))
437                (return (all-completions prefix prev))))))
438        (let ((candidates (funcall company-backend 'candidates prefix)))
439          (when company-candidates-predicate
440            (setq candidates
441                  (company-apply-predicate candidates
442                                           company-candidates-predicate)))
443          (unless (funcall company-backend 'sorted)
444            (setq candidates (sort candidates 'string<)))
445          candidates)))
446   (unless (assoc prefix company-candidates-cache)
447     (push (cons prefix company-candidates) company-candidates-cache))
448   company-candidates)
449
450 (defun company-idle-begin (buf win tick pos)
451   (and company-mode
452        (eq buf (current-buffer))
453        (eq win (selected-window))
454        (eq tick (buffer-chars-modified-tick))
455        (eq pos (point))
456        (not company-candidates)
457        (not (equal (point) company-point))
458        (let ((company-idle-delay t))
459          (company-begin)
460          (when company-candidates
461            (company-input-noop)
462            (company-post-command)))))
463
464 (defun company-manual-begin ()
465   (unless company-mode (error "Company not enabled"))
466   (and company-mode
467        (not company-candidates)
468        (let ((company-idle-delay t)
469              (company-minimum-prefix-length 0))
470          (company-begin)))
471   ;; Return non-nil if active.
472   company-candidates)
473
474 (defun company-continue ()
475   (when company-candidates
476     (when (funcall company-backend 'no-cache company-prefix)
477       ;; Don't complete existing candidates, fetch new ones.
478       (setq company-candidates-cache nil))
479     (let ((new-prefix (funcall company-backend 'prefix)))
480       (unless (and (= (- (point) (length new-prefix))
481                       (- company-point (length company-prefix)))
482                    (or (equal company-prefix new-prefix)
483                        (company-calculate-candidates new-prefix)))
484         (setq company-candidates nil)))))
485
486 (defun company-begin ()
487   (if (or buffer-read-only overriding-terminal-local-map overriding-local-map)
488       ;; Don't complete in these cases.
489       (setq company-candidates nil)
490     (company-continue)
491     (unless company-candidates
492       (let (prefix)
493         (dolist (backend company-backends)
494           (unless (fboundp backend)
495             (ignore-errors (require backend nil t)))
496           (if (fboundp backend)
497               (when (setq prefix (funcall backend 'prefix))
498                 (when (company-should-complete prefix)
499                   (setq company-backend backend)
500                   (company-calculate-candidates prefix))
501                 (return prefix))
502             (unless (memq backend company-disabled-backends)
503               (push backend company-disabled-backends)
504               (message "Company back-end '%s' could not be initialized"
505                        backend)))))))
506   (if company-candidates
507       (progn
508         (setq company-point (point))
509         (company-enable-overriding-keymap company-active-map)
510         (company-call-frontends 'update))
511     (company-cancel)))
512
513 (defun company-cancel ()
514   (setq company-backend nil
515         company-prefix nil
516         company-candidates nil
517         company-candidates-length nil
518         company-candidates-cache nil
519         company-candidates-predicate nil
520         company-common nil
521         company-selection 0
522         company-selection-changed nil
523         company-point nil)
524   (when company-timer
525     (cancel-timer company-timer))
526   (company-search-mode 0)
527   (company-call-frontends 'hide)
528   (company-enable-overriding-keymap nil))
529
530 (defun company-abort ()
531   (company-cancel)
532   ;; Don't start again, unless started manually.
533   (setq company-point (point)))
534
535 (defun company-pre-command ()
536   (unless (eq this-command 'company-show-doc-buffer)
537     (condition-case err
538         (when company-candidates
539           (company-call-frontends 'pre-command))
540       (error (message "Company: An error occurred in pre-command")
541              (message "%s" (error-message-string err))
542              (company-cancel))))
543   (when company-timer
544     (cancel-timer company-timer))
545   (company-uninstall-map))
546
547 (defun company-post-command ()
548   (unless (eq this-command 'company-show-doc-buffer)
549     (condition-case err
550         (progn
551           (unless (equal (point) company-point)
552             (company-begin))
553           (when company-candidates
554             (company-call-frontends 'post-command))
555           (when (numberp company-idle-delay)
556             (setq company-timer
557                   (run-with-timer company-idle-delay nil 'company-idle-begin
558                                   (current-buffer) (selected-window)
559                                   (buffer-chars-modified-tick) (point)))))
560       (error (message "Company: An error occurred in post-command")
561              (message "%s" (error-message-string err))
562              (company-cancel))))
563   (company-install-map))
564
565 ;;; search ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
566
567 (defvar company-search-string nil)
568 (make-variable-buffer-local 'company-search-string)
569
570 (defvar company-search-lighter " Search: \"\"")
571 (make-variable-buffer-local 'company-search-lighter)
572
573 (defvar company-search-old-map nil)
574 (make-variable-buffer-local 'company-search-old-map)
575
576 (defvar company-search-old-selection 0)
577 (make-variable-buffer-local 'company-search-old-selection)
578
579 (defun company-search (text lines)
580   (let ((quoted (regexp-quote text))
581         (i 0))
582     (dolist (line lines)
583       (when (string-match quoted line (length company-prefix))
584         (return i))
585       (incf i))))
586
587 (defun company-search-printing-char ()
588   (interactive)
589   (unless company-mode (error "Company not enabled"))
590   (unless company-search-mode (error "Company not in search mode"))
591   (setq company-search-string
592         (concat (or company-search-string "") (string last-command-event))
593         company-search-lighter (concat " Search: \"" company-search-string
594                                         "\""))
595   (let ((pos (company-search company-search-string
596                               (nthcdr company-selection company-candidates))))
597     (if (null pos)
598         (ding)
599       (company-set-selection (+ company-selection pos) t))))
600
601 (defun company-search-repeat-forward ()
602   "Repeat the incremental search in completion candidates forward."
603   (interactive)
604   (unless company-mode (error "Company not enabled"))
605   (unless company-search-mode (error "Company not in search mode"))
606   (let ((pos (company-search company-search-string
607                               (cdr (nthcdr company-selection
608                                            company-candidates)))))
609     (if (null pos)
610         (ding)
611       (company-set-selection (+ company-selection pos 1) t))))
612
613 (defun company-search-repeat-backward ()
614   "Repeat the incremental search in completion candidates backwards."
615   (interactive)
616   (unless company-mode (error "Company not enabled"))
617   (unless company-search-mode (error "Company not in search mode"))
618   (let ((pos (company-search company-search-string
619                               (nthcdr (- company-candidates-length
620                                          company-selection)
621                                       (reverse company-candidates)))))
622     (if (null pos)
623         (ding)
624       (company-set-selection (- company-selection pos 1) t))))
625
626 (defsubst company-create-match-predicate (search-string)
627   `(lambda (candidate)
628      ,(if company-candidates-predicate
629           `(and (string-match ,search-string candidate)
630                 (funcall ,company-candidates-predicate candidate))
631         `(string-match ,company-search-string candidate))))
632
633 (defun company-search-kill-others ()
634   "Limit the completion candidates to the ones matching the search string."
635   (interactive)
636   (unless company-mode (error "Company not enabled"))
637   (unless company-search-mode (error "Company not in search mode"))
638   (let ((predicate (company-create-match-predicate company-search-string)))
639     (setq company-candidates-predicate predicate)
640     (company-update-candidates (company-apply-predicate company-candidates
641                                                         predicate))
642     (company-search-mode 0)
643     (company-call-frontends 'update)))
644
645 (defun company-search-abort ()
646   "Abort searching the completion candidates."
647   (interactive)
648   (unless company-mode (error "Company not enabled"))
649   (unless company-search-mode (error "Company not in search mode"))
650   (company-set-selection company-search-old-selection t)
651   (company-search-mode 0))
652
653 (defun company-search-other-char ()
654   (interactive)
655   (unless company-mode (error "Company not enabled"))
656   (unless company-search-mode (error "Company not in search mode"))
657   (company-search-mode 0)
658   (when last-input-event
659     (clear-this-command-keys t)
660     (setq unread-command-events (list last-input-event))))
661
662 (defvar company-search-map
663   (let ((i 0)
664         (keymap (make-keymap)))
665     (if (fboundp 'max-char)
666         (set-char-table-range (nth 1 keymap) (cons #x100 (max-char))
667                               'company-search-printing-char)
668       (with-no-warnings
669         ;; obselete in Emacs 23
670         (let ((l (generic-character-list))
671               (table (nth 1 keymap)))
672           (while l
673             (set-char-table-default table (car l) 'isearch-printing-char)
674             (setq l (cdr l))))))
675     (define-key keymap [t] 'company-search-other-char)
676     (while (< i ?\s)
677       (define-key keymap (make-string 1 i) 'company-search-other-char)
678       (incf i))
679     (while (< i 256)
680       (define-key keymap (vector i) 'company-search-printing-char)
681       (incf i))
682     (let ((meta-map (make-sparse-keymap)))
683       (define-key keymap (char-to-string meta-prefix-char) meta-map)
684       (define-key keymap [escape] meta-map))
685     (define-key keymap (vector meta-prefix-char t) 'company-search-other-char)
686     (define-key keymap "\e\e\e" 'company-search-other-char)
687     (define-key keymap  [escape escape escape] 'company-search-other-char)
688
689     (define-key keymap "\C-g" 'company-search-abort)
690     (define-key keymap "\C-s" 'company-search-repeat-forward)
691     (define-key keymap "\C-r" 'company-search-repeat-backward)
692     (define-key keymap "\C-o" 'company-search-kill-others)
693     keymap)
694   "Keymap used for incrementally searching the completion candidates.")
695
696 (define-minor-mode company-search-mode
697   "Start searching the completion candidates incrementally.
698
699 \\<company-search-map>Search can be controlled with the commands:
700 - `company-search-repeat-forward' (\\[company-search-repeat-forward])
701 - `company-search-repeat-backward' (\\[company-search-repeat-backward])
702 - `company-search-abort' (\\[company-search-abort])
703
704 Regular characters are appended to the search string.
705
706 The command `company-search-kill-others' (\\[company-search-kill-others]) uses
707  the search string to limit the completion candidates."
708   nil company-search-lighter nil
709   (if company-search-mode
710       (if (company-manual-begin)
711           (progn
712             (setq company-search-old-selection company-selection)
713             (company-enable-overriding-keymap company-search-map)
714             (company-call-frontends 'update))
715         (setq company-search-mode nil))
716     (kill-local-variable 'company-search-string)
717     (kill-local-variable 'company-search-lighter)
718     (kill-local-variable 'company-search-old-selection)
719     (company-enable-overriding-keymap company-active-map)))
720
721 (defun company-search-candidates ()
722   "Start searching the completion candidates incrementally.
723
724 \\<company-search-map>Search can be controlled with the commands:
725 - `company-search-repeat-forward' (\\[company-search-repeat-forward])
726 - `company-search-repeat-backward' (\\[company-search-repeat-backward])
727 - `company-search-abort' (\\[company-search-abort])
728
729 Regular characters are appended to the search string.
730
731 The command `company-search-kill-others' (\\[company-search-kill-others]) uses
732  the search string to limit the completion candidates."
733   (interactive)
734   (company-search-mode 1))
735
736 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
737
738 (defun company-select-next ()
739   "Select the next candidate in the list."
740   (interactive)
741   (when (company-manual-begin)
742     (company-set-selection (1+ company-selection))))
743
744 (defun company-select-previous ()
745   "Select the previous candidate in the list."
746   (interactive)
747   (when (company-manual-begin)
748     (company-set-selection (1- company-selection))))
749
750 (defun company-complete-selection ()
751   "Complete the selected candidate."
752   (interactive)
753   (when (company-manual-begin)
754     (insert (company-strip-prefix (nth company-selection company-candidates)))
755     (company-abort)))
756
757 (defun company-complete-common ()
758   "Complete the common part of all candidates."
759   (interactive)
760   (when (company-manual-begin)
761     (insert (company-strip-prefix company-common))))
762
763 (defun company-complete ()
764   "Complete the common part of all candidates or the current selection.
765 The first time this is called, the common part is completed, the second time, or
766 when the selection has been changed, the selected candidate is completed."
767   (interactive)
768   (when (company-manual-begin)
769     (if (or company-selection-changed
770             (eq last-command 'company-complete-common))
771         (call-interactively 'company-complete-selection)
772       (call-interactively 'company-complete-common)
773       (setq this-command 'company-complete-common))))
774
775 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
776
777 (defconst company-space-strings-limit 100)
778
779 (defconst company-space-strings
780   (let (lst)
781     (dotimes (i company-space-strings-limit)
782       (push (make-string (- company-space-strings-limit 1 i) ?\  ) lst))
783     (apply 'vector lst)))
784
785 (defsubst company-space-string (len)
786   (if (< len company-space-strings-limit)
787       (aref company-space-strings len)
788     (make-string len ?\ )))
789
790 (defsubst company-safe-substring (str from &optional to)
791   (let ((len (length str)))
792     (if (> from len)
793         ""
794       (if (and to (> to len))
795           (concat (substring str from)
796                   (company-space-string (- to len)))
797         (substring str from to)))))
798
799 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
800
801 (defvar company-last-metadata nil)
802 (make-variable-buffer-local 'company-last-metadata)
803
804 (defun company-fetch-metadata ()
805   (let ((selected (nth company-selection company-candidates)))
806     (unless (equal selected (car company-last-metadata))
807       (setq company-last-metadata
808             (cons selected (funcall company-backend 'meta selected))))
809     (cdr company-last-metadata)))
810
811 (defun company-doc-buffer (&optional string)
812   (with-current-buffer (get-buffer-create "*Company meta-data*")
813     (erase-buffer)
814     (current-buffer)))
815
816 (defun company-show-doc-buffer ()
817   "Temporarily show a buffer with the complete documentation for the selection."
818   (interactive)
819   (unless company-mode (error "Company not enabled"))
820   (when (company-manual-begin)
821     (save-window-excursion
822       (let* ((height (window-height))
823              (row (cdr (posn-col-row (posn-at-point))))
824              (selected (nth company-selection company-candidates))
825              (buffer (funcall company-backend 'doc-buffer selected)))
826         (if (not buffer)
827             (error "No documentation available.")
828           (display-buffer buffer)
829           (and (< (window-height) height)
830                (< (- (window-height) row 2) company-tooltip-limit)
831                (recenter (- (window-height) row 2)))
832           (while (eq 'scroll-other-window
833                      (key-binding (vector (list (read-event)))))
834             (scroll-other-window))
835           (when last-input-event
836             (clear-this-command-keys t)
837             (setq unread-command-events (list last-input-event))))))))
838
839 ;;; pseudo-tooltip ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
840
841 (defvar company-pseudo-tooltip-overlay nil)
842 (make-variable-buffer-local 'company-pseudo-tooltip-overlay)
843
844 (defvar company-tooltip-offset 0)
845 (make-variable-buffer-local 'company-tooltip-offset)
846
847 (defun company-pseudo-tooltip-update-offset (selection num-lines limit)
848
849   (decf limit 2)
850   (setq company-tooltip-offset
851         (max (min selection company-tooltip-offset)
852              (- selection -1 limit)))
853
854   (when (<= company-tooltip-offset 1)
855     (incf limit)
856     (setq company-tooltip-offset 0))
857
858   (when (>= company-tooltip-offset (- num-lines limit 1))
859     (incf limit)
860     (when (= selection (1- num-lines))
861       (decf company-tooltip-offset)
862       (when (<= company-tooltip-offset 1)
863         (setq company-tooltip-offset 0)
864         (incf limit))))
865
866   limit)
867
868 ;;; propertize
869
870 (defsubst company-round-tab (arg)
871   (* (/ (+ arg tab-width) tab-width) tab-width))
872
873 (defun company-untabify (str)
874   (let* ((pieces (split-string str "\t"))
875          (copy pieces))
876     (while (cdr copy)
877       (setcar copy (company-safe-substring
878                     (car copy) 0 (company-round-tab (string-width (car copy)))))
879       (pop copy))
880     (apply 'concat pieces)))
881
882 (defun company-fill-propertize (line width selected)
883   (setq line (company-safe-substring line 0 width))
884   (add-text-properties 0 width (list 'face 'company-tooltip) line)
885   (add-text-properties 0 (length company-common)
886                        (list 'face 'company-tooltip-common) line)
887   (when selected
888     (if (and company-search-string
889              (string-match (regexp-quote company-search-string) line
890                            (length company-prefix)))
891         (progn
892           (add-text-properties (match-beginning 0) (match-end 0)
893                                '(face company-tooltip-selection) line)
894           (when (< (match-beginning 0) (length company-common))
895             (add-text-properties (match-beginning 0) (length company-common)
896                                  '(face company-tooltip-common-selection)
897                                  line)))
898       (add-text-properties 0 width '(face company-tooltip-selection) line)
899       (add-text-properties 0 (length company-common)
900                            (list 'face 'company-tooltip-common-selection)
901                            line)))
902   line)
903
904 ;;; replace
905
906 (defun company-buffer-lines (beg end)
907   (goto-char beg)
908   (let ((row (cdr (posn-col-row (posn-at-point))))
909         lines)
910     (while (and (equal (move-to-window-line (incf row)) row)
911                 (<= (point) end))
912       (push (buffer-substring beg (min end (1- (point)))) lines)
913       (setq beg (point)))
914     (unless (eq beg end)
915       (push (buffer-substring beg end) lines))
916     (nreverse lines)))
917
918 (defsubst company-modify-line (old new offset)
919   (concat (company-safe-substring old 0 offset)
920           new
921           (company-safe-substring old (+ offset (length new)))))
922
923 (defun company-replacement-string (old lines column nl)
924   (let (new)
925     ;; Inject into old lines.
926     (while old
927       (push (company-modify-line (pop old) (pop lines) column) new))
928     ;; Append whole new lines.
929     (while lines
930       (push (concat (company-space-string column) (pop lines)) new))
931     (concat (when nl "\n")
932             (mapconcat 'identity (nreverse new) "\n")
933             "\n")))
934
935 (defun company-create-lines (column selection limit)
936
937   (let ((len company-candidates-length)
938         lines
939         width
940         lines-copy
941         previous
942         remainder
943         new)
944
945     ;; Scroll to offset.
946     (setq limit (company-pseudo-tooltip-update-offset selection len limit))
947
948     (when (> company-tooltip-offset 0)
949       (setq previous (format "...(%d)" company-tooltip-offset)))
950
951     (setq remainder (- len limit company-tooltip-offset)
952           remainder (when (> remainder 0)
953                       (setq remainder (format "...(%d)" remainder))))
954
955     (decf selection company-tooltip-offset)
956     (setq width (min (length previous) (length remainder))
957           lines (nthcdr company-tooltip-offset company-candidates)
958           len (min limit len)
959           lines-copy lines)
960
961     (dotimes (i len)
962       (setq width (max (length (pop lines-copy)) width)))
963     (setq width (min width (- (window-width) column)))
964
965     (when previous
966       (push (propertize (company-safe-substring previous 0 width)
967                         'face 'company-tooltip)
968             new))
969
970     (dotimes (i len)
971       (push (company-fill-propertize (company-reformat (pop lines))
972                                      width (equal i selection))
973             new))
974
975     (when remainder
976       (push (propertize (company-safe-substring remainder 0 width)
977                         'face 'company-tooltip)
978             new))
979
980     (setq lines (nreverse new))))
981
982 ;; show
983
984 (defsubst company-pseudo-tooltip-height ()
985   "Calculate the appropriate tooltip height."
986   (max 3 (min company-tooltip-limit
987               (- (window-height) 2
988                  (count-lines (window-start) (point-at-bol))))))
989
990 (defun company-pseudo-tooltip-show (row column selection)
991   (company-pseudo-tooltip-hide)
992   (save-excursion
993
994     (move-to-column 0)
995
996     (let* ((height (company-pseudo-tooltip-height))
997            (lines (company-create-lines column selection height))
998            (nl (< (move-to-window-line row) row))
999            (beg (point))
1000            (end (save-excursion
1001                   (move-to-window-line (+ row height))
1002                   (point)))
1003            (old-string
1004             (mapcar 'company-untabify (company-buffer-lines beg end)))
1005            str)
1006
1007       (setq company-pseudo-tooltip-overlay (make-overlay beg end))
1008
1009       (overlay-put company-pseudo-tooltip-overlay 'company-old old-string)
1010       (overlay-put company-pseudo-tooltip-overlay 'company-column column)
1011       (overlay-put company-pseudo-tooltip-overlay 'company-nl nl)
1012       (overlay-put company-pseudo-tooltip-overlay 'company-before
1013                    (company-replacement-string old-string lines column nl))
1014       (overlay-put company-pseudo-tooltip-overlay 'company-height height)
1015
1016       (overlay-put company-pseudo-tooltip-overlay 'window (selected-window)))))
1017
1018 (defun company-pseudo-tooltip-show-at-point (pos)
1019   (let ((col-row (posn-col-row (posn-at-point pos))))
1020     (company-pseudo-tooltip-show (1+ (cdr col-row)) (car col-row) company-selection)))
1021
1022 (defun company-pseudo-tooltip-edit (lines selection)
1023   (let* ((old-string (overlay-get company-pseudo-tooltip-overlay 'company-old))
1024          (column (overlay-get company-pseudo-tooltip-overlay 'company-column))
1025          (nl (overlay-get company-pseudo-tooltip-overlay 'company-nl))
1026          (height (overlay-get company-pseudo-tooltip-overlay 'company-height))
1027          (lines (company-create-lines column selection height)))
1028     (overlay-put company-pseudo-tooltip-overlay 'company-before
1029                  (company-replacement-string old-string lines column nl))))
1030
1031 (defun company-pseudo-tooltip-hide ()
1032   (when company-pseudo-tooltip-overlay
1033     (delete-overlay company-pseudo-tooltip-overlay)
1034     (setq company-pseudo-tooltip-overlay nil)))
1035
1036 (defun company-pseudo-tooltip-hide-temporarily ()
1037   (when (overlayp company-pseudo-tooltip-overlay)
1038     (overlay-put company-pseudo-tooltip-overlay 'invisible nil)
1039     (overlay-put company-pseudo-tooltip-overlay 'before-string nil)))
1040
1041 (defun company-pseudo-tooltip-unhide ()
1042   (when company-pseudo-tooltip-overlay
1043     (overlay-put company-pseudo-tooltip-overlay 'invisible t)
1044     (overlay-put company-pseudo-tooltip-overlay 'before-string
1045                  (overlay-get company-pseudo-tooltip-overlay 'company-before))
1046     (overlay-put company-pseudo-tooltip-overlay 'window (selected-window))))
1047
1048 (defun company-pseudo-tooltip-frontend (command)
1049   "A `company-mode' front-end similar to a tool-tip but based on overlays."
1050   (case command
1051     ('pre-command (company-pseudo-tooltip-hide-temporarily))
1052     ('post-command
1053      (unless (and (overlayp company-pseudo-tooltip-overlay)
1054                   (equal (overlay-get company-pseudo-tooltip-overlay
1055                                       'company-height)
1056                          (company-pseudo-tooltip-height)))
1057        ;; Redraw needed.
1058        (company-pseudo-tooltip-show-at-point (- (point)
1059                                                 (length company-prefix))))
1060      (company-pseudo-tooltip-unhide))
1061     ('hide (company-pseudo-tooltip-hide)
1062            (setq company-tooltip-offset 0))
1063     ('update (when (overlayp company-pseudo-tooltip-overlay)
1064                (company-pseudo-tooltip-edit company-candidates
1065                                             company-selection)))))
1066
1067 (defun company-pseudo-tooltip-unless-just-one-frontend (command)
1068   "`company-pseudo-tooltip-frontend', but not shown for single candidates."
1069   (unless (and (eq command 'post-command)
1070                (not (cdr company-candidates)))
1071     (company-pseudo-tooltip-frontend command)))
1072
1073 ;;; overlay ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1074
1075 (defvar company-preview-overlay nil)
1076 (make-variable-buffer-local 'company-preview-overlay)
1077
1078 (defun company-preview-show-at-point (pos)
1079   (company-preview-hide)
1080
1081   (setq company-preview-overlay (make-overlay pos pos))
1082
1083   (let ((completion (company-strip-prefix (nth company-selection
1084                                                company-candidates))))
1085     (and (equal pos (point))
1086          (not (equal completion ""))
1087          (add-text-properties 0 1 '(cursor t) completion))
1088
1089     (setq completion (propertize completion 'face 'company-preview))
1090     (add-text-properties 0 (- (length company-common) (length company-prefix))
1091                          '(face company-preview-common) completion)
1092
1093     (overlay-put company-preview-overlay 'after-string completion)
1094     (overlay-put company-preview-overlay 'window (selected-window))))
1095
1096 (defun company-preview-hide ()
1097   (when company-preview-overlay
1098     (delete-overlay company-preview-overlay)
1099     (setq company-preview-overlay nil)))
1100
1101 (defun company-preview-frontend (command)
1102   "A `company-mode' front-end showing the selection as if it had been inserted."
1103   (case command
1104     ('pre-command (company-preview-hide))
1105     ('post-command (company-preview-show-at-point (point)))
1106     ('hide (company-preview-hide))))
1107
1108 (defun company-preview-if-just-one-frontend (command)
1109   "`company-preview-frontend', but only shown for single candidates."
1110   (unless (and (eq command 'post-command)
1111                (cdr company-candidates))
1112     (company-preview-frontend command)))
1113
1114 ;;; echo ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1115
1116 (defvar company-echo-last-msg nil)
1117 (make-variable-buffer-local 'company-echo-last-msg)
1118
1119 (defvar company-echo-timer nil)
1120
1121 (defvar company-echo-delay .1)
1122
1123 (defun company-echo-show (&optional getter)
1124   (when getter
1125     (setq company-echo-last-msg (funcall getter)))
1126   (let ((message-log-max nil))
1127     (if company-echo-last-msg
1128         (message "%s" company-echo-last-msg)
1129       (message ""))))
1130
1131 (defsubst company-echo-show-soon (&optional getter)
1132   (when company-echo-timer
1133     (cancel-timer company-echo-timer))
1134   (setq company-echo-timer (run-with-timer company-echo-delay nil
1135                                            'company-echo-show getter)))
1136
1137 (defun company-echo-format ()
1138
1139   (let ((limit (window-width (minibuffer-window)))
1140         (len -1)
1141         ;; Roll to selection.
1142         (candidates (nthcdr company-selection company-candidates))
1143         comp msg)
1144
1145     (while candidates
1146       (setq comp (company-reformat (pop candidates))
1147             len (+ len 1 (length comp)))
1148       (if (>= len limit)
1149           (setq candidates nil)
1150         (setq comp (propertize comp 'face 'company-echo))
1151         (add-text-properties 0 (length company-common)
1152                              '(face company-echo-common) comp)
1153         (push comp msg)))
1154
1155     (mapconcat 'identity (nreverse msg) " ")))
1156
1157 (defun company-echo-hide ()
1158   (when company-echo-timer
1159     (cancel-timer company-echo-timer))
1160   (unless (equal company-echo-last-msg "")
1161     (setq company-echo-last-msg "")
1162     (company-echo-show)))
1163
1164 (defun company-echo-frontend (command)
1165   "A `company-mode' front-end showing the candidates in the echo area."
1166   (case command
1167     ('pre-command (company-echo-show-soon))
1168     ('post-command (company-echo-show-soon 'company-echo-format))
1169     ('hide (company-echo-hide))))
1170
1171 (defun company-echo-metadata-frontend (command)
1172   "A `company-mode' front-end showing the documentation in the echo area."
1173   (case command
1174     ('pre-command (company-echo-show-soon))
1175     ('post-command (company-echo-show-soon 'company-fetch-metadata))
1176     ('hide (company-echo-hide))))
1177
1178 (provide 'company)
1179 ;;; company.el ends here