]> rtime.felk.cvut.cz Git - sojka/company-mode.git/blob - company.el
Added incremental completion.
[sojka/company-mode.git] / company.el
1 (eval-when-compile (require 'cl))
2
3 (add-to-list 'debug-ignored-errors
4              "^Pseudo tooltip frontend cannot be used twice$")
5 (add-to-list 'debug-ignored-errors "^Preview frontend cannot be used twice$")
6
7 (defgroup company nil
8   ""
9   :group 'abbrev
10   :group 'convenience
11   :group 'maching)
12
13 (defface company-tooltip
14   '((t :background "yellow"
15        :foreground "black"))
16   "*"
17   :group 'company)
18
19 (defface company-tooltip-selection
20   '((t :background "orange1"
21        :foreground "black"))
22   "*"
23   :group 'company)
24
25 (defface company-tooltip-common
26   '((t :inherit company-tooltip
27        :foreground "red"))
28   "*"
29   :group 'company)
30
31 (defface company-tooltip-common-selection
32   '((t :inherit company-tooltip-selection
33        :foreground "red"))
34   "*"
35   :group 'company)
36
37 (defcustom company-tooltip-limit 10
38   "*"
39   :group 'company
40   :type 'integer)
41
42 (defface company-preview
43   '((t :background "blue4"
44        :foreground "wheat"))
45   "*"
46   :group 'company)
47
48 (defface company-preview-common
49   '((t :inherit company-preview
50        :foreground "red"))
51   "*"
52   :group 'company)
53
54 (defface company-echo nil
55   "*"
56   :group 'company)
57
58 (defface company-echo-common
59   '((((background dark)) (:foreground "firebrick1"))
60     (((background light)) (:background "firebrick4")))
61   "*"
62   :group 'company)
63
64 (defun company-frontends-set (variable value)
65   ;; uniquify
66   (let ((remainder value))
67     (setcdr remainder (delq (car remainder) (cdr remainder))))
68   (and (memq 'company-pseudo-tooltip-unless-just-one-frontend value)
69        (memq 'company-pseudo-tooltip-frontend value)
70        (error "Pseudo tooltip frontend cannot be used twice"))
71   (and (memq 'company-preview-if-just-one-frontend value)
72        (memq 'company-preview-frontend value)
73        (error "Preview frontend cannot be used twice"))
74   ;; preview must come last
75   (dolist (f '(company-preview-if-just-one-frontend company-preview-frontend))
76     (when (memq f value)
77       (setq value (append (delq f value) (list f)))))
78   (set variable value))
79
80 (defcustom company-frontends '(company-echo-frontend
81                                company-pseudo-tooltip-unless-just-one-frontend
82                                company-preview-if-just-one-frontend)
83   "*"
84   :set 'company-frontends-set
85   :group 'company
86   :type '(repeat (choice (const :tag "echo" company-echo-frontend)
87                          (const :tag "pseudo tooltip"
88                                 company-pseudo-tooltip-frontend)
89                          (const :tag "pseudo tooltip, multiple only"
90                                 company-pseudo-tooltip-unless-just-one-frontend)
91                          (const :tag "preview" company-preview-frontend)
92                          (const :tag "preview, unique only"
93                                 company-preview-if-just-one-frontend)
94                          (function :tag "custom function" nil))))
95
96 (defcustom company-backends '(company-elisp company-nxml company-css
97                               company-ispell)
98   "*"
99   :group 'company
100   :type '(repeat (function :tag "function" nil)))
101
102 (defcustom company-minimum-prefix-length 3
103   "*"
104   :group 'company
105   :type '(integer :tag "prefix length"))
106
107 (defvar company-timer nil)
108
109 (defun company-timer-set (variable value)
110   (set variable value)
111   (when company-timer (cancel-timer company-timer))
112   (when (numberp value)
113     (setq company-timer (run-with-idle-timer value t 'company-idle-begin))))
114
115 (defcustom company-idle-delay .7
116   "*"
117   :set 'company-timer-set
118   :group 'company
119   :type '(choice (const :tag "never (nil)" nil)
120                  (const :tag "immediate (t)" t)
121                  (number :tag "seconds")))
122
123 ;;; mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
124
125 (defvar company-mode-map
126   (let ((keymap (make-sparse-keymap)))
127     (define-key keymap (kbd "M-n") 'company-select-next)
128     (define-key keymap (kbd "M-p") 'company-select-previous)
129     (define-key keymap (kbd "M-<return>") 'company-complete-selection)
130     (define-key keymap "\t" 'company-complete)
131     keymap))
132
133 ;;;###autoload
134 (define-minor-mode company-mode
135   ""
136   nil " comp" company-mode-map
137   (if company-mode
138       (progn
139         (add-hook 'pre-command-hook 'company-pre-command nil t)
140         (add-hook 'post-command-hook 'company-post-command nil t)
141         (company-timer-set 'company-idle-delay
142                            company-idle-delay))
143     (remove-hook 'pre-command-hook 'company-pre-command t)
144     (remove-hook 'post-command-hook 'company-post-command t)
145     (company-cancel)
146     (kill-local-variable 'company-point)))
147
148 ;;; backends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
149
150 (defun company-grab (regexp &optional expression)
151   (when (looking-back regexp)
152     (or (match-string-no-properties (or expression 0)) "")))
153
154 (defun company-in-string-or-comment (&optional point)
155   (let ((pos (syntax-ppss)))
156     (or (nth 3 pos) (nth 4 pos) (nth 7 pos))))
157
158 ;;; completion mechanism ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
159
160 (defvar company-backend nil)
161 (make-variable-buffer-local 'company-backend)
162
163 (defvar company-prefix nil)
164 (make-variable-buffer-local 'company-prefix)
165
166 (defvar company-candidates nil)
167 (make-variable-buffer-local 'company-candidates)
168
169 (defvar company-common nil)
170 (make-variable-buffer-local 'company-common)
171
172 (defvar company-selection 0)
173 (make-variable-buffer-local 'company-selection)
174
175 (defvar company-selection-changed nil)
176 (make-variable-buffer-local 'company-selection-changed)
177
178 (defvar company-point nil)
179 (make-variable-buffer-local 'company-point)
180
181 (defvar company-disabled-backends nil)
182
183 (defsubst company-strip-prefix (str)
184   (substring str (length company-prefix)))
185
186 (defsubst company-reformat (candidate)
187   ;; company-ispell needs this, because the results are always lower-case
188   ;; It's mory efficient to fix it only when they are displayed.
189   (concat company-prefix (substring candidate (length company-prefix))))
190
191 (defsubst company-should-complete (prefix)
192   (and (eq company-idle-delay t)
193        (>= (length prefix) company-minimum-prefix-length)))
194
195 (defsubst company-call-frontends (command)
196   (dolist (frontend company-frontends)
197     (funcall frontend command)))
198
199 (defun company-idle-begin ()
200   (and company-mode
201        (not company-candidates)
202        (not (equal (point) company-point))
203        (let ((company-idle-delay t))
204          (company-begin)
205          (company-post-command))))
206
207 (defun company-manual-begin ()
208   (and company-mode
209        (not company-candidates)
210        (let ((company-idle-delay t)
211              (company-minimum-prefix-length 0))
212          (company-begin)))
213   ;; Return non-nil if active.
214   company-candidates)
215
216 (defun company-continue-add (new-prefix)
217   (let ((completion-ignore-case (funcall company-backend 'ignore-case)))
218     (and (< (length company-prefix) (length new-prefix))
219          (equal (substring new-prefix 0 (length company-prefix)) company-prefix)
220          (setq company-candidates
221                (all-completions new-prefix company-candidates))
222          (setq company-prefix new-prefix)
223          (setq company-selection 0))))
224
225 (defun company-continue-remove (new-prefix)
226   (and (> (length company-prefix) (length new-prefix))
227        (equal (substring company-prefix 0 (length new-prefix)) new-prefix)
228        (setq company-candidates
229              (funcall company-backend 'candidates new-prefix))
230        (setq company-prefix new-prefix)
231        (setq company-selection 0)))
232
233 (defun company-continue ()
234   (when company-candidates
235     (let ((new-prefix (funcall company-backend 'prefix)))
236       (if (and (= (- (point) (length new-prefix))
237                   (- company-point (length company-prefix)))
238                (or (equal company-prefix new-prefix)
239                    (company-continue-add new-prefix)
240                    (company-continue-remove new-prefix)))
241           (company-call-frontends 'update)
242         (setq company-candidates nil)))))
243
244 (defun company-begin ()
245   (company-continue)
246   (unless company-candidates
247     (let (prefix)
248       (dolist (backend company-backends)
249         (unless (fboundp backend)
250           (ignore-errors (require backend nil t)))
251         (if (fboundp backend)
252             (when (setq prefix (funcall backend 'prefix))
253               (when (company-should-complete prefix)
254                 (setq company-backend backend
255                       company-prefix prefix
256                       company-candidates
257                       (funcall company-backend 'candidates prefix)
258                       company-selection 0)
259                 (unless (funcall company-backend 'sorted)
260                   (setq company-candidates
261                         (sort company-candidates 'string<)))
262                 (company-call-frontends 'update))
263               (return prefix))
264           (unless (memq backend company-disabled-backends)
265             (push backend company-disabled-backends)
266             (message "Company back-end '%s' could not be initialized"
267                      backend))))))
268   (if (or (not company-candidates)
269           (eq t (let ((completion-ignore-case (funcall company-backend
270                                                        'ignore-case)))
271                   (setq company-common
272                         (try-completion company-prefix company-candidates)))))
273       (company-cancel)
274     (setq company-point (point))))
275
276 (defun company-cancel ()
277   (setq company-backend nil
278         company-prefix nil
279         company-candidates nil
280         company-common nil
281         company-selection 0
282         company-selection-changed nil
283         company-point nil)
284   (company-call-frontends 'hide))
285
286 (defun company-abort ()
287   (company-cancel)
288   ;; Don't start again, unless started manually.
289   (setq company-point (point)))
290
291 (defun company-pre-command ()
292   (when company-candidates
293     (company-call-frontends 'pre-command)))
294
295 (defun company-post-command ()
296   (unless (equal (point) company-point)
297     (company-begin))
298   (when company-candidates
299     (company-call-frontends 'post-command)))
300
301 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
302
303 (defun company-select-next ()
304   (interactive)
305   (when (company-manual-begin)
306     (setq company-selection (min (1- (length company-candidates))
307                                  (1+ company-selection))
308           company-selection-changed t)))
309
310 (defun company-select-previous ()
311   (interactive)
312   (when (company-manual-begin)
313     (setq company-selection (max 0 (1- company-selection))
314           company-selection-changed t)))
315
316 (defun company-complete-selection ()
317   (interactive)
318   (when (company-manual-begin)
319     (insert (company-strip-prefix (nth company-selection company-candidates)))
320     (company-abort)))
321
322 (defun company-complete-common ()
323   (interactive)
324   (when (company-manual-begin)
325     (insert (company-strip-prefix company-common))))
326
327 (defun company-complete ()
328   (interactive)
329   (when (company-manual-begin)
330     (if (or company-selection-changed
331             (eq last-command 'company-complete-common))
332         (call-interactively 'company-complete-selection)
333       (call-interactively 'company-complete-common)
334       (setq this-command 'company-complete-common))))
335
336 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
337
338 (defconst company-space-strings-limit 100)
339
340 (defconst company-space-strings
341   (let (lst)
342     (dotimes (i company-space-strings-limit)
343       (push (make-string (- company-space-strings-limit 1 i) ?\  ) lst))
344     (apply 'vector lst)))
345
346 (defsubst company-space-string (len)
347   (if (< len company-space-strings-limit)
348       (aref company-space-strings len)
349     (make-string len ?\ )))
350
351 (defsubst company-safe-substring (str from &optional to)
352   (let ((len (length str)))
353     (if (> from len)
354         ""
355       (if (and to (> to len))
356           (concat (substring str from)
357                   (company-space-string (- to len)))
358         (substring str from to)))))
359
360 ;;; pseudo-tooltip ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
361
362 (defvar company-pseudo-tooltip-overlay nil)
363 (make-variable-buffer-local 'company-pseudo-tooltip-overlay)
364
365 (defvar company-tooltip-offset 0)
366 (make-variable-buffer-local 'company-tooltip-offset)
367
368 (defun company-pseudo-tooltip-update-offset (selection num-lines limit)
369
370   (decf limit 2)
371   (setq company-tooltip-offset
372         (max (min selection company-tooltip-offset)
373              (- selection -1 limit)))
374
375   (when (<= company-tooltip-offset 1)
376     (incf limit)
377     (setq company-tooltip-offset 0))
378
379   (when (>= company-tooltip-offset (- num-lines limit 1))
380     (incf limit)
381     (when (= selection (1- num-lines))
382       (setq company-tooltip-offset (max (1- company-tooltip-offset) 0))))
383
384   limit)
385
386 ;;; propertize
387
388 (defun company-fill-propertize (line width selected)
389   (setq line (company-safe-substring line 0 width))
390   (add-text-properties 0 width
391                        (list 'face (if selected
392                                        'company-tooltip-selection
393                                      'company-tooltip)) line)
394   (add-text-properties 0 (length company-common)
395                        (list 'face (if selected
396                                        'company-tooltip-common-selection
397                                      'company-tooltip-common)) line)
398   line)
399
400 ;;; replace
401
402 (defun company-buffer-lines (beg end)
403   (goto-char beg)
404   (let ((row (cdr (posn-col-row (posn-at-point))))
405         lines)
406     (while (< (point) end)
407       (move-to-window-line (incf row))
408       (push (buffer-substring beg (min end (1- (point)))) lines)
409       (setq beg (point)))
410     (nreverse lines)))
411
412 (defun company-modify-line (old new offset)
413   (concat (company-safe-substring old 0 offset)
414           new
415           (company-safe-substring old (+ offset (length new)))))
416
417 (defun company-modified-substring (beg end lines column nl)
418   (let ((old (company-buffer-lines beg end))
419         new)
420     ;; Inject into old lines.
421     (while old
422       (push (company-modify-line (pop old) (pop lines) column) new))
423     ;; Append whole new lines.
424     (while lines
425       (push (company-modify-line "" (pop lines) column) new))
426     (concat (when nl "\n")
427             (mapconcat 'identity (nreverse new) "\n")
428             "\n")))
429
430 ;; show
431
432 (defun company-pseudo-tooltip-show (row column lines selection)
433   (company-pseudo-tooltip-hide)
434   (unless lines (error "No text provided"))
435   (save-excursion
436
437     (let ((limit (max company-tooltip-limit 3))
438           (len (length lines))
439           width
440           lines-copy
441           previous
442           remainder
443           new)
444
445       ;; Scroll to offset.
446       (setq limit (company-pseudo-tooltip-update-offset selection len limit))
447
448       (when (> company-tooltip-offset 0)
449         (setq previous (format "...(%d)" company-tooltip-offset)))
450
451       (setq remainder (- len limit company-tooltip-offset)
452             remainder (when (> remainder 0)
453                         (setq remainder (format "...(%d)" remainder))))
454
455       (decf selection company-tooltip-offset)
456       (setq width (min (length previous) (length remainder))
457             lines (nthcdr company-tooltip-offset lines)
458             len (min limit (length lines))
459             lines-copy lines)
460
461       (dotimes (i len)
462         (setq width (max (length (pop lines-copy)) width)))
463       (setq width (min width (- (window-width) column)))
464
465       (when previous
466         (push (propertize (company-safe-substring previous 0 width)
467                           'face 'company-tooltip)
468               new))
469
470       (dotimes (i len)
471         (push (company-fill-propertize (company-reformat (pop lines))
472                                        width (equal i selection))
473               new))
474
475       (when remainder
476         (push (propertize (company-safe-substring remainder 0 width)
477                           'face 'company-tooltip)
478               new))
479
480       (setq lines (nreverse new)))
481
482     (move-to-column 0)
483
484     (let ((nl (< (move-to-window-line row) row))
485           (beg (point))
486           (end (save-excursion
487                  (move-to-window-line (min (window-height)
488                                            (+ row company-tooltip-limit)))
489                  (point)))
490           str)
491
492       (setq company-pseudo-tooltip-overlay (make-overlay beg end))
493
494       (overlay-put company-pseudo-tooltip-overlay 'before-string
495                    (company-modified-substring beg end lines column nl))
496       (overlay-put company-pseudo-tooltip-overlay 'invisible t)
497       (overlay-put company-pseudo-tooltip-overlay 'window (selected-window)))))
498
499 (defun company-pseudo-tooltip-show-at-point (pos)
500   (let ((col-row (posn-col-row (posn-at-point pos))))
501     (company-pseudo-tooltip-show (1+ (cdr col-row)) (car col-row)
502                                  company-candidates company-selection)))
503
504 (defun company-pseudo-tooltip-hide ()
505   (when company-pseudo-tooltip-overlay
506     (delete-overlay company-pseudo-tooltip-overlay)
507     (setq company-pseudo-tooltip-overlay nil)))
508
509 (defun company-pseudo-tooltip-frontend (command)
510   (case command
511     ('pre-command (company-pseudo-tooltip-hide))
512     ('post-command (company-pseudo-tooltip-show-at-point
513                     (- (point) (length company-prefix))))
514     ('hide (company-pseudo-tooltip-hide)
515            (setq company-tooltip-offset 0))))
516
517 (defun company-pseudo-tooltip-unless-just-one-frontend (command)
518   (unless (and (eq command 'post-command)
519                (not (cdr company-candidates)))
520     (company-pseudo-tooltip-frontend command)))
521
522 ;;; overlay ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
523
524 (defvar company-preview-overlay nil)
525 (make-variable-buffer-local 'company-preview-overlay)
526
527 (defun company-preview-show-at-point (pos)
528   (company-preview-hide)
529
530   (setq company-preview-overlay (make-overlay pos pos))
531
532   (let ((completion (company-strip-prefix (nth company-selection
533                                                company-candidates))))
534     (and (equal pos (point))
535          (not (equal completion ""))
536          (add-text-properties 0 1 '(cursor t) completion))
537
538     (setq completion (propertize completion 'face 'company-preview))
539     (add-text-properties 0 (- (length company-common) (length company-prefix))
540                          '(face company-preview-common) completion)
541
542     (overlay-put company-preview-overlay 'after-string completion)
543     (overlay-put company-preview-overlay 'window (selected-window))))
544
545 (defun company-preview-hide ()
546   (when company-preview-overlay
547     (delete-overlay company-preview-overlay)
548     (setq company-preview-overlay nil)))
549
550 (defun company-preview-frontend (command)
551   (case command
552     ('pre-command (company-preview-hide))
553     ('post-command (company-preview-show-at-point (point)))
554     ('hide (company-preview-hide))))
555
556 (defun company-preview-if-just-one-frontend (command)
557   (unless (and (eq command 'post-command)
558                (cdr company-candidates))
559     (company-preview-frontend command)))
560
561 ;;; echo ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
562
563 (defvar company-echo-last-msg nil)
564 (make-variable-buffer-local 'company-echo-last-msg)
565
566 (defun company-echo-refresh ()
567   (let ((message-log-max nil))
568     (if company-echo-last-msg
569         (message "%s" company-echo-last-msg)
570       (message ""))))
571
572 (defun company-echo-show (candidates)
573
574   ;; Roll to selection.
575   (setq candidates (nthcdr company-selection candidates))
576
577   (let ((limit (window-width (minibuffer-window)))
578         (len -1)
579         comp msg)
580     (while candidates
581       (setq comp (company-reformat (pop candidates))
582             len (+ len 1 (length comp)))
583       (if (>= len limit)
584           (setq candidates nil)
585         (setq comp (propertize comp 'face 'company-echo))
586         (add-text-properties 0 (length company-common)
587                              '(face company-echo-common) comp)
588         (push comp msg)))
589
590     (setq company-echo-last-msg (mapconcat 'identity (nreverse msg) " "))
591     (company-echo-refresh)))
592
593 (defun company-echo-frontend (command)
594   (case command
595     ('pre-command (company-echo-refresh))
596     ('post-command (company-echo-show company-candidates))
597     ('hide (setq company-echo-last-msg nil))))
598
599 (provide 'company)
600 ;;; company.el ends here