]> crepu.dev Git - config.git/blame - djavu-asus/emacs/elpa/company-20230926.32/company.el
Reorganización de directorios
[config.git] / djavu-asus / emacs / elpa / company-20230926.32 / company.el
CommitLineData
53e6db90
DC
1;;; company.el --- Modular text completion framework -*- lexical-binding: t -*-
2
3;; Copyright (C) 2009-2023 Free Software Foundation, Inc.
4
5;; Author: Nikolaj Schumacher
6;; Maintainer: Dmitry Gutov <dgutov@yandex.ru>
7;; URL: http://company-mode.github.io/
8;; Version: 0.9.13
9;; Keywords: abbrev, convenience, matching
10;; Package-Requires: ((emacs "25.1"))
11
12;; This file is part of GNU Emacs.
13
14;; GNU Emacs is free software: you can redistribute it and/or modify
15;; it under the terms of the GNU General Public License as published by
16;; the Free Software Foundation, either version 3 of the License, or
17;; (at your option) any later version.
18
19;; GNU Emacs is distributed in the hope that it will be useful,
20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22;; GNU General Public License for more details.
23
24;; You should have received a copy of the GNU General Public License
25;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
26
27;;; Commentary:
28;;
29;; Company is a modular completion framework. Modules for retrieving completion
30;; candidates are called backends, modules for displaying them are frontends.
31;;
32;; Company comes with many backends, e.g. `company-etags'. These are
33;; distributed in separate files and can be used individually.
34;;
35;; Enable `company-mode' in all buffers with M-x global-company-mode. For
36;; further information look at the documentation for `company-mode' (C-h f
37;; company-mode RET).
38;;
39;; If you want to start a specific backend, call it interactively or use
40;; `company-begin-backend'. For example:
41;; M-x company-abbrev will prompt for and insert an abbrev.
42;;
43;; To write your own backend, look at the documentation for `company-backends'.
44;; Here is a simple example completing "foo":
45;;
46;; (defun company-my-backend (command &optional arg &rest ignored)
47;; (interactive (list 'interactive))
48;; (pcase command
49;; (`interactive (company-begin-backend 'company-my-backend))
50;; (`prefix (company-grab-symbol))
51;; (`candidates (list "foobar" "foobaz" "foobarbaz"))
52;; (`meta (format "This value is named %s" arg))))
53;;
54;; Sometimes it is a good idea to mix several backends together, for example to
55;; enrich gtags with dabbrev-code results (to emulate local variables). To do
56;; this, add a list with both backends as an element in `company-backends'.
57;;
58;;; Change Log:
59;;
60;; See NEWS.md in the repository.
61
62;;; Code:
63
64(require 'cl-lib)
65(require 'subr-x)
66(require 'pcase)
67
68(defgroup company nil
69 "Extensible inline text completion mechanism."
70 :group 'abbrev
71 :group 'convenience
72 :group 'matching
73 :link '(custom-manual "(company) Top"))
74
75(defgroup company-faces nil
76 "Faces used by Company."
77 :group 'company
78 :group 'faces)
79
80(defface company-tooltip
81 '((((class color) (min-colors 88) (background light))
82 (:foreground "black" :background "cornsilk"))
83 (((class color) (min-colors 88) (background dark))
84 (:background "gray26"))
85 (t (:foreground "black" :background "yellow")))
86 "Face used for the tooltip.")
87
88(defface company-tooltip-selection
89 '((((class color) (min-colors 88) (background light))
90 (:background "light blue"))
91 (((class color) (min-colors 88) (background dark))
92 (:background "gray31"))
93 (t (:background "green")))
94 "Face used for the selection in the tooltip.")
95
96(defface company-tooltip-deprecated
97 '((t (:strike-through t)))
98 "Face used for the deprecated items.")
99
100(defface company-tooltip-search
101 '((default :inherit highlight))
102 "Face used for the search string in the tooltip.")
103
104(defface company-tooltip-search-selection
105 '((default :inherit highlight))
106 "Face used for the search string inside the selection in the tooltip.")
107
108(defface company-tooltip-mouse
109 '((default :inherit highlight))
110 "Face used for the tooltip item under the mouse.")
111
112(defface company-tooltip-common
113 '((((background light))
114 :foreground "darkred")
115 (((background dark))
116 :foreground "pale turquoise"))
117 "Face used for the common completion in the tooltip.")
118
119(defface company-tooltip-common-selection
120 '((default :inherit company-tooltip-common))
121 "Face used for the selected common completion in the tooltip.")
122
123(defface company-tooltip-annotation
124 '((((background light))
125 :foreground "firebrick4")
126 (((background dark))
127 :foreground "LightCyan3"))
128 "Face used for the completion annotation in the tooltip.")
129
130(defface company-tooltip-annotation-selection
131 '((default :inherit company-tooltip-annotation))
132 "Face used for the selected completion annotation in the tooltip.")
133
134(defface company-tooltip-quick-access
135 '((default :inherit company-tooltip-annotation))
136 "Face used for the quick-access hints shown in the tooltip."
137 :package-version '(company . "0.9.14"))
138
139(defface company-tooltip-quick-access-selection
140 '((default :inherit company-tooltip-annotation-selection))
141 "Face used for the selected quick-access hints shown in the tooltip."
142 :package-version '(company . "0.9.14"))
143
144(define-obsolete-face-alias
145 'company-scrollbar-fg
146 'company-tooltip-scrollbar-thumb
147 "0.9.14")
148
149(defface company-tooltip-scrollbar-thumb
150 '((((background light))
151 :background "darkred")
152 (((background dark))
153 :background "gray33"))
154 "Face used for the tooltip scrollbar thumb (bar).")
155
156(define-obsolete-face-alias
157 'company-scrollbar-bg
158 'company-tooltip-scrollbar-track
159 "0.9.14")
160
161(defface company-tooltip-scrollbar-track
162 '((((background light))
163 :background "wheat")
164 (((background dark))
165 :background "gray28"))
166 "Face used for the tooltip scrollbar track (trough).")
167
168(defface company-preview
169 '((default :inherit (company-tooltip-selection company-tooltip)))
170 "Face used for the completion preview.")
171
172(defface company-preview-common
173 '((default :inherit company-tooltip-common-selection))
174 "Face used for the common part of the completion preview.")
175
176(defface company-preview-search
177 '((default :inherit company-tooltip-common-selection))
178 "Face used for the search string in the completion preview.")
179
180(defface company-echo nil
181 "Face used for completions in the echo area.")
182
183(defface company-echo-common
184 '((((background light)) (:foreground "firebrick4"))
185 (((background dark)) (:foreground "firebrick1")))
186 "Face used for the common part of completions in the echo area.")
187
188;; Too lazy to re-add :group to all defcustoms down below.
189(setcdr (assoc load-file-name custom-current-group-alist)
190 'company)
191
192(defun company-frontends-set (variable value)
193 ;; Uniquify.
194 (let ((value (delete-dups (copy-sequence value))))
195 (and (or (and (memq 'company-pseudo-tooltip-unless-just-one-frontend value)
196 (memq 'company-pseudo-tooltip-frontend value))
197 (and (memq 'company-pseudo-tooltip-unless-just-one-frontend-with-delay value)
198 (memq 'company-pseudo-tooltip-frontend value))
199 (and (memq 'company-pseudo-tooltip-unless-just-one-frontend-with-delay value)
200 (memq 'company-pseudo-tooltip-unless-just-one-frontend value)))
201 (user-error "Pseudo tooltip frontend cannot be used more than once"))
202 (and (or (and (memq 'company-preview-if-just-one-frontend value)
203 (memq 'company-preview-frontend value))
204 (and (memq 'company-preview-if-just-one-frontend value)
205 (memq 'company-preview-common-frontend value))
206 (and (memq 'company-preview-frontend value)
207 (memq 'company-preview-common-frontend value))
208 )
209 (user-error "Preview frontend cannot be used twice"))
210 (and (memq 'company-echo value)
211 (memq 'company-echo-metadata-frontend value)
212 (user-error "Echo area cannot be used twice"))
213 ;; Preview must come last.
214 (dolist (f '(company-preview-if-just-one-frontend company-preview-frontend company-preview-common-frontend))
215 (when (cdr (memq f value))
216 (setq value (append (delq f value) (list f)))))
217 (set variable value)))
218
219(defcustom company-frontends '(company-pseudo-tooltip-unless-just-one-frontend
220 company-preview-if-just-one-frontend
221 company-echo-metadata-frontend)
222 "The list of active frontends (visualizations).
223Each frontend is a function that takes one argument. It is called with
224one of the following arguments:
225
226`show': When the visualization should start.
227
228`hide': When the visualization should end.
229
230`update': When the data has been updated.
231
232`pre-command': Before every command that is executed while the
233visualization is active.
234
235`post-command': After every command that is executed while the
236visualization is active.
237
238`unhide': When an asynchronous backend is waiting for its completions.
239Only needed in frontends which hide their visualizations in `pre-command'
240for technical reasons.
241
242The visualized data is stored in `company-prefix', `company-candidates',
243`company-common', `company-selection', `company-point' and
244`company-search-string'."
245 :set 'company-frontends-set
246 :type '(repeat (choice (const :tag "echo" company-echo-frontend)
247 (const :tag "echo, strip common"
248 company-echo-strip-common-frontend)
249 (const :tag "show echo meta-data in echo"
250 company-echo-metadata-frontend)
251 (const :tag "pseudo tooltip"
252 company-pseudo-tooltip-frontend)
253 (const :tag "pseudo tooltip, multiple only"
254 company-pseudo-tooltip-unless-just-one-frontend)
255 (const :tag "pseudo tooltip, multiple only, delayed"
256 company-pseudo-tooltip-unless-just-one-frontend-with-delay)
257 (const :tag "preview" company-preview-frontend)
258 (const :tag "preview, unique only"
259 company-preview-if-just-one-frontend)
260 (const :tag "preview, common"
261 company-preview-common-frontend)
262 (function :tag "custom function" nil))))
263
264(defcustom company-tooltip-limit 10
265 "The maximum number of candidates in the tooltip."
266 :type 'integer)
267
268(defcustom company-tooltip-minimum 6
269 "Ensure visibility of this number of candidates.
270When that many lines are not available between point and the bottom of the
271window, display the tooltip above point."
272 :type 'integer)
273
274(defcustom company-tooltip-minimum-width 0
275 "The minimum width of the tooltip's inner area.
276This doesn't include the margins and the scroll bar."
277 :type 'integer
278 :package-version '(company . "0.8.0"))
279
280(defcustom company-tooltip-maximum-width most-positive-fixnum
281 "The maximum width of the tooltip's inner area.
282This doesn't include the margins and the scroll bar."
283 :type 'integer
284 :package-version '(company . "0.9.5"))
285
286(defcustom company-tooltip-width-grow-only nil
287 "When non-nil, the tooltip width is not allowed to decrease."
288 :type 'boolean
289 :package-version '(company . "0.9.14"))
290
291(defcustom company-tooltip-margin 1
292 "Width of margin columns to show around the toolip."
293 :type 'integer)
294
295(defcustom company-tooltip-offset-display 'scrollbar
296 "Method using which the tooltip displays scrolling position.
297`scrollbar' means draw a scrollbar to the right of the items.
298`lines' means wrap items in lines with \"before\" and \"after\" counters."
299 :type '(choice (const :tag "Scrollbar" scrollbar)
300 (const :tag "Two lines" lines)))
301
302(defcustom company-tooltip-align-annotations nil
303 "When non-nil, align annotations to the right tooltip border."
304 :type 'boolean
305 :package-version '(company . "0.7.1"))
306
307(defcustom company-tooltip-flip-when-above nil
308 "Whether to flip the tooltip when it's above the current line."
309 :type 'boolean
310 :package-version '(company . "0.8.1"))
311
312(defcustom company-tooltip-annotation-padding nil
313 "Non-nil to specify the padding before annotation.
314
315Depending on the value of `company-tooltip-align-annotations', the default
316padding is either 0 or 1 space. This variable allows to override that
317value to increase the padding. When annotations are right-aligned, it sets
318the minimum padding, and otherwise just the constant one."
319 :type 'number
320 :package-version '(company "0.9.14"))
321
322(defvar company-safe-backends
323 '((company-abbrev . "Abbrev")
324 (company-bbdb . "BBDB")
325 (company-capf . "completion-at-point-functions")
326 (company-clang . "Clang")
327 (company-cmake . "CMake")
328 (company-css . "CSS (obsolete backend)")
329 (company-dabbrev . "dabbrev for plain text")
330 (company-dabbrev-code . "dabbrev for code")
331 (company-elisp . "Emacs Lisp (obsolete backend)")
332 (company-etags . "etags")
333 (company-files . "Files")
334 (company-gtags . "GNU Global")
335 (company-ispell . "Ispell")
336 (company-keywords . "Programming language keywords")
337 (company-nxml . "nxml (obsolete backend)")
338 (company-oddmuse . "Oddmuse")
339 (company-semantic . "Semantic")
340 (company-tempo . "Tempo templates")))
341(put 'company-safe-backends 'risky-local-variable t)
342
343(defun company-safe-backends-p (backends)
344 (and (consp backends)
345 (not (cl-dolist (backend backends)
346 (unless (if (consp backend)
347 (company-safe-backends-p backend)
348 (assq backend company-safe-backends))
349 (cl-return t))))))
350
351(defcustom company-backends `(company-bbdb
352 ,@(unless (version<= "26" emacs-version)
353 (list 'company-nxml))
354 ,@(unless (version<= "26" emacs-version)
355 (list 'company-css))
356 company-semantic
357 company-cmake
358 company-capf
359 company-clang
360 company-files
361 (company-dabbrev-code company-gtags company-etags
362 company-keywords)
363 company-oddmuse company-dabbrev)
364 "The list of active backends (completion engines).
365
366Only one backend is used at a time. The choice depends on the order of
367the items in this list, and on the values they return in response to the
368`prefix' command (see below). But a backend can also be a \"grouped\"
369one (see below).
370
371`company-begin-backend' can be used to start a specific backend,
372`company-other-backend' will skip to the next matching backend in the list.
373
374Each backend is a function that takes a variable number of arguments.
375The first argument is the command requested from the backend. It is one
376of the following:
377
378`prefix': The backend should return the text to be completed. It must be
379text immediately before point. Returning nil from this command passes
380control to the next backend. The function should return `stop' if it
381should complete but cannot (e.g. when in the middle of a symbol).
382Instead of a string, the backend may return a cons (PREFIX . LENGTH)
383where LENGTH is a number used in place of PREFIX's length when
384comparing against `company-minimum-prefix-length'. LENGTH can also
385be just t, and in the latter case the test automatically succeeds.
386
387`candidates': The second argument is the prefix to be completed. The
388return value should be a list of candidates that match the prefix.
389
390Non-prefix matches are also supported (candidates that don't start with the
391prefix, but match it in some backend-defined way). Backends that use this
392feature must disable cache (return t to `no-cache') and might also want to
393respond to `match'.
394
395Optional commands
396=================
397
398`sorted': Return t here to indicate that the candidates are sorted and will
399not need to be sorted again.
400
401`duplicates': If non-nil, company will take care of removing duplicates
402from the list.
403
404`no-cache': Usually company doesn't ask for candidates again as completion
405progresses, unless the backend returns t for this command. The second
406argument is the latest prefix.
407
408`ignore-case': Return t here if the backend returns case-insensitive
409matches. This value is used to determine the longest common prefix (as
410used in `company-complete-common'), and to filter completions when fetching
411them from cache.
412
413`meta': The second argument is a completion candidate. Return a (short)
414documentation string for it.
415
416`doc-buffer': The second argument is a completion candidate. Return a
417buffer with documentation for it. Preferably use `company-doc-buffer'. If
418not all buffer contents pertain to this candidate, return a cons of buffer
419and window start position.
420
421`location': The second argument is a completion candidate. Return a cons
422of buffer and buffer location, or of file and line number where the
423completion candidate was defined.
424
425`annotation': The second argument is a completion candidate. Return a
426string to be displayed inline with the candidate in the popup. If
427duplicates are removed by company, candidates with equal string values will
428be kept if they have different annotations. For that to work properly,
429backends should store the related information on candidates using text
430properties.
431
432`deprecated': The second argument is a completion candidate. Return
433non-nil if the completion candidate is deprecated.
434
435`match': The second argument is a completion candidate. Return a positive
436integer, the index after the end of text matching `prefix' within the
437candidate string. Alternatively, return a list of (CHUNK-START
438. CHUNK-END) elements, where CHUNK-START and CHUNK-END are indexes within
439the candidate string. The corresponding regions are be used when rendering
440the popup. This command only makes sense for backends that provide
441non-prefix completion.
442
443`require-match': If this returns t, the user is not allowed to enter
444anything not offered as a candidate. Please don't use that value in normal
445backends. The default value nil gives the user that choice with
446`company-require-match'. Return value `never' overrides that option the
447other way around (using that value will indicate that the returned set of
448completions is often incomplete, so this behavior will not be useful).
449
450`init': Called once for each buffer. The backend can check for external
451programs and files and load any required libraries. Raising an error here
452will show up in message log once, and the backend will not be used for
453completion.
454
455`post-completion': Called after a completion candidate has been inserted
456into the buffer. The second argument is the candidate. Can be used to
457modify it, e.g. to expand a snippet.
458
459`kind': The second argument is a completion candidate. Return a symbol
460describing the kind of the candidate. Refer to `company-vscode-icons-mapping'
461for the possible values.
462
463The backend should return nil for all commands it does not support or
464does not know about. It should also be callable interactively and use
465`company-begin-backend' to start itself in that case.
466
467Grouped backends
468================
469
470An element of `company-backends' can also be a list of backends. The
471completions from backends in such groups are merged, but only from those
472backends which return the same `prefix'.
473
474If a backend command takes a candidate as an argument (e.g. `meta'), the
475call is dispatched to the backend the candidate came from. In other
476cases (except for `duplicates' and `sorted'), the first non-nil value among
477all the backends is returned.
478
479The group can also contain keywords. Currently, `:with' and `:separate'
480keywords are defined. If the group contains keyword `:with', the backends
481listed after this keyword are ignored for the purpose of the `prefix'
482command. If the group contains keyword `:separate', the candidates that
483come from different backends are sorted separately in the combined list.
484
485Asynchronous backends
486=====================
487
488The return value of each command can also be a cons (:async . FETCHER)
489where FETCHER is a function of one argument, CALLBACK. When the data
490arrives, FETCHER must call CALLBACK and pass it the appropriate return
491value, as described above. That call must happen in the same buffer as
492where completion was initiated.
493
494True asynchronous operation is only supported for command `candidates', and
495only during idle completion. Other commands will block the user interface,
496even if the backend uses the asynchronous calling convention."
497 :type `(repeat
498 (choice
499 :tag "backend"
500 ,@(mapcar (lambda (b) `(const :tag ,(cdr b) ,(car b)))
501 company-safe-backends)
502 (symbol :tag "User defined")
503 (repeat :tag "Merged backends"
504 (choice :tag "backend"
505 ,@(mapcar (lambda (b)
506 `(const :tag ,(cdr b) ,(car b)))
507 company-safe-backends)
508 (const :tag "With" :with)
509 (symbol :tag "User defined"))))))
510
511(put 'company-backends 'safe-local-variable 'company-safe-backends-p)
512
513(defcustom company-transformers nil
514 "Functions to change the list of candidates received from backends.
515
516Each function gets called with the return value of the previous one.
517The first one gets passed the list of candidates, already sorted and
518without duplicates."
519 :type '(choice
520 (const :tag "None" nil)
521 (const :tag "Sort by occurrence" (company-sort-by-occurrence))
522 (const :tag "Sort by backend importance"
523 (company-sort-by-backend-importance))
524 (const :tag "Prefer case sensitive prefix"
525 (company-sort-prefer-same-case-prefix))
526 (repeat :tag "User defined" function)))
527
528(defcustom company-completion-started-hook nil
529 "Hook run when company starts completing.
530The hook is called with one argument that is non-nil if the completion was
531started manually."
532 :type 'hook)
533
534(defcustom company-completion-cancelled-hook nil
535 "Hook run when company cancels completing.
536The hook is called with one argument that is non-nil if the completion was
537aborted manually."
538 :type 'hook)
539
540(defcustom company-completion-finished-hook nil
541 "Hook run when company successfully completes.
542The hook is called with the selected candidate as an argument.
543
544If you indend to use it to post-process candidates from a specific
545backend, consider using the `post-completion' command instead."
546 :type 'hook)
547
548(defcustom company-after-completion-hook nil
549 "Hook run at the end of completion, successful or not.
550The hook is called with one argument which is either a string or a symbol."
551 :type 'hook)
552
553(defcustom company-minimum-prefix-length 3
554 "The minimum prefix length for idle completion."
555 :type '(integer :tag "prefix length"))
556
557(defcustom company-abort-manual-when-too-short nil
558 "If enabled, cancel a manually started completion when the prefix gets
559shorter than both `company-minimum-prefix-length' and the length of the
560prefix it was started from."
561 :type 'boolean
562 :package-version '(company . "0.8.0"))
563
564(defcustom company-abort-on-unique-match t
565 "If non-nil, typing a full unique match aborts completion.
566
567You can still invoke `company-complete' manually to run the
568`post-completion' handler, though.
569
570If it's nil, completion will remain active until you type a prefix that
571doesn't match anything or finish it manually, e.g. with RET."
572 :type 'boolean)
573
574(defcustom company-require-match 'company-explicit-action-p
575 "If enabled, disallow non-matching input.
576This can be a function do determine if a match is required.
577
578This can be overridden by the backend, if it returns t or `never' to
579`require-match'. `company-insertion-on-trigger' also takes precedence over
580this."
581 :type '(choice (const :tag "Off" nil)
582 (function :tag "Predicate function")
583 (const :tag "On, if user interaction took place"
584 company-explicit-action-p)
585 (const :tag "On" t)))
586
587(define-obsolete-variable-alias
588 'company-auto-complete
589 'company-insertion-on-trigger
590 "0.9.14")
591
592(define-obsolete-variable-alias
593 'company-auto-commit
594 'company-insertion-on-trigger
595 "0.9.14")
596
597(defcustom company-insertion-on-trigger nil
598 "If enabled, allow triggering insertion of the selected candidate.
599This can also be a predicate function, for example,
600`company-explicit-action-p'.
601
602See `company-insertion-triggers' for more details on how to define
603triggers."
604 :type '(choice (const :tag "Off" nil)
605 (function :tag "Predicate function")
606 (const :tag "On, if user interaction took place"
607 company-explicit-action-p)
608 (const :tag "On" t))
609 :package-version '(company . "0.9.14"))
610
611(define-obsolete-variable-alias
612 'company-auto-complete-chars
613 'company-insertion-triggers
614 "0.9.14")
615
616(define-obsolete-variable-alias
617 'company-auto-commit-chars
618 'company-insertion-triggers
619 "0.9.14")
620
621(defcustom company-insertion-triggers '(?\ ?\) ?.)
622 "Determine triggers for `company-insertion-on-trigger'.
623
624If this is a string, then each character in it can trigger insertion of the
625selected candidate. If it is a list of syntax description characters (see
626`modify-syntax-entry'), then characters with any of those syntaxes can act
627as triggers.
628
629This can also be a function, which is called with the new input. To
630trigger insertion, the function should return a non-nil value.
631
632Note that a character that is part of a valid completion never triggers
633insertion."
634 :type '(choice (string :tag "Characters")
635 (set :tag "Syntax"
636 (const :tag "Whitespace" ?\ )
637 (const :tag "Symbol" ?_)
638 (const :tag "Opening parentheses" ?\()
639 (const :tag "Closing parentheses" ?\))
640 (const :tag "Word constituent" ?w)
641 (const :tag "Punctuation." ?.)
642 (const :tag "String quote." ?\")
643 (const :tag "Paired delimiter." ?$)
644 (const :tag "Expression quote or prefix operator." ?\')
645 (const :tag "Comment starter." ?<)
646 (const :tag "Comment ender." ?>)
647 (const :tag "Character-quote." ?/)
648 (const :tag "Generic string fence." ?|)
649 (const :tag "Generic comment fence." ?!))
650 (function :tag "Predicate function"))
651 :package-version '(company . "0.9.14"))
652
653(defcustom company-idle-delay .2
654 "The idle delay in seconds until completion starts automatically.
655The prefix still has to satisfy `company-minimum-prefix-length' before that
656happens. The value of nil means no idle completion."
657 :type '(choice (const :tag "never (nil)" nil)
658 (const :tag "immediate (0)" 0)
659 (function :tag "Predicate function")
660 (number :tag "seconds")))
661
662(defcustom company-tooltip-idle-delay .5
663 "The idle delay in seconds until tooltip is shown when using
664`company-pseudo-tooltip-unless-just-one-frontend-with-delay'."
665 :type '(choice (const :tag "never (nil)" nil)
666 (const :tag "immediate (0)" 0)
667 (number :tag "seconds")))
668
669(defcustom company-begin-commands '(self-insert-command
670 org-self-insert-command
671 orgtbl-self-insert-command
672 c-scope-operator
673 c-electric-colon
674 c-electric-lt-gt
675 c-electric-slash)
676 "A list of commands after which idle completion is allowed.
677If this is t, it can show completions after any command except a few from a
678pre-defined list. See `company-idle-delay'.
679
680Alternatively, any command with a non-nil `company-begin' property is
681treated as if it was on this list."
682 :type '(choice (const :tag "Any command" t)
683 (const :tag "Self insert command" (self-insert-command))
684 (repeat :tag "Commands" function))
685 :package-version '(company . "0.8.4"))
686
687(defcustom company-continue-commands '(not save-buffer save-some-buffers
688 save-buffers-kill-terminal
689 save-buffers-kill-emacs
690 completion-at-point)
691 "A list of commands that are allowed during completion.
692If this is t, or if `company-begin-commands' is t, any command is allowed.
693Otherwise, the value must be a list of symbols. If it starts with `not',
694the cdr is the list of commands that abort completion. Otherwise, all
695commands except those in that list, or in `company-begin-commands', or
696commands in the `company-' namespace, abort completion."
697 :type '(choice (const :tag "Any command" t)
698 (cons :tag "Any except"
699 (const not)
700 (repeat :tag "Commands" function))
701 (repeat :tag "Commands" function)))
702
703(defun company-custom--set-quick-access (option value)
704 "Re-bind quick-access key sequences on OPTION VALUE change."
705 (when (boundp 'company-active-map)
706 (company-keymap--unbind-quick-access company-active-map))
707 (when (boundp 'company-search-map)
708 (company-keymap--unbind-quick-access company-search-map))
709 (custom-set-default option value)
710 (when (boundp 'company-active-map)
711 (company-keymap--bind-quick-access company-active-map))
712 (when (boundp 'company-search-map)
713 (company-keymap--bind-quick-access company-search-map)))
714
715(defcustom company-quick-access-keys '("1" "2" "3" "4" "5" "6" "7" "8" "9" "0")
716 "Character strings used as a part of quick-access key sequences.
717To change this value without Customize interface, use `customize-set-variable'.
718
719To change the quick-access key sequences modifier, customize
720`company-quick-access-modifier'.
721
722If `company-show-quick-access' is non-nil, show quick-access hints
723beside the candidates."
724 :set #'company-custom--set-quick-access
725 :type '(choice
726 (const :tag "Digits" ("1" "2" "3" "4" "5" "6" "7" "8" "9" "0"))
727 (const :tag "QWERTY home row" ("a" "s" "d" "f" "g" "h" "j" "k" "l" ";"))
728 ;; TODO un-comment on removal of `M-n' `company--select-next-and-warn'.
729 ;; (const :tag "Dvorak home row" ("a" "o" "e" "u" "i" "d" "h" "t" "n" "s"))
730 (repeat :tag "User defined" string))
731 :package-version '(company . "0.9.14"))
732
733(defcustom company-quick-access-modifier 'meta
734 "Modifier key used for quick-access keys sequences.
735To change this value without Customize interface, use `customize-set-variable'.
736See `company-quick-access-keys' for more details."
737 :set #'company-custom--set-quick-access
738 :type '(choice (const :tag "Meta key" meta)
739 (const :tag "Super key" super)
740 (const :tag "Hyper key" hyper)
741 (const :tag "Control key" control))
742 :package-version '(company . "0.9.14"))
743
744(defun company-keymap--quick-access-modifier ()
745 "Return string representation of the `company-quick-access-modifier'."
746 (if-let ((modifier (assoc-default company-quick-access-modifier
747 '((meta . "M")
748 (super . "s")
749 (hyper . "H")
750 (control . "C")))))
751 modifier
752 (warn "company-quick-access-modifier value unknown: %S"
753 company-quick-access-modifier)
754 "M"))
755
756(defun company-keymap--unbind-quick-access (keymap)
757 (let ((modifier (company-keymap--quick-access-modifier)))
758 (dolist (key company-quick-access-keys)
759 (let ((key-seq (company-keymap--kbd-quick-access modifier key)))
760 (when (equal (lookup-key keymap key-seq) 'company-complete-quick-access)
761 (define-key keymap key-seq nil))))))
762
763(defun company-keymap--bind-quick-access (keymap)
764 (let ((modifier (company-keymap--quick-access-modifier)))
765 (dolist (key company-quick-access-keys)
766 (let ((key-seq (company-keymap--kbd-quick-access modifier key)))
767 (if (lookup-key keymap key-seq)
768 (warn "Key sequence %s already bound" (key-description key-seq))
769 (define-key keymap key-seq #'company-complete-quick-access))))))
770
771(defun company-keymap--kbd-quick-access (modifier key)
772 (kbd (format "%s-%s" modifier key)))
773
774(define-obsolete-variable-alias
775 'company-show-numbers
776 'company-show-quick-access
777 "0.9.14")
778
779(defcustom company-show-quick-access nil
780 "If non-nil, show quick-access hints beside the candidates.
781
782For a tooltip frontend, non-nil value enables a column with the hints
783on the right side of the tooltip, unless the configured value is `left'.
784
785To change the quick-access key bindings, customize `company-quick-access-keys'
786and `company-quick-access-modifier'.
787
788To change the shown quick-access hints, customize
789`company-quick-access-hint-function'."
790 :type '(choice (const :tag "off" nil)
791 (const :tag "left" left)
792 (const :tag "on" t)))
793
794(defcustom company-show-numbers-function nil
795 "Function called to get quick-access numbers for the first ten candidates.
796
797The function receives the candidate number (starting from 1) and should
798return a string prefixed with one space."
799 :type 'function)
800(make-obsolete-variable
801 'company-show-numbers-function
802 "use `company-quick-access-hint-function' instead,
803but adjust the expected values appropriately."
804 "0.9.14")
805
806(defcustom company-quick-access-hint-function #'company-quick-access-hint-key
807 "Function called to get quick-access hints for the candidates.
808
809The function receives a candidate's 0-based number
810and should return a string.
811See `company-show-quick-access' for more details."
812 :type 'function)
813
814(defun company-quick-access-hint-key (candidate)
815 "Return a quick-access key for the CANDIDATE number.
816This is a default value of `company-quick-access-hint-function'."
817 (if company-show-numbers-function
818 (funcall company-show-numbers-function (1+ candidate))
819 (format "%s"
820 (if (< candidate (length company-quick-access-keys))
821 (nth candidate company-quick-access-keys)
822 ""))))
823
824(defcustom company-selection-wrap-around nil
825 "If enabled, selecting item before first or after last wraps around."
826 :type '(choice (const :tag "off" nil)
827 (const :tag "on" t)))
828
829(defcustom company-async-redisplay-delay 0.005
830 "Delay before redisplay when fetching candidates asynchronously.
831
832You might want to set this to a higher value if your backends respond
833quickly, to avoid redisplaying twice per each typed character."
834 :type 'number)
835
836(defvar company-async-wait 0.03
837 "Pause between checks to see if the value's been set when turning an
838asynchronous call into synchronous.")
839
840(defvar company-async-timeout 2
841 "Maximum wait time for a value to be set during asynchronous call.")
842
843;;; mode ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
844
845(defvar company-mode-map (make-sparse-keymap)
846 "Keymap used by `company-mode'.")
847
848(defvar company-active-map
849 (let ((keymap (make-sparse-keymap)))
850 (define-key keymap "\e\e\e" 'company-abort)
851 (define-key keymap "\C-g" 'company-abort)
852 (define-key keymap (kbd "M-n") 'company--select-next-and-warn)
853 (define-key keymap (kbd "M-p") 'company--select-previous-and-warn)
854 (define-key keymap (kbd "C-n") 'company-select-next-or-abort)
855 (define-key keymap (kbd "C-p") 'company-select-previous-or-abort)
856 (define-key keymap (kbd "<down>") 'company-select-next-or-abort)
857 (define-key keymap (kbd "<up>") 'company-select-previous-or-abort)
858 (define-key keymap [remap scroll-up-command] 'company-next-page)
859 (define-key keymap [remap scroll-down-command] 'company-previous-page)
860 (define-key keymap [down-mouse-1] 'ignore)
861 (define-key keymap [down-mouse-3] 'ignore)
862 (define-key keymap [mouse-1] 'company-complete-mouse)
863 (define-key keymap [mouse-3] 'company-select-mouse)
864 (define-key keymap [up-mouse-1] 'ignore)
865 (define-key keymap [up-mouse-3] 'ignore)
866 (define-key keymap [return] 'company-complete-selection)
867 (define-key keymap (kbd "RET") 'company-complete-selection)
868 (define-key keymap [tab] 'company-complete-common)
869 (define-key keymap (kbd "TAB") 'company-complete-common)
870 (define-key keymap (kbd "<f1>") 'company-show-doc-buffer)
871 (define-key keymap (kbd "C-h") 'company-show-doc-buffer)
872 (define-key keymap "\C-w" 'company-show-location)
873 (define-key keymap "\C-s" 'company-search-candidates)
874 (define-key keymap "\C-\M-s" 'company-filter-candidates)
875 (company-keymap--bind-quick-access keymap)
876 keymap)
877 "Keymap that is enabled during an active completion.")
878
879(defvar company--disabled-backends nil)
880
881(defun company--select-next-and-warn (&optional arg)
882 (interactive "p")
883 (company--warn-changed-binding)
884 (company-select-next arg))
885
886(defun company--select-previous-and-warn (&optional arg)
887 (interactive "p")
888 (company--warn-changed-binding)
889 (company-select-previous arg))
890
891(defun company--warn-changed-binding ()
892 (interactive)
893 (run-with-idle-timer
894 0.01 nil
895 (lambda ()
896 (message "Warning: default bindings are being changed to C-n and C-p"))))
897
898(defun company-init-backend (backend)
899 (and (symbolp backend)
900 (not (fboundp backend))
901 (ignore-errors (require backend nil t)))
902 (cond
903 ((symbolp backend)
904 (condition-case err
905 (progn
906 (funcall backend 'init)
907 (put backend 'company-init t))
908 (error
909 (put backend 'company-init 'failed)
910 (unless (memq backend company--disabled-backends)
911 (message "Company backend '%s' could not be initialized:\n%s"
912 backend (error-message-string err)))
913 (cl-pushnew backend company--disabled-backends)
914 nil)))
915 ;; No initialization for lambdas.
916 ((functionp backend) t)
917 (t ;; Must be a list.
918 (cl-dolist (b backend)
919 (unless (keywordp b)
920 (company-init-backend b))))))
921
922(defun company--maybe-init-backend (backend)
923 (or (not (symbolp backend))
924 (eq t (get backend 'company-init))
925 (unless (get backend 'company-init)
926 (company-init-backend backend))))
927
928(defcustom company-lighter-base "company"
929 "Base string to use for the `company-mode' lighter."
930 :type 'string
931 :package-version '(company . "0.8.10"))
932
933(defvar company-lighter '(" "
934 (company-candidates
935 (:eval
936 (if (consp company-backend)
937 (when company-selection
938 (company--group-lighter (nth company-selection
939 company-candidates)
940 company-lighter-base))
941 (symbol-name company-backend)))
942 company-lighter-base))
943 "Mode line lighter for Company.
944
945The value of this variable is a mode line template as in
946`mode-line-format'.")
947
948(put 'company-lighter 'risky-local-variable t)
949
950;;;###autoload
951(define-minor-mode company-mode
952 "\"complete anything\"; is an in-buffer completion framework.
953Completion starts automatically, depending on the values
954`company-idle-delay' and `company-minimum-prefix-length'.
955
956Completion can be controlled with the commands:
957`company-complete-common', `company-complete-selection', `company-complete',
958`company-select-next', `company-select-previous'. If these commands are
959called before `company-idle-delay', completion will also start.
960
961Completions can be searched with `company-search-candidates' or
962`company-filter-candidates'. These can be used while completion is
963inactive, as well.
964
965The completion data is retrieved using `company-backends' and displayed
966using `company-frontends'. If you want to start a specific backend, call
967it interactively or use `company-begin-backend'.
968
969By default, the completions list is sorted alphabetically, unless the
970backend chooses otherwise, or `company-transformers' changes it later.
971
972regular keymap (`company-mode-map'):
973
974\\{company-mode-map}
975keymap during active completions (`company-active-map'):
976
977\\{company-active-map}"
978 :lighter company-lighter
979 (if company-mode
980 (progn
981 (add-hook 'pre-command-hook 'company-pre-command nil t)
982 (add-hook 'post-command-hook 'company-post-command nil t)
983 (add-hook 'yas-keymap-disable-hook 'company--active-p nil t)
984 (mapc 'company-init-backend company-backends))
985 (remove-hook 'pre-command-hook 'company-pre-command t)
986 (remove-hook 'post-command-hook 'company-post-command t)
987 (remove-hook 'yas-keymap-disable-hook 'company--active-p t)
988 (company-cancel)
989 (kill-local-variable 'company-point)))
990
991(defcustom company-global-modes t
992 "Modes for which `company-mode' mode is turned on by `global-company-mode'.
993If nil, means no modes. If t, then all major modes have it turned on.
994If a list, it should be a list of `major-mode' symbol names for which
995`company-mode' should be automatically turned on. The sense of the list is
996negated if it begins with `not'. For example:
997 (c-mode c++-mode)
998means that `company-mode' is turned on for buffers in C and C++ modes only.
999 (not message-mode)
1000means that `company-mode' is always turned on except in `message-mode' buffers."
1001 :type '(choice (const :tag "none" nil)
1002 (const :tag "all" t)
1003 (set :menu-tag "mode specific" :tag "modes"
1004 :value (not)
1005 (const :tag "Except" not)
1006 (repeat :inline t (symbol :tag "mode")))))
1007
1008;;;###autoload
1009(define-globalized-minor-mode global-company-mode company-mode company-mode-on)
1010
1011(defun company-mode-on ()
1012 (when (and (not (or noninteractive (eq (aref (buffer-name) 0) ?\s)))
1013 (cond ((eq company-global-modes t)
1014 t)
1015 ((eq (car-safe company-global-modes) 'not)
1016 (not (memq major-mode (cdr company-global-modes))))
1017 (t (memq major-mode company-global-modes))))
1018 (company-mode 1)))
1019
1020(defsubst company-assert-enabled ()
1021 (unless company-mode
1022 (company-uninstall-map)
1023 (user-error "Company not enabled")))
1024
1025;;; keymaps ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1026
1027(defvar-local company-my-keymap nil)
1028
1029(defvar company-emulation-alist '((t . nil)))
1030
1031(defun company-enable-overriding-keymap (keymap)
1032 (company-uninstall-map)
1033 (setq company-my-keymap keymap))
1034
1035(defun company-ensure-emulation-alist ()
1036 (unless (eq 'company-emulation-alist (car emulation-mode-map-alists))
1037 (setq emulation-mode-map-alists
1038 (cons 'company-emulation-alist
1039 (delq 'company-emulation-alist emulation-mode-map-alists)))))
1040
1041(defun company-install-map ()
1042 (unless (or (cdar company-emulation-alist)
1043 (null company-my-keymap))
1044 (setf (cdar company-emulation-alist) company-my-keymap)))
1045
1046(defun company-uninstall-map ()
1047 (setf (cdar company-emulation-alist) nil))
1048
1049(defun company--company-command-p (keys)
1050 "Checks if the keys are part of company's overriding keymap"
1051 (or (equal [company-dummy-event] keys)
1052 (commandp (lookup-key company-my-keymap keys))))
1053
1054;; To avoid warnings in Emacs < 26.
1055(declare-function line-number-display-width "indent.c")
1056
1057(defun company--posn-col-row (posn)
1058 (let ((col (car (posn-col-row posn)))
1059 ;; `posn-col-row' doesn't work well with lines of different height.
1060 ;; `posn-actual-col-row' doesn't handle multiple-width characters.
1061 (row (cdr (or (posn-actual-col-row posn)
1062 ;; When position is non-visible for some reason.
1063 (posn-col-row posn)))))
1064 ;; posn-col-row return value relative to the left
1065 (when (eq (current-bidi-paragraph-direction) 'right-to-left)
1066 (let ((ww (window-body-width)))
1067 (setq col (- ww col))))
1068 (when (bound-and-true-p display-line-numbers)
1069 (cl-decf col (+ 2 (line-number-display-width))))
1070 (cons (+ col (window-hscroll)) row)))
1071
1072(defun company--col-row (&optional pos)
1073 (company--posn-col-row (posn-at-point pos)))
1074
1075(defun company--row (&optional pos)
1076 (cdr (company--col-row pos)))
1077
1078;;; backends ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1079
1080(defvar-local company-backend nil)
1081
1082(defun company-grab (regexp &optional expression limit)
1083 (when (looking-back regexp limit)
1084 (or (match-string-no-properties (or expression 0)) "")))
1085
1086(defun company-grab-line (regexp &optional expression)
1087 "Return a match string for REGEXP if it matches text before point.
1088If EXPRESSION is non-nil, return the match string for the respective
1089parenthesized expression in REGEXP.
1090Matching is limited to the current line."
1091 (let ((inhibit-field-text-motion t))
1092 (company-grab regexp expression (line-beginning-position))))
1093
1094(defun company-grab-symbol ()
1095 "If point is at the end of a symbol, return it.
1096Otherwise, if point is not inside a symbol, return an empty string."
1097 (if (looking-at "\\_>")
1098 (buffer-substring (point) (save-excursion (skip-syntax-backward "w_")
1099 (point)))
1100 (unless (and (char-after) (memq (char-syntax (char-after)) '(?w ?_)))
1101 "")))
1102
1103(defun company-grab-word ()
1104 "If point is at the end of a word, return it.
1105Otherwise, if point is not inside a symbol, return an empty string."
1106 (if (looking-at "\\>")
1107 (buffer-substring (point) (save-excursion (skip-syntax-backward "w")
1108 (point)))
1109 (unless (and (char-after) (eq (char-syntax (char-after)) ?w))
1110 "")))
1111
1112(defun company-grab-symbol-cons (idle-begin-after-re &optional max-len)
1113 "Return a string SYMBOL or a cons (SYMBOL . t).
1114SYMBOL is as returned by `company-grab-symbol'. If the text before point
1115matches IDLE-BEGIN-AFTER-RE, return it wrapped in a cons."
1116 (let ((symbol (company-grab-symbol)))
1117 (when symbol
1118 (save-excursion
1119 (forward-char (- (length symbol)))
1120 (if (looking-back idle-begin-after-re (if max-len
1121 (- (point) max-len)
1122 (line-beginning-position)))
1123 (cons symbol t)
1124 symbol)))))
1125
1126(defun company-in-string-or-comment ()
1127 "Return non-nil if point is within a string or comment."
1128 (let ((ppss (syntax-ppss)))
1129 (or (car (setq ppss (nthcdr 3 ppss)))
1130 (car (setq ppss (cdr ppss)))
1131 (nth 3 ppss))))
1132
1133(defun company-call-backend (&rest args)
1134 (company--force-sync #'company-call-backend-raw args company-backend))
1135
1136(defun company--force-sync (fun args backend)
1137 (let ((value (apply fun args)))
1138 (if (not (eq (car-safe value) :async))
1139 value
1140 (let ((res 'trash)
1141 (start (time-to-seconds)))
1142 (funcall (cdr value)
1143 (lambda (result) (setq res result)))
1144 (while (eq res 'trash)
1145 (if (> (- (time-to-seconds) start) company-async-timeout)
1146 (error "Company: backend %s async timeout with args %s"
1147 backend args)
1148 ;; XXX: Reusing the trick from company--fetch-candidates here
1149 ;; doesn't work well: sit-for isn't a good fit when we want to
1150 ;; ignore pending input (results in too many calls).
1151 ;; FIXME: We should deal with this by standardizing on a kind of
1152 ;; Future object that knows how to sync itself. In most cases (but
1153 ;; not all), by calling accept-process-output, probably.
1154 (sleep-for company-async-wait)))
1155 res))))
1156
1157(defun company-call-backend-raw (&rest args)
1158 (condition-case-unless-debug err
1159 (if (functionp company-backend)
1160 (apply company-backend args)
1161 (apply #'company--multi-backend-adapter company-backend args))
1162 (user-error (user-error
1163 "Company: backend %s user-error: %s"
1164 company-backend (error-message-string err)))
1165 (error (error "Company: backend %s error \"%s\" with args %s"
1166 company-backend (error-message-string err) args))))
1167
1168(defun company--multi-backend-adapter (backends command &rest args)
1169 (let ((backends (cl-loop for b in backends
1170 when (or (keywordp b)
1171 (company--maybe-init-backend b))
1172 collect b))
1173 (separate (memq :separate backends)))
1174
1175 (when (eq command 'prefix)
1176 (setq backends (butlast backends (length (member :with backends)))))
1177
1178 (setq backends (cl-delete-if #'keywordp backends))
1179
1180 (pcase command
1181 (`candidates
1182 (company--multi-backend-adapter-candidates backends (car args) separate))
1183 (`sorted separate)
1184 (`duplicates (not separate))
1185 ((or `prefix `ignore-case `no-cache `require-match)
1186 (let (value)
1187 (cl-dolist (backend backends)
1188 (when (setq value (company--force-sync
1189 backend (cons command args) backend))
1190 (when (and (eq command 'ignore-case)
1191 (eq value 'keep-prefix))
1192 (setq value t))
1193 (cl-return value)))))
1194 (_
1195 (let ((arg (car args)))
1196 (when (> (length arg) 0)
1197 (let ((backend (or (get-text-property 0 'company-backend arg)
1198 (car backends))))
1199 (apply backend command args))))))))
1200
1201(defun company--multi-backend-adapter-candidates (backends prefix separate)
1202 (let ((pairs (cl-loop for backend in backends
1203 when (equal (company--prefix-str
1204 (let ((company-backend backend))
1205 (company-call-backend 'prefix)))
1206 prefix)
1207 collect (cons (funcall backend 'candidates prefix)
1208 (company--multi-candidates-mapper
1209 backend
1210 separate
1211 ;; Small perf optimization: don't tag the
1212 ;; candidates received from the first
1213 ;; backend in the group.
1214 (not (eq backend (car backends))))))))
1215 (company--merge-async pairs (lambda (values) (apply #'append values)))))
1216
1217(defun company--multi-candidates-mapper (backend separate tag)
1218 (lambda (candidates)
1219 (when separate
1220 (let ((company-backend backend))
1221 (setq candidates
1222 (company--preprocess-candidates candidates))))
1223 (when tag
1224 (setq candidates
1225 (mapcar
1226 (lambda (str)
1227 (propertize str 'company-backend backend))
1228 candidates)))
1229 candidates))
1230
1231(defun company--merge-async (pairs merger)
1232 (let ((async (cl-loop for pair in pairs
1233 thereis
1234 (eq :async (car-safe (car pair))))))
1235 (if (not async)
1236 (funcall merger (cl-loop for (val . mapper) in pairs
1237 collect (funcall mapper val)))
1238 (cons
1239 :async
1240 (lambda (callback)
1241 (let* (lst
1242 (pending (mapcar #'car pairs))
1243 (finisher (lambda ()
1244 (unless pending
1245 (funcall callback
1246 (funcall merger
1247 (nreverse lst)))))))
1248 (dolist (pair pairs)
1249 (push nil lst)
1250 (let* ((cell lst)
1251 (val (car pair))
1252 (mapper (cdr pair))
1253 (this-finisher (lambda (res)
1254 (setq pending (delq val pending))
1255 (setcar cell (funcall mapper res))
1256 (funcall finisher))))
1257 (if (not (eq :async (car-safe val)))
1258 (funcall this-finisher val)
1259 (let ((fetcher (cdr val)))
1260 (funcall fetcher this-finisher)))))))))))
1261
1262(defun company--prefix-str (prefix)
1263 (or (car-safe prefix) prefix))
1264
1265;;; completion mechanism ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1266
1267(defvar-local company-prefix nil)
1268
1269(defvar-local company-candidates nil)
1270
1271(defvar-local company-candidates-length nil)
1272
1273(defvar-local company-candidates-cache nil)
1274
1275(defvar-local company-candidates-predicate nil)
1276
1277(defvar-local company-common nil)
1278
1279(defvar company-selection-default 0
1280 "The default value for `company-selection'.")
1281(defvar-local company-selection company-selection-default)
1282
1283(defvar-local company-selection-changed nil)
1284
1285(defvar-local company--manual-action nil
1286 "Non-nil, if manual completion took place.")
1287
1288(defvar-local company--manual-prefix nil)
1289
1290(defvar-local company--point-max nil)
1291
1292(defvar-local company-point nil)
1293
1294(defvar company-timer nil)
1295(defvar company-tooltip-timer nil)
1296
1297(defsubst company-strip-prefix (str)
1298 (substring str (length company-prefix)))
1299
1300(defun company--insert-candidate (candidate)
1301 (when (> (length candidate) 0)
1302 (setq candidate (substring-no-properties candidate))
1303 ;; XXX: Return value we check here is subject to change.
1304 (if (eq (company-call-backend 'ignore-case) 'keep-prefix)
1305 (insert (company-strip-prefix candidate))
1306 (unless (equal company-prefix candidate)
1307 (delete-region (- (point) (length company-prefix)) (point))
1308 (insert candidate)))))
1309
1310(defmacro company-with-candidate-inserted (candidate &rest body)
1311 "Evaluate BODY with CANDIDATE temporarily inserted.
1312This is a tool for backends that need candidates inserted before they
1313can retrieve meta-data for them."
1314 (declare (indent 1))
1315 `(let ((inhibit-modification-hooks t)
1316 (inhibit-point-motion-hooks t)
1317 (modified-p (buffer-modified-p)))
1318 (company--insert-candidate ,candidate)
1319 (unwind-protect
1320 (progn ,@body)
1321 (delete-region company-point (point))
1322 (set-buffer-modified-p modified-p))))
1323
1324(defun company-explicit-action-p ()
1325 "Return whether explicit completion action was taken by the user."
1326 (or company--manual-action
1327 company-selection-changed))
1328
1329(defun company-reformat (candidate)
1330 ;; company-ispell needs this, because the results are always lower-case
1331 ;; It's mory efficient to fix it only when they are displayed.
1332 ;; FIXME: Adopt the current text's capitalization instead?
1333 (if (eq (company-call-backend 'ignore-case) 'keep-prefix)
1334 (let ((prefix (company--clean-string company-prefix)))
1335 (concat prefix (substring candidate (length prefix))))
1336 candidate))
1337
1338(defun company--should-complete ()
1339 (and (eq company-idle-delay 'now)
1340 (not (or buffer-read-only
1341 overriding-local-map))
1342 ;; Check if in the middle of entering a key combination.
1343 (or (equal (this-command-keys-vector) [])
1344 (not (keymapp (key-binding (this-command-keys-vector)))))
1345 (not (and transient-mark-mode mark-active))))
1346
1347(defun company--should-continue ()
1348 (or (eq t company-begin-commands)
1349 (eq t company-continue-commands)
1350 (if (eq 'not (car company-continue-commands))
1351 (not (memq this-command (cdr company-continue-commands)))
1352 (or (memq this-command company-begin-commands)
1353 (memq this-command company-continue-commands)
1354 (and (symbolp this-command)
1355 (string-match-p "\\`company-" (symbol-name this-command)))))))
1356
1357(defvar company-auto-update-doc nil
1358 "If non-nil, update the documentation buffer on each selection change.
1359To toggle the value of this variable, call `company-show-doc-buffer' with a
1360prefix argument.")
1361
1362(defun company-call-frontends (command)
1363 (cl-loop for frontend in company-frontends collect
1364 (condition-case-unless-debug err
1365 (funcall frontend command)
1366 (error (error "Company: frontend %s error \"%s\" on command %s"
1367 frontend (error-message-string err) command)))))
1368
1369(defun company-set-selection (selection &optional force-update)
1370 "Set SELECTION for company candidates.
1371This will update `company-selection' and related variable.
1372Only update when the current selection is changed, but optionally always
1373update if FORCE-UPDATE."
1374 (when selection
1375 (let* ((offset (if company-selection-default 0 1))
1376 (company-candidates-length
1377 (+ company-candidates-length offset)))
1378 (setq selection (+ selection offset))
1379 (setq selection
1380 (if company-selection-wrap-around
1381 (mod selection company-candidates-length)
1382 (max 0 (min (1- company-candidates-length) selection))))
1383 (setq selection (unless (< selection offset)
1384 (- selection offset)))))
1385 (when (or force-update (not (equal selection company-selection)))
1386 (setq company-selection selection
1387 company-selection-changed t)
1388 (company-call-frontends 'update)))
1389
1390(defun company--group-lighter (candidate base)
1391 (let ((backend (or (get-text-property 0 'company-backend candidate)
1392 (cl-some (lambda (x) (and (not (keywordp x)) x))
1393 company-backend))))
1394 (when (and backend (symbolp backend))
1395 (let ((name (replace-regexp-in-string "company-\\|-company" ""
1396 (symbol-name backend))))
1397 (format "%s-<%s>" base name)))))
1398
1399(defun company-update-candidates (candidates)
1400 (setq company-candidates-length (length candidates))
1401 (if company-selection-changed
1402 ;; Try to restore the selection
1403 (let ((selected (and company-selection
1404 (nth company-selection company-candidates))))
1405 (setq company-candidates candidates)
1406 (when selected
1407 (setq company-selection 0)
1408 (catch 'found
1409 (while candidates
1410 (let ((candidate (pop candidates)))
1411 (when (and (string= candidate selected)
1412 (equal (company-call-backend 'annotation candidate)
1413 (company-call-backend 'annotation selected)))
1414 (throw 'found t)))
1415 (cl-incf company-selection))
1416 (setq company-selection company-selection-default
1417 company-selection-changed nil))))
1418 (setq company-selection company-selection-default
1419 company-candidates candidates))
1420 ;; Calculate common.
1421 (let ((completion-ignore-case (company-call-backend 'ignore-case)))
1422 ;; We want to support non-prefix completion, so filtering is the
1423 ;; responsibility of each respective backend, not ours.
1424 ;; On the other hand, we don't want to replace non-prefix input in
1425 ;; `company-complete-common', unless there's only one candidate.
1426 (setq company-common
1427 (if (cdr company-candidates)
1428 (let ((common (try-completion "" company-candidates)))
1429 (when (string-prefix-p company-prefix common
1430 completion-ignore-case)
1431 common))
1432 (car company-candidates)))))
1433
1434(defun company-calculate-candidates (prefix ignore-case)
1435 (let ((candidates (cdr (assoc prefix company-candidates-cache))))
1436 (or candidates
1437 (when company-candidates-cache
1438 (let ((len (length prefix))
1439 (completion-ignore-case ignore-case)
1440 prev)
1441 (cl-dotimes (i (1+ len))
1442 (when (setq prev (cdr (assoc (substring prefix 0 (- len i))
1443 company-candidates-cache)))
1444 (setq candidates (all-completions prefix prev))
1445 (cl-return t)))))
1446 ;; No cache match, call the backend.
1447 (let ((refresh-timer (run-with-timer company-async-redisplay-delay
1448 nil #'company--sneaky-refresh)))
1449 (setq candidates (company--preprocess-candidates
1450 (company--fetch-candidates prefix)))
1451 ;; If the backend is synchronous, no chance for the timer to run.
1452 (cancel-timer refresh-timer)
1453 ;; Save in cache.
1454 (push (cons prefix candidates) company-candidates-cache)))
1455 ;; Only now apply the predicate and transformers.
1456 (company--postprocess-candidates candidates)))
1457
1458(defun company--unique-match-p (candidates prefix ignore-case)
1459 (and candidates
1460 (not (cdr candidates))
1461 (eq t (compare-strings (car candidates) nil nil
1462 prefix nil nil ignore-case))
1463 (not (eq (company-call-backend 'kind (car candidates))
1464 'snippet))))
1465
1466(defun company--fetch-candidates (prefix)
1467 (let* ((non-essential (not (company-explicit-action-p)))
1468 (inhibit-redisplay t)
1469 (c (if (or company-selection-changed
1470 ;; FIXME: This is not ideal, but we have not managed to deal
1471 ;; with these situations in a better way yet.
1472 (company-require-match-p))
1473 (company-call-backend 'candidates prefix)
1474 (company-call-backend-raw 'candidates prefix))))
1475 (if (not (eq (car c) :async))
1476 c
1477 (let ((res 'none))
1478 (funcall
1479 (cdr c)
1480 (lambda (candidates)
1481 (when (eq res 'none)
1482 (push 'company-foo unread-command-events))
1483 (setq res candidates)))
1484 (if (company--flyspell-workaround-p)
1485 (while (and (eq res 'none)
1486 (not (input-pending-p)))
1487 (sleep-for company-async-wait))
1488 (while (and (eq res 'none)
1489 (sit-for 0.5 t))))
1490 (while (member (car unread-command-events)
1491 '(company-foo (t . company-foo)))
1492 (pop unread-command-events))
1493 (prog1
1494 (and (consp res) res)
1495 (setq res 'exited))))))
1496
1497(defun company--sneaky-refresh ()
1498 (when company-candidates (company-call-frontends 'unhide))
1499 (let (inhibit-redisplay)
1500 (redisplay))
1501 (when company-candidates (company-call-frontends 'pre-command)))
1502
1503(defun company--flyspell-workaround-p ()
1504 ;; https://debbugs.gnu.org/23980
1505 (and (bound-and-true-p flyspell-mode)
1506 (version< emacs-version "27")))
1507
1508(defun company--preprocess-candidates (candidates)
1509 (cl-assert (cl-every #'stringp candidates))
1510 (unless (company-call-backend 'sorted)
1511 (setq candidates (sort candidates 'string<)))
1512 (when (company-call-backend 'duplicates)
1513 (company--strip-duplicates candidates))
1514 candidates)
1515
1516(defun company--postprocess-candidates (candidates)
1517 (when (or company-candidates-predicate company-transformers)
1518 (setq candidates (copy-sequence candidates)))
1519 (when company-candidates-predicate
1520 (setq candidates (cl-delete-if-not company-candidates-predicate candidates)))
1521 (company--transform-candidates candidates))
1522
1523(defun company--strip-duplicates (candidates)
1524 (let ((c2 candidates)
1525 (extras 'unk))
1526 (while c2
1527 (setcdr c2
1528 (let ((str (pop c2)))
1529 (while (let ((str2 (car c2)))
1530 (if (not (equal str str2))
1531 (progn
1532 (setq extras 'unk)
1533 nil)
1534 (when (eq extras 'unk)
1535 (setq extras (list (cons (company-call-backend
1536 'annotation str)
1537 (company-call-backend
1538 'kind str)))))
1539 (let ((extra2 (cons (company-call-backend
1540 'annotation str2)
1541 (company-call-backend
1542 'kind str2))))
1543 (if (member extra2 extras)
1544 t
1545 (push extra2 extras)
1546 nil))))
1547 (pop c2))
1548 c2)))))
1549
1550(defun company--transform-candidates (candidates)
1551 (let ((c candidates))
1552 (dolist (tr company-transformers)
1553 (setq c (funcall tr c)))
1554 c))
1555
1556(defcustom company-occurrence-weight-function
1557 #'company-occurrence-prefer-closest-above
1558 "Function to weigh matches in `company-sort-by-occurrence'.
1559It's called with three arguments: cursor position, the beginning and the
1560end of the match."
1561 :type '(choice
1562 (const :tag "First above point, then below point"
1563 company-occurrence-prefer-closest-above)
1564 (const :tag "Prefer closest in any direction"
1565 company-occurrence-prefer-any-closest)))
1566
1567(defvar company-vscode-icons-mapping
1568 '((array . "symbol-array.svg")
1569 (boolean . "symbol-boolean.svg")
1570 (class . "symbol-class.svg")
1571 (color . "symbol-color.svg")
1572 (constant . "symbol-constant.svg")
1573 (constructor . "symbol-method.svg")
1574 (enum-member . "symbol-enumerator-member.svg")
1575 (enum . "symbol-enumerator.svg")
1576 (event . "symbol-event.svg")
1577 (field . "symbol-field.svg")
1578 (file . "symbol-file.svg")
1579 (folder . "folder.svg")
1580 (interface . "symbol-interface.svg")
1581 (keyword . "symbol-keyword.svg")
1582 (method . "symbol-method.svg")
1583 (function . "symbol-method.svg")
1584 (module . "symbol-namespace.svg")
1585 (numeric . "symbol-numeric.svg")
1586 (operator . "symbol-operator.svg")
1587 (property . "symbol-property.svg")
1588 (reference . "references.svg")
1589 (snippet . "symbol-snippet.svg")
1590 (string . "symbol-string.svg")
1591 (struct . "symbol-structure.svg")
1592 (text . "symbol-key.svg")
1593 (type-parameter . "symbol-parameter.svg")
1594 (unit . "symbol-ruler.svg")
1595 (value . "symbol-enumerator.svg")
1596 (variable . "symbol-variable.svg")
1597 (t . "symbol-misc.svg")))
1598
1599(defconst company-icons-root
1600 (file-name-as-directory
1601 (expand-file-name "icons"
1602 (file-name-directory (or load-file-name buffer-file-name)))))
1603
1604(defcustom company-icon-size '(auto-scale . 16)
1605 "Size of icons indicating completion kind in the popup."
1606 :type '(choice (integer :tag "Size in pixels" :value 16)
1607 (cons :tag "Size in pixels, scaled 2x on HiDPI screens"
1608 (const auto-scale)
1609 (integer :value 16))))
1610
1611(defcustom company-icon-margin 2
1612 "Width of the margin that shows the icons, in characters."
1613 :type 'integer)
1614
1615(defun company--render-icons-margin (icon-mapping root-dir candidate selected)
1616 (if-let ((ws (window-system))
1617 (candidate candidate)
1618 (kind (company-call-backend 'kind candidate))
1619 (icon-file (or (alist-get kind icon-mapping)
1620 (alist-get t icon-mapping))))
1621 (let* ((bkg (face-attribute (if selected
1622 'company-tooltip-selection
1623 'company-tooltip)
1624 :background))
1625 (dfw (default-font-width))
1626 (icon-size (cond
1627 ((integerp company-icon-size)
1628 company-icon-size)
1629 ;; XXX: Also consider smooth scaling, e.g. using
1630 ;; (aref (font-info (face-font 'default)) 2)
1631 ((and (consp company-icon-size)
1632 (eq 'auto-scale (car company-icon-size)))
1633 (let ((base-size (cdr company-icon-size))
1634 (dfh (default-font-height)))
1635 (min
1636 (if (>= dfh (* 2 base-size))
1637 (* 2 base-size)
1638 base-size)
1639 (* company-icon-margin dfw))))))
1640 (spec (list 'image
1641 :file (expand-file-name icon-file root-dir)
1642 :type 'svg
1643 :width icon-size
1644 :height icon-size
1645 :ascent 'center
1646 :background (unless (eq bkg 'unspecified)
1647 bkg)))
1648 (spacer-px-width (- (* company-icon-margin dfw) icon-size)))
1649 (cond
1650 ((<= company-icon-margin 2)
1651 (concat
1652 (propertize " " 'display spec)
1653 (propertize (company-space-string (1- company-icon-margin))
1654 'display `(space . (:width (,spacer-px-width))))))
1655 (t
1656 (let* ((spacer-left (/ spacer-px-width 2))
1657 (spacer-right (- spacer-px-width spacer-left)))
1658 (concat
1659 (propertize (company-space-string 1)
1660 'display `(space . (:width (,spacer-left))))
1661 (propertize " " 'display spec)
1662 (propertize (company-space-string (- company-icon-margin 2))
1663 'display `(space . (:width (,spacer-right)))))))))
1664 nil))
1665
1666(defun company-vscode-dark-icons-margin (candidate selected)
1667 "Margin function which returns icons from vscode's dark theme."
1668 (company--render-icons-margin company-vscode-icons-mapping
1669 (expand-file-name "vscode-dark" company-icons-root)
1670 candidate
1671 selected))
1672
1673(defun company-vscode-light-icons-margin (candidate selected)
1674 "Margin function which returns icons from vscode's light theme."
1675 (company--render-icons-margin company-vscode-icons-mapping
1676 (expand-file-name "vscode-light" company-icons-root)
1677 candidate
1678 selected))
1679
1680(defcustom company-text-icons-mapping
1681 '((array "a" font-lock-type-face)
1682 (boolean "b" font-lock-builtin-face)
1683 (class "c" font-lock-type-face)
1684 (color "#" success)
1685 (constant "c" font-lock-constant-face)
1686 (constructor "c" font-lock-function-name-face)
1687 (enum-member "e" font-lock-builtin-face)
1688 (enum "e" font-lock-builtin-face)
1689 (field "f" font-lock-variable-name-face)
1690 (file "f" font-lock-string-face)
1691 (folder "d" font-lock-doc-face)
1692 (interface "i" font-lock-type-face)
1693 (keyword "k" font-lock-keyword-face)
1694 (method "m" font-lock-function-name-face)
1695 (function "f" font-lock-function-name-face)
1696 (module "{" font-lock-type-face)
1697 (numeric "n" font-lock-builtin-face)
1698 (operator "o" font-lock-comment-delimiter-face)
1699 (property "p" font-lock-variable-name-face)
1700 (reference "r" font-lock-doc-face)
1701 (snippet "S" font-lock-string-face)
1702 (string "s" font-lock-string-face)
1703 (struct "%" font-lock-variable-name-face)
1704 (text "w" shadow)
1705 (type-parameter "p" font-lock-type-face)
1706 (unit "u" shadow)
1707 (value "v" font-lock-builtin-face)
1708 (variable "v" font-lock-variable-name-face)
1709 (t "." shadow))
1710 "Mapping of the text icons.
1711The format should be an alist of (KIND . CONF) where CONF is a list of the
1712form (ICON FG BG) which is used to propertize the icon to be shown for a
1713candidate of kind KIND. FG can either be color string or a face from which
1714we can get a color string (using the :foreground face-property). BG must be
1715of the same form as FG or a cons cell of (BG . BG-WHEN-SELECTED) which each
1716should be of the same form as FG.
1717
1718The only mandatory element in CONF is ICON, you can omit both the FG and BG
1719fields without issue.
1720
1721When BG is omitted and `company-text-icons-add-background' is non-nil, a BG
1722color is generated using a gradient between the active tooltip color and
1723the FG color."
1724 :type '(repeat sexp))
1725
1726(defcustom company-text-face-extra-attributes '(:weight bold)
1727 "Additional attributes to add to text/dot icons faces.
1728If non-nil, an anonymous face is generated.
1729
1730Affects `company-text-icons-margin' and `company-dot-icons-margin'."
1731 :type '(plist :tag "Face property list"))
1732
1733(defcustom company-text-icons-format " %s "
1734 "Format string for printing the text icons."
1735 :type 'string)
1736
1737(defcustom company-text-icons-add-background nil
1738 "Generate a background color for text/dot icons when none is given.
1739See `company-text-icons-mapping'."
1740 :type 'boolean)
1741
1742(defun company-text-icons-margin (candidate selected)
1743 "Margin function which returns unicode icons."
1744 (when-let ((candidate candidate)
1745 (kind (company-call-backend 'kind candidate))
1746 (conf (or (alist-get kind company-text-icons-mapping)
1747 (alist-get t company-text-icons-mapping))))
1748 (cl-destructuring-bind (icon &optional fg bg) conf
1749 (propertize
1750 (format company-text-icons-format icon)
1751 'face
1752 (company-text-icons--face fg bg selected)))))
1753
1754(declare-function color-rgb-to-hex "color")
1755(declare-function color-gradient "color")
1756
1757(defun company-text-icons--extract-property (face property)
1758 "Try to extract PROPERTY from FACE.
1759If FACE isn't a valid face return FACE as is. If FACE doesn't have
1760PROPERTY return nil."
1761 (if (facep face)
1762 (let ((value (face-attribute face property)))
1763 (unless (eq value 'unspecified)
1764 value))
1765 face))
1766
1767(defun company-text-icons--face (fg bg selected)
1768 (let ((fg-color (company-text-icons--extract-property fg :foreground)))
1769 `(,@company-text-face-extra-attributes
1770 ,@(and fg-color
1771 (list :foreground fg-color))
1772 ,@(let* ((bg-is-cons (consp bg))
1773 (bg (if bg-is-cons (if selected (cdr bg) (car bg)) bg))
1774 (bg-color (company-text-icons--extract-property bg :background))
1775 (tooltip-bg-color (company-text-icons--extract-property
1776 (if selected
1777 'company-tooltip-selection
1778 'company-tooltip)
1779 :background)))
1780 (cond
1781 ((and company-text-icons-add-background selected
1782 (not bg-is-cons) bg-color tooltip-bg-color)
1783 ;; Adjust the coloring of the background when *selected* but user hasn't
1784 ;; specified an alternate background color for selected item icons.
1785 (list :background
1786 (apply #'color-rgb-to-hex
1787 (nth 0 (color-gradient (color-name-to-rgb tooltip-bg-color)
1788 (color-name-to-rgb bg-color)
1789 2)))))
1790 (bg
1791 ;; When background is configured we use it as is, even if it doesn't
1792 ;; constrast well with other candidates when selected.
1793 (and bg-color
1794 (list :background bg-color)))
1795 ((and company-text-icons-add-background fg-color tooltip-bg-color)
1796 ;; Lastly attempt to generate a background from the foreground.
1797 (list :background
1798 (apply #'color-rgb-to-hex
1799 (nth 0 (color-gradient (color-name-to-rgb tooltip-bg-color)
1800 (color-name-to-rgb fg-color)
1801 10))))))))))
1802
1803(defcustom company-dot-icons-format "● "
1804 "Format string for `company-dot-icons-margin'."
1805 :type 'string)
1806
1807(defun company-dot-icons-margin (candidate selected)
1808 "Margin function that uses a colored dot to display completion kind."
1809 (when-let ((kind (company-call-backend 'kind candidate))
1810 (conf (or (assoc-default kind company-text-icons-mapping)
1811 (assoc-default t company-text-icons-mapping))))
1812 (cl-destructuring-bind (_icon &optional fg bg) conf
1813 (propertize company-dot-icons-format
1814 'face
1815 (company-text-icons--face fg bg selected)))))
1816
1817(defun company-detect-icons-margin (candidate selected)
1818 "Margin function which picks the appropriate icon set automatically."
1819 (if (and (display-graphic-p)
1820 (image-type-available-p 'svg))
1821 (cl-case (frame-parameter nil 'background-mode)
1822 (light (company-vscode-light-icons-margin candidate selected))
1823 (t (company-vscode-dark-icons-margin candidate selected)))
1824 (company-text-icons-margin candidate selected)))
1825
1826(defcustom company-format-margin-function #'company-detect-icons-margin
1827 "Function to format the margin.
1828It accepts 2 params `candidate' and `selected' and can be used for
1829inserting prefix/image before the completion items. Typically, the
1830functions call the backends with `kind' and then insert the appropriate
1831image for the returned kind image. Function is called with (nil nil) to get
1832the default margin."
1833 :type '(choice
1834 (const :tag "Disabled" nil)
1835 (const :tag "Detect icons theme base on conditions" company-detect-icons-margin)
1836 (const :tag "Text characters as icons" company-text-icons-margin)
1837 (const :tag "Colored dots as icons" company-dot-icons-margin)
1838 (const :tag "VScode dark icons theme" company-vscode-dark-icons-margin)
1839 (const :tag "VScode light icons theme" company-vscode-light-icons-margin)
1840 (function :tag "Custom icon function.")))
1841
1842(defun company-occurrence-prefer-closest-above (pos match-beg match-end)
1843 "Give priority to the matches above point, then those below point."
1844 (if (< match-beg pos)
1845 (- pos match-end)
1846 (- match-beg (window-start))))
1847
1848(defun company-occurrence-prefer-any-closest (pos _match-beg match-end)
1849 "Give priority to the matches closest to the point."
1850 (abs (- pos match-end)))
1851
1852(defun company-sort-by-occurrence (candidates)
1853 "Sort CANDIDATES according to their occurrences.
1854Searches for each in the currently visible part of the current buffer and
1855prioritizes the matches according to `company-occurrence-weight-function'.
1856The rest of the list is appended unchanged.
1857Keywords and function definition names are ignored."
1858 (let* ((w-start (window-start))
1859 (w-end (window-end))
1860 (start-point (point))
1861 occurs
1862 (noccurs
1863 (save-excursion
1864 (cl-delete-if
1865 (lambda (candidate)
1866 (goto-char w-start)
1867 (when (and (not (equal candidate ""))
1868 (search-forward candidate w-end t)
1869 ;; ^^^ optimize for large lists where most elements
1870 ;; won't have a match.
1871 (catch 'done
1872 (goto-char (1- start-point))
1873 (while (search-backward candidate w-start t)
1874 (when (save-match-data
1875 (company--occurrence-predicate))
1876 (throw 'done t)))
1877 (goto-char start-point)
1878 (while (search-forward candidate w-end t)
1879 (when (save-match-data
1880 (company--occurrence-predicate))
1881 (throw 'done t)))))
1882 (push
1883 (cons candidate
1884 (funcall company-occurrence-weight-function
1885 start-point
1886 (match-beginning 0)
1887 (match-end 0)))
1888 occurs)
1889 t))
1890 candidates))))
1891 (nconc
1892 (mapcar #'car (sort occurs (lambda (e1 e2) (<= (cdr e1) (cdr e2)))))
1893 noccurs)))
1894
1895(defun company--occurrence-predicate ()
1896 (defvar comint-last-prompt)
1897 (let ((beg (match-beginning 0))
1898 (end (match-end 0))
1899 (comint-last-prompt (bound-and-true-p comint-last-prompt)))
1900 (save-excursion
1901 (goto-char end)
1902 ;; Workaround for python-shell-completion-at-point's behavior:
1903 ;; https://github.com/company-mode/company-mode/issues/759
1904 ;; https://github.com/company-mode/company-mode/issues/549
1905 (when (derived-mode-p 'inferior-python-mode)
1906 (let ((lbp (line-beginning-position)))
1907 (setq comint-last-prompt (cons lbp lbp))))
1908 (and (not (memq (get-text-property (1- (point)) 'face)
1909 '(font-lock-function-name-face
1910 font-lock-keyword-face)))
1911 (let ((prefix (company--prefix-str
1912 (company-call-backend 'prefix))))
1913 (and (stringp prefix)
1914 (= (length prefix) (- end beg))))))))
1915
1916(defun company-sort-by-backend-importance (candidates)
1917 "Sort CANDIDATES as two priority groups.
1918If `company-backend' is a function, do nothing. If it's a list, move
1919candidates from backends before keyword `:with' to the front. Candidates
1920from the rest of the backends in the group, if any, will be left at the end."
1921 (if (functionp company-backend)
1922 candidates
1923 (let ((low-priority (cdr (memq :with company-backend))))
1924 (if (null low-priority)
1925 candidates
1926 (sort candidates
1927 (lambda (c1 c2)
1928 (and
1929 (let ((b2 (get-text-property 0 'company-backend c2)))
1930 (and b2 (memq b2 low-priority)))
1931 (let ((b1 (get-text-property 0 'company-backend c1)))
1932 (or (not b1) (not (memq b1 low-priority)))))))))))
1933
1934(defun company-sort-prefer-same-case-prefix (candidates)
1935 "Prefer CANDIDATES with the exact same prefix.
1936If a backend returns case insensitive matches, candidates with the an exact
1937prefix match (same case) will be prioritized."
1938 (cl-loop for candidate in candidates
1939 if (string-prefix-p company-prefix candidate)
1940 collect candidate into same-case
1941 else collect candidate into other-case
1942 finally return (append same-case other-case)))
1943
1944(defun company-idle-begin (buf win tick pos)
1945 (and (eq buf (current-buffer))
1946 (eq win (selected-window))
1947 (eq tick (buffer-chars-modified-tick))
1948 (eq pos (point))
1949 (let ((non-essential t))
1950 (when (company-auto-begin)
1951 (let ((this-command 'company-idle-begin))
1952 (company-post-command))))))
1953
1954(defun company-auto-begin ()
1955 (and company-mode
1956 (not company-candidates)
1957 (let ((company-idle-delay 'now))
1958 (condition-case-unless-debug err
1959 (let ((inhibit-quit nil))
1960 (company--perform)
1961 ;; Return non-nil if active.
1962 company-candidates)
1963 (error (message "Company: An error occurred in auto-begin")
1964 (message "%s" (error-message-string err))
1965 (company-cancel))
1966 (quit (company-cancel))))))
1967
1968;;;###autoload
1969(defun company-manual-begin ()
1970 (interactive)
1971 (company-assert-enabled)
1972 (setq company--manual-action t)
1973 (unwind-protect
1974 (let ((company-minimum-prefix-length 0))
1975 (or company-candidates
1976 (company-auto-begin)))
1977 (unless company-candidates
1978 (setq company--manual-action nil))))
1979
1980(defun company-other-backend (&optional backward)
1981 (interactive (list current-prefix-arg))
1982 (company-assert-enabled)
1983 (let* ((after (if company-backend
1984 (cdr (member company-backend company-backends))
1985 company-backends))
1986 (before (cdr (member company-backend (reverse company-backends))))
1987 (next (if backward
1988 (append before (reverse after))
1989 (append after (reverse before)))))
1990 (company-cancel)
1991 (cl-dolist (backend next)
1992 (when (ignore-errors (company-begin-backend backend))
1993 (cl-return t))))
1994 (unless company-candidates
1995 (user-error "No other backend")))
1996
1997(defun company-require-match-p ()
1998 (let ((backend-value (company-call-backend 'require-match)))
1999 (or (eq backend-value t)
2000 (and (not (eq backend-value 'never))
2001 (if (functionp company-require-match)
2002 (funcall company-require-match)
2003 (eq company-require-match t))))))
2004
2005(defun company-insertion-on-trigger-p (input)
2006 "Return non-nil if INPUT should trigger insertion.
2007For more details see `company-insertion-on-trigger' and
2008`company-insertion-triggers'."
2009 (and (if (functionp company-insertion-on-trigger)
2010 (funcall company-insertion-on-trigger)
2011 company-insertion-on-trigger)
2012 (if (functionp company-insertion-triggers)
2013 (funcall company-insertion-triggers input)
2014 (if (consp company-insertion-triggers)
2015 (memq (char-syntax (string-to-char input))
2016 company-insertion-triggers)
2017 (string-match (regexp-quote (substring input 0 1))
2018 company-insertion-triggers)))))
2019
2020(defun company--incremental-p ()
2021 (and (> (point) company-point)
2022 (> (point-max) company--point-max)
2023 (not (eq this-command 'backward-delete-char-untabify))
2024 (equal (buffer-substring (- company-point (length company-prefix))
2025 company-point)
2026 company-prefix)))
2027
2028(defun company--continue-failed (new-prefix)
2029 (cond
2030 ((and (or (not (company-require-match-p))
2031 ;; Don't require match if the new prefix
2032 ;; doesn't continue the old one, and the latter was a match.
2033 (not (stringp new-prefix))
2034 (<= (length new-prefix) (length company-prefix)))
2035 (member company-prefix company-candidates))
2036 ;; Last input was a success,
2037 ;; but we're treating it as an abort + input anyway,
2038 ;; like the `unique' case below.
2039 (company-cancel 'non-unique))
2040 ((company-require-match-p)
2041 ;; Wrong incremental input, but required match.
2042 (delete-char (- company-point (point)))
2043 (ding)
2044 (message "Matching input is required")
2045 company-candidates)
2046 (t (company-cancel))))
2047
2048(defun company--good-prefix-p (prefix)
2049 (and (stringp (company--prefix-str prefix)) ;excludes 'stop
2050 (or (eq (cdr-safe prefix) t)
2051 (let ((len (or (cdr-safe prefix) (length prefix))))
2052 (if company--manual-prefix
2053 (or (not company-abort-manual-when-too-short)
2054 ;; Must not be less than minimum or initial length.
2055 (>= len (min company-minimum-prefix-length
2056 (length company--manual-prefix))))
2057 (>= len company-minimum-prefix-length))))))
2058
2059(defun company--continue ()
2060 (when (company-call-backend 'no-cache company-prefix)
2061 ;; Don't complete existing candidates, fetch new ones.
2062 (setq company-candidates-cache nil))
2063 (let* ((new-prefix (company-call-backend 'prefix))
2064 (ignore-case (company-call-backend 'ignore-case))
2065 (c (when (and (company--good-prefix-p new-prefix)
2066 (setq new-prefix (company--prefix-str new-prefix))
2067 (= (- (point) (length new-prefix))
2068 (- company-point (length company-prefix))))
2069 (company-calculate-candidates new-prefix ignore-case))))
2070 (cond
2071 ((and company-abort-on-unique-match
2072 (company--unique-match-p c new-prefix ignore-case))
2073 ;; Handle it like completion was aborted, to differentiate from user
2074 ;; calling one of Company's commands to insert the candidate,
2075 ;; not to trigger template expansion, etc.
2076 (company-cancel 'unique))
2077 ((consp c)
2078 ;; incremental match
2079 (setq company-prefix new-prefix)
2080 (company-update-candidates c)
2081 c)
2082 ((and (characterp last-command-event)
2083 (company-insertion-on-trigger-p (string last-command-event)))
2084 ;; Insertion on trigger.
2085 (save-excursion
2086 (goto-char company-point)
2087 (company-complete-selection)
2088 nil))
2089 ((not (company--incremental-p))
2090 (company-cancel))
2091 (t (company--continue-failed new-prefix)))))
2092
2093(defun company--begin-new ()
2094 (let (prefix c)
2095 (cl-dolist (backend (if company-backend
2096 ;; prefer manual override
2097 (list company-backend)
2098 company-backends))
2099 (setq prefix
2100 (if (or (symbolp backend)
2101 (functionp backend))
2102 (when (company--maybe-init-backend backend)
2103 (let ((company-backend backend))
2104 (company-call-backend 'prefix)))
2105 (company--multi-backend-adapter backend 'prefix)))
2106 (when prefix
2107 (when (company--good-prefix-p prefix)
2108 (let ((ignore-case (company-call-backend 'ignore-case)))
2109 (setq company-prefix (company--prefix-str prefix)
2110 company-backend backend
2111 c (company-calculate-candidates company-prefix ignore-case))
2112 (cond
2113 ((and company-abort-on-unique-match
2114 (company--unique-match-p c company-prefix ignore-case)
2115 (if company--manual-action
2116 ;; If `company-manual-begin' was called, the user
2117 ;; really wants something to happen. Otherwise...
2118 (ignore (message "Sole completion"))
2119 t))
2120 ;; ...abort and run the hooks, e.g. to clear the cache.
2121 (company-cancel 'unique))
2122 ((null c)
2123 (when company--manual-action
2124 (message "No completion found")))
2125 (t ;; We got completions!
2126 (when company--manual-action
2127 (setq company--manual-prefix prefix))
2128 (company-update-candidates c)
2129 (run-hook-with-args 'company-completion-started-hook
2130 (company-explicit-action-p))
2131 (company-call-frontends 'show)))))
2132 (cl-return c)))))
2133
2134(defun company--perform ()
2135 (cond
2136 (company-candidates
2137 (company--continue))
2138 ((company--should-complete)
2139 (company--begin-new)))
2140 (if (not company-candidates)
2141 (setq company-backend nil)
2142 (setq company-point (point)
2143 company--point-max (point-max))
2144 (company-ensure-emulation-alist)
2145 (company-enable-overriding-keymap company-active-map)
2146 (company-call-frontends 'update)))
2147
2148(defun company-cancel (&optional result)
2149 (let ((prefix company-prefix)
2150 (backend company-backend))
2151 (setq company-backend nil
2152 company-prefix nil
2153 company-candidates nil
2154 company-candidates-length nil
2155 company-candidates-cache nil
2156 company-candidates-predicate nil
2157 company-common nil
2158 company-selection company-selection-default
2159 company-selection-changed nil
2160 company--manual-action nil
2161 company--manual-prefix nil
2162 company--point-max nil
2163 company-point nil)
2164 (when company-timer
2165 (cancel-timer company-timer))
2166 (company-echo-cancel t)
2167 (company-search-mode 0)
2168 (company-call-frontends 'hide)
2169 (company-enable-overriding-keymap nil)
2170 (when prefix
2171 (if (stringp result)
2172 (let ((company-backend backend))
2173 (run-hook-with-args 'company-completion-finished-hook result)
2174 (company-call-backend 'post-completion result))
2175 (run-hook-with-args 'company-completion-cancelled-hook result))
2176 (run-hook-with-args 'company-after-completion-hook result)))
2177 ;; Make return value explicit.
2178 nil)
2179
2180(defun company-abort ()
2181 (interactive)
2182 (company-cancel 'abort))
2183
2184(defun company-finish (result)
2185 (company--insert-candidate result)
2186 (company-cancel result))
2187
2188(defsubst company-keep (command)
2189 (and (symbolp command) (get command 'company-keep)))
2190
2191(defun company--active-p ()
2192 company-candidates)
2193
2194(defun company-pre-command ()
2195 (company--electric-restore-window-configuration)
2196 (unless (company-keep this-command)
2197 (condition-case-unless-debug err
2198 (when company-candidates
2199 (company-call-frontends 'pre-command)
2200 (unless (company--should-continue)
2201 (company-abort)))
2202 (error (message "Company: An error occurred in pre-command")
2203 (message "%s" (error-message-string err))
2204 (company-cancel))))
2205 (when company-timer
2206 (cancel-timer company-timer)
2207 (setq company-timer nil))
2208 (company-echo-cancel t)
2209 (company-uninstall-map))
2210
2211(defun company-post-command ()
2212 (when (and company-candidates
2213 (null this-command))
2214 ;; Happens when the user presses `C-g' while inside
2215 ;; `flyspell-post-command-hook', for example.
2216 ;; Or any other `post-command-hook' function that can call `sit-for',
2217 ;; or any quittable timer function.
2218 (company-abort)
2219 (setq this-command 'company-abort))
2220 (unless (company-keep this-command)
2221 (condition-case-unless-debug err
2222 (progn
2223 (unless (equal (point) company-point)
2224 (let (company-idle-delay) ; Against misbehavior while debugging.
2225 (company--perform)))
2226 (if company-candidates
2227 (progn
2228 (company-call-frontends 'post-command)
2229 (when company-auto-update-doc
2230 (condition-case nil
2231 (company-show-doc-buffer)
2232 (user-error nil))))
2233 (let ((delay (company--idle-delay)))
2234 (and (numberp delay)
2235 (not defining-kbd-macro)
2236 (company--should-begin)
2237 (setq company-timer
2238 (run-with-timer delay nil
2239 'company-idle-begin
2240 (current-buffer) (selected-window)
2241 (buffer-chars-modified-tick) (point)))))))
2242 (error (message "Company: An error occurred in post-command")
2243 (message "%s" (error-message-string err))
2244 (company-cancel))))
2245 (company-install-map))
2246
2247(defun company--idle-delay ()
2248 (let ((delay
2249 (if (functionp company-idle-delay)
2250 (funcall company-idle-delay)
2251 company-idle-delay)))
2252 (if (memql delay '(t 0 0.0))
2253 0.01
2254 delay)))
2255
2256(defvar company--begin-inhibit-commands '(company-abort
2257 company-complete-mouse
2258 company-complete
2259 company-complete-common
2260 company-complete-selection
2261 company-complete-tooltip-row)
2262 "List of commands after which idle completion is (still) disabled when
2263`company-begin-commands' is t.")
2264
2265(defun company--should-begin ()
2266 (if (eq t company-begin-commands)
2267 (not (memq this-command company--begin-inhibit-commands))
2268 (or
2269 (memq this-command company-begin-commands)
2270 (and (symbolp this-command) (get this-command 'company-begin)))))
2271
2272;;; search ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2273
2274(defcustom company-search-regexp-function #'regexp-quote
2275 "Function to construct the search regexp from input.
2276It's called with one argument, the current search input. It must return
2277either a regexp without groups, or one where groups don't intersect and
2278each one wraps a part of the input string."
2279 :type '(choice
2280 (const :tag "Exact match" regexp-quote)
2281 (const :tag "Words separated with spaces" company-search-words-regexp)
2282 (const :tag "Words separated with spaces, in any order"
2283 company-search-words-in-any-order-regexp)
2284 (const :tag "All characters in given order, with anything in between"
2285 company-search-flex-regexp)))
2286
2287(defvar-local company-search-string "")
2288
2289(defvar company-search-lighter '(" "
2290 (company-search-filtering "Filter" "Search")
2291 ": \""
2292 company-search-string
2293 "\""))
2294
2295(defvar-local company-search-filtering nil
2296 "Non-nil to filter the completion candidates by the search string")
2297
2298(defvar-local company--search-old-selection 0)
2299
2300(defvar-local company--search-old-changed nil)
2301
2302(defun company-search-words-regexp (input)
2303 (mapconcat (lambda (word) (format "\\(%s\\)" (regexp-quote word)))
2304 (split-string input " +" t) ".*"))
2305
2306(defun company-search-words-in-any-order-regexp (input)
2307 (let* ((words (mapcar (lambda (word) (format "\\(%s\\)" (regexp-quote word)))
2308 (split-string input " +" t)))
2309 (permutations (company--permutations words)))
2310 (mapconcat (lambda (words)
2311 (mapconcat #'identity words ".*"))
2312 permutations
2313 "\\|")))
2314
2315(defun company-search-flex-regexp (input)
2316 (if (zerop (length input))
2317 ""
2318 (concat (regexp-quote (string (aref input 0)))
2319 (mapconcat (lambda (c)
2320 (concat "[^" (string c) "]*"
2321 (regexp-quote (string c))))
2322 (substring input 1) ""))))
2323
2324(defun company--permutations (lst)
2325 (if (not lst)
2326 '(nil)
2327 ;; FIXME: Replace with `mapcan' in Emacs 26.
2328 (cl-mapcan
2329 (lambda (e)
2330 (mapcar (lambda (perm) (cons e perm))
2331 (company--permutations (cl-remove e lst :count 1))))
2332 lst)))
2333
2334(defun company--search (text lines)
2335 (let ((re (funcall company-search-regexp-function text))
2336 (i 0))
2337 (cl-dolist (line lines)
2338 (when (string-match-p re line)
2339 (cl-return i))
2340 (cl-incf i))))
2341
2342(defun company-search-printing-char ()
2343 (interactive)
2344 (company--search-assert-enabled)
2345 (let* ((event-type (event-basic-type last-command-event))
2346 (event-string (if (characterp event-type)
2347 (string last-command-event)
2348 ;; Handle key press on the keypad.
2349 (let ((name (symbol-name event-type)))
2350 (if (string-match "kp-\\([0-9]\\)" name)
2351 (match-string 1 name)
2352 (error "Unexpected printing char input")))))
2353 (ss (concat company-search-string event-string)))
2354 (when company-search-filtering
2355 (company--search-update-predicate ss))
2356 (company--search-update-string ss)))
2357
2358(defun company--search-update-predicate (ss)
2359 (let* ((re (funcall company-search-regexp-function ss))
2360 (company-candidates-predicate
2361 (and (not (string= re ""))
2362 company-search-filtering
2363 (lambda (candidate) (string-match re candidate))))
2364 (cc (company-calculate-candidates company-prefix
2365 (company-call-backend 'ignore-case))))
2366 (unless cc (user-error "No match"))
2367 (company-update-candidates cc)))
2368
2369(defun company--search-update-string (new)
2370 (let* ((selection (or company-selection 0))
2371 (pos (company--search new (nthcdr selection company-candidates))))
2372 (if (null pos)
2373 (ding)
2374 (setq company-search-string new)
2375 (company-set-selection (+ selection pos) t))))
2376
2377(defun company--search-assert-input ()
2378 (company--search-assert-enabled)
2379 (when (string= company-search-string "")
2380 (user-error "Empty search string")))
2381
2382(defun company-search-repeat-forward ()
2383 "Repeat the incremental search in completion candidates forward."
2384 (interactive)
2385 (company--search-assert-input)
2386 (let* ((selection (or company-selection 0))
2387 (pos (company--search company-search-string
2388 (cdr (nthcdr selection company-candidates)))))
2389 (if (null pos)
2390 (ding)
2391 (company-set-selection (+ selection pos 1) t))))
2392
2393(defun company-search-repeat-backward ()
2394 "Repeat the incremental search in completion candidates backwards."
2395 (interactive)
2396 (company--search-assert-input)
2397 (let* ((selection (or company-selection 0))
2398 (pos (company--search company-search-string
2399 (nthcdr (- company-candidates-length
2400 selection)
2401 (reverse company-candidates)))))
2402 (if (null pos)
2403 (ding)
2404 (company-set-selection (- selection pos 1) t))))
2405
2406(defun company-search-toggle-filtering ()
2407 "Toggle `company-search-filtering'."
2408 (interactive)
2409 (company--search-assert-enabled)
2410 (setq company-search-filtering (not company-search-filtering))
2411 (let ((ss company-search-string))
2412 (company--search-update-predicate ss)
2413 (company--search-update-string ss)))
2414
2415(defun company-search-abort ()
2416 "Abort searching the completion candidates."
2417 (interactive)
2418 (company--search-assert-enabled)
2419 (company-search-mode 0)
2420 (company-set-selection company--search-old-selection t)
2421 (setq company-selection-changed company--search-old-changed))
2422
2423(defun company-search-other-char ()
2424 (interactive)
2425 (company--search-assert-enabled)
2426 (company-search-mode 0)
2427 (company--unread-this-command-keys))
2428
2429(defun company-search-delete-char ()
2430 (interactive)
2431 (company--search-assert-enabled)
2432 (if (string= company-search-string "")
2433 (ding)
2434 (let ((ss (substring company-search-string 0 -1)))
2435 (when company-search-filtering
2436 (company--search-update-predicate ss))
2437 (company--search-update-string ss))))
2438
2439(defvar company-search-map
2440 (let ((i 0)
2441 (keymap (make-keymap)))
2442 (if (fboundp 'max-char)
2443 (set-char-table-range (nth 1 keymap) (cons #x100 (max-char))
2444 'company-search-printing-char)
2445 (with-no-warnings
2446 ;; obsolete in Emacs 23
2447 (let ((l (generic-character-list))
2448 (table (nth 1 keymap)))
2449 (while l
2450 (set-char-table-default table (car l) 'company-search-printing-char)
2451 (setq l (cdr l))))))
2452 (define-key keymap [t] 'company-search-other-char)
2453 (while (< i ?\s)
2454 (define-key keymap (make-string 1 i) 'company-search-other-char)
2455 (cl-incf i))
2456 (while (< i 256)
2457 (define-key keymap (vector i) 'company-search-printing-char)
2458 (cl-incf i))
2459 (dotimes (i 10)
2460 (define-key keymap (kbd (format "<kp-%d>" i)) 'company-search-printing-char))
2461 (let ((meta-map (make-sparse-keymap)))
2462 (define-key keymap (char-to-string meta-prefix-char) meta-map)
2463 (define-key keymap [escape] meta-map))
2464 (define-key keymap (vector meta-prefix-char t) 'company-search-other-char)
2465 (define-key keymap (kbd "C-n") 'company-select-next-or-abort)
2466 (define-key keymap (kbd "C-p") 'company-select-previous-or-abort)
2467 (define-key keymap (kbd "M-n") 'company--select-next-and-warn)
2468 (define-key keymap (kbd "M-p") 'company--select-previous-and-warn)
2469 (define-key keymap (kbd "<down>") 'company-select-next-or-abort)
2470 (define-key keymap (kbd "<up>") 'company-select-previous-or-abort)
2471 (define-key keymap "\e\e\e" 'company-search-other-char)
2472 (define-key keymap [escape escape escape] 'company-search-other-char)
2473 (define-key keymap (kbd "DEL") 'company-search-delete-char)
2474 (define-key keymap [backspace] 'company-search-delete-char)
2475 (define-key keymap "\C-g" 'company-search-abort)
2476 (define-key keymap "\C-s" 'company-search-repeat-forward)
2477 (define-key keymap "\C-r" 'company-search-repeat-backward)
2478 (define-key keymap "\C-o" 'company-search-toggle-filtering)
2479 (company-keymap--bind-quick-access keymap)
2480 keymap)
2481 "Keymap used for incrementally searching the completion candidates.")
2482
2483(define-minor-mode company-search-mode
2484 "Search mode for completion candidates.
2485Don't start this directly, use `company-search-candidates' or
2486`company-filter-candidates'."
2487 :lighter company-search-lighter
2488 (if company-search-mode
2489 (if (company-manual-begin)
2490 (progn
2491 (setq company--search-old-selection company-selection
2492 company--search-old-changed company-selection-changed)
2493 (company-call-frontends 'update)
2494 (company-enable-overriding-keymap company-search-map))
2495 (setq company-search-mode nil))
2496 (kill-local-variable 'company-search-string)
2497 (kill-local-variable 'company-search-filtering)
2498 (kill-local-variable 'company--search-old-selection)
2499 (kill-local-variable 'company--search-old-changed)
2500 (when company-backend
2501 (company--search-update-predicate "")
2502 (company-call-frontends 'update))
2503 (company-enable-overriding-keymap company-active-map)))
2504
2505(defun company--search-assert-enabled ()
2506 (company-assert-enabled)
2507 (unless company-search-mode
2508 (company-uninstall-map)
2509 (user-error "Company not in search mode")))
2510
2511(defun company-search-candidates ()
2512 "Start searching the completion candidates incrementally.
2513
2514\\<company-search-map>Search can be controlled with the commands:
2515- `company-search-repeat-forward' (\\[company-search-repeat-forward])
2516- `company-search-repeat-backward' (\\[company-search-repeat-backward])
2517- `company-search-abort' (\\[company-search-abort])
2518- `company-search-delete-char' (\\[company-search-delete-char])
2519
2520Regular characters are appended to the search string.
2521
2522Customize `company-search-regexp-function' to change how the input
2523is interpreted when searching.
2524
2525The command `company-search-toggle-filtering' (\\[company-search-toggle-filtering])
2526uses the search string to filter the completion candidates."
2527 (interactive)
2528 (company-search-mode 1))
2529
2530(defun company-filter-candidates ()
2531 "Start filtering the completion candidates incrementally.
2532This works the same way as `company-search-candidates' immediately
2533followed by `company-search-toggle-filtering'."
2534 (interactive)
2535 (company-search-mode 1)
2536 (setq company-search-filtering t))
2537
2538;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2539
2540(defun company-select-next (&optional arg)
2541 "Select the next candidate in the list.
2542
2543With ARG, move by that many elements.
2544When `company-selection-default' is nil, add a special pseudo candidates
2545meant for no selection."
2546 (interactive "p")
2547 (when (company-manual-begin)
2548 (let ((selection (+ (or arg 1)
2549 (or company-selection
2550 company-selection-default
2551 -1))))
2552 (company-set-selection selection))))
2553
2554(defun company-select-previous (&optional arg)
2555 "Select the previous candidate in the list.
2556
2557With ARG, move by that many elements."
2558 (interactive "p")
2559 (company-select-next (if arg (- arg) -1)))
2560
2561(defun company-select-next-or-abort (&optional arg)
2562 "Select the next candidate if more than one, else abort
2563and invoke the normal binding.
2564
2565With ARG, move by that many elements."
2566 (interactive "p")
2567 (if (or (not company-selection)
2568 (> company-candidates-length 1))
2569 (company-select-next arg)
2570 (company-abort)
2571 (company--unread-this-command-keys)))
2572
2573(defun company-select-previous-or-abort (&optional arg)
2574 "Select the previous candidate if more than one, else abort
2575and invoke the normal binding.
2576
2577With ARG, move by that many elements."
2578 (interactive "p")
2579 (if (> company-candidates-length 1)
2580 (company-select-previous arg)
2581 (company-abort)
2582 (company--unread-this-command-keys)))
2583
2584(defun company-select-first ()
2585 "Select the first completion candidate."
2586 (interactive)
2587 (company-set-selection 0))
2588
2589(defun company-select-last ()
2590 "Select the last completion candidate."
2591 (interactive)
2592 (company-set-selection (1- company-candidates-length)))
2593
2594(defun company-next-page ()
2595 "Select the candidate one page further."
2596 (interactive)
2597 (when (company-manual-begin)
2598 (if (and company-selection-wrap-around
2599 (= company-selection (1- company-candidates-length)))
2600 (company-set-selection 0)
2601 (let (company-selection-wrap-around)
2602 (company-set-selection (+ company-selection
2603 company-tooltip-limit))))))
2604
2605(defun company-previous-page ()
2606 "Select the candidate one page earlier."
2607 (interactive)
2608 (when (company-manual-begin)
2609 (if (and company-selection-wrap-around
2610 (zerop company-selection))
2611 (company-set-selection (1- company-candidates-length))
2612 (let (company-selection-wrap-around)
2613 (company-set-selection (- company-selection
2614 company-tooltip-limit))))))
2615
2616(defun company--event-col-row (event)
2617 (company--posn-col-row (event-start event)))
2618
2619(defvar company-mouse-event nil
2620 "Holds the mouse event from `company-select-mouse'.
2621For use in the `select-mouse' frontend action. `let'-bound.")
2622
2623(defun company-select-mouse (event)
2624 "Select the candidate picked by the mouse."
2625 (interactive "e")
2626 (or (let ((company-mouse-event event))
2627 (cl-some #'identity (company-call-frontends 'select-mouse)))
2628 (progn
2629 (company-abort)
2630 (company--unread-this-command-keys)
2631 nil)))
2632
2633(defun company-complete-mouse (event)
2634 "Insert the candidate picked by the mouse."
2635 (interactive "e")
2636 (when (company-select-mouse event)
2637 (company-complete-selection)))
2638
2639(defun company-complete-selection ()
2640 "Insert the selected candidate."
2641 (interactive)
2642 (when (and (company-manual-begin) company-selection)
2643 (let ((result (nth company-selection company-candidates)))
2644 (company-finish result))))
2645
2646(defun company-complete-common ()
2647 "Insert the common part of all candidates."
2648 (interactive)
2649 (when (company-manual-begin)
2650 (if (and (not (cdr company-candidates))
2651 (equal company-common (car company-candidates)))
2652 (company-complete-selection)
2653 (company--insert-candidate company-common))))
2654
2655(defun company-complete-common-or-cycle (&optional arg)
2656 "Insert the common part of all candidates, or select the next one.
2657
2658With ARG, move by that many elements."
2659 (interactive "p")
2660 (when (company-manual-begin)
2661 (let ((tick (buffer-chars-modified-tick)))
2662 (call-interactively 'company-complete-common)
2663 (when (eq tick (buffer-chars-modified-tick))
2664 (let ((company-selection-wrap-around t)
2665 (current-prefix-arg arg))
2666 (call-interactively 'company-select-next))))))
2667
2668(defun company-complete-common-or-show-delayed-tooltip ()
2669 "Insert the common part of all candidates, or show a tooltip."
2670 (interactive)
2671 (when (company-manual-begin)
2672 (let ((tick (buffer-chars-modified-tick)))
2673 (call-interactively 'company-complete-common)
2674 (when (eq tick (buffer-chars-modified-tick))
2675 (let ((company-tooltip-idle-delay 0.0))
2676 (company-complete)
2677 (and company-candidates
2678 (company-call-frontends 'post-command)))))))
2679
2680(defun company-indent-or-complete-common (arg)
2681 "Indent the current line or region, or complete the common part."
2682 (interactive "P")
2683 (cond
2684 ((use-region-p)
2685 (indent-region (region-beginning) (region-end)))
2686 ((memq indent-line-function
2687 '(indent-relative indent-relative-maybe))
2688 (company-complete-common))
2689 ((let ((old-point (point))
2690 (old-tick (buffer-chars-modified-tick))
2691 (tab-always-indent t))
2692 (indent-for-tab-command arg)
2693 (when (and (eq old-point (point))
2694 (eq old-tick (buffer-chars-modified-tick)))
2695 (company-complete-common))))))
2696
2697(defun company-select-next-if-tooltip-visible-or-complete-selection ()
2698 "Insert selection if appropriate, or select the next candidate.
2699Insert selection if only preview is showing or only one candidate,
2700otherwise select the next candidate."
2701 (interactive)
2702 (if (and (company-tooltip-visible-p) (> company-candidates-length 1))
2703 (call-interactively 'company-select-next)
2704 (call-interactively 'company-complete-selection)))
2705
2706;;;###autoload
2707(defun company-complete ()
2708 "Insert the common part of all candidates or the current selection.
2709The first time this is called, the common part is inserted, the second
2710time, or when the selection has been changed, the selected candidate is
2711inserted."
2712 (interactive)
2713 (when (company-manual-begin)
2714 (if (or company-selection-changed
2715 (and (eq real-last-command 'company-complete)
2716 (eq last-command 'company-complete-common)))
2717 (call-interactively 'company-complete-selection)
2718 (call-interactively 'company-complete-common)
2719 (when company-candidates
2720 (setq this-command 'company-complete-common)))))
2721
2722(define-obsolete-function-alias
2723 'company-complete-number
2724 'company-complete-tooltip-row
2725 "0.9.14")
2726
2727(defun company-complete-tooltip-row (number)
2728 "Insert a candidate visible on the tooltip's row NUMBER.
2729
2730Inserts one of the first ten candidates,
2731numbered according to the current scrolling position starting with 1.
2732
2733When called interactively, uses the last typed digit, stripping the
2734modifiers and translating 0 into 10, so `M-1' inserts the first visible
2735candidate, and `M-0' insert to 10th one.
2736
2737To show hint numbers beside the candidates, enable `company-show-quick-access'."
2738 (interactive
2739 (list (let* ((type (event-basic-type last-command-event))
2740 (char (if (characterp type)
2741 ;; Number on the main row.
2742 type
2743 ;; Keypad number, if bound directly.
2744 (car (last (string-to-list (symbol-name type))))))
2745 (number (- char ?0)))
2746 (if (zerop number) 10 number))))
2747 (company--complete-nth (1- number)))
2748
2749(defun company-complete-quick-access (row)
2750 "Insert a candidate visible on a ROW matched by a quick-access key binding.
2751See `company-quick-access-keys' for more details."
2752 (interactive
2753 (list (let* ((event-type (event-basic-type last-command-event))
2754 (event-string (if (characterp event-type)
2755 (string event-type)
2756 (error "Unexpected input"))))
2757 (cl-position event-string company-quick-access-keys :test 'equal))))
2758 (when row
2759 (company--complete-nth row)))
2760
2761(defvar-local company-tooltip-offset 0
2762 "Current scrolling state of the tooltip.
2763Represented by the index of the first visible completion candidate
2764from the candidates list.")
2765
2766(defun company--complete-nth (row)
2767 "Insert a candidate visible on the tooltip's zero-based ROW."
2768 (when (company-manual-begin)
2769 (and (or (< row 0) (>= row (- company-candidates-length
2770 company-tooltip-offset)))
2771 (user-error "No candidate on the row number %d" row))
2772 (company-finish (nth (+ row company-tooltip-offset)
2773 company-candidates))))
2774
2775;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2776
2777(defconst company-space-strings-limit 100)
2778
2779(defconst company-space-strings
2780 (let (lst)
2781 (dotimes (i company-space-strings-limit)
2782 (push (make-string (- company-space-strings-limit 1 i) ?\ ) lst))
2783 (apply 'vector lst)))
2784
2785(defun company-space-string (len)
2786 (if (< len company-space-strings-limit)
2787 (aref company-space-strings len)
2788 (make-string len ?\ )))
2789
2790(defun company-safe-substring (str from &optional to)
2791 (let ((bis buffer-invisibility-spec))
2792 (if (> from (string-width str))
2793 ""
2794 (with-temp-buffer
2795 (setq buffer-invisibility-spec bis)
2796 (insert str)
2797 (move-to-column from)
2798 (let ((beg (point)))
2799 (if to
2800 (progn
2801 (move-to-column to)
2802 (concat (buffer-substring beg (point))
2803 (let ((padding (- to (current-column))))
2804 (when (> padding 0)
2805 (company-space-string padding)))))
2806 (buffer-substring beg (point-max))))))))
2807
2808;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2809
2810(defvar-local company-last-metadata nil)
2811
2812(defun company-fetch-metadata ()
2813 (let ((selected (nth (or company-selection 0) company-candidates)))
2814 (unless (eq selected (car company-last-metadata))
2815 (setq company-last-metadata
2816 (cons selected (company-call-backend 'meta selected))))
2817 (cdr company-last-metadata)))
2818
2819(defun company-doc-buffer (&optional string)
2820 (with-current-buffer (get-buffer-create "*company-documentation*")
2821 (erase-buffer)
2822 (fundamental-mode)
2823 (when string
2824 (save-excursion
2825 (insert string)
2826 (visual-line-mode)))
2827 (current-buffer)))
2828
2829(defvar company--electric-saved-window-configuration nil)
2830
2831(defvar company--electric-commands
2832 '(scroll-other-window scroll-other-window-down mwheel-scroll)
2833 "List of Commands that won't break out of electric commands.")
2834
2835(defun company--electric-restore-window-configuration ()
2836 "Restore window configuration (after electric commands)."
2837 (when (and company--electric-saved-window-configuration
2838 (not (memq this-command company--electric-commands)))
2839 (set-window-configuration company--electric-saved-window-configuration)
2840 (setq company--electric-saved-window-configuration nil)))
2841
2842(defmacro company--electric-do (&rest body)
2843 (declare (indent 0) (debug t))
2844 `(when (company-manual-begin)
2845 (cl-assert (null company--electric-saved-window-configuration))
2846 (setq company--electric-saved-window-configuration (current-window-configuration))
2847 (let ((height (window-height))
2848 (row (company--row)))
2849 ,@body
2850 (and (< (window-height) height)
2851 (< (- (window-height) row 2) company-tooltip-limit)
2852 (recenter (- (window-height) row 2))))))
2853
2854(defun company--unread-this-command-keys ()
2855 (when (> (length (this-command-keys)) 0)
2856 (setq unread-command-events (nconc
2857 (listify-key-sequence (this-command-keys))
2858 unread-command-events))
2859 (clear-this-command-keys t)))
2860
2861(defun company--show-doc-buffer ()
2862 "Show the documentation buffer for the selection."
2863 (let ((other-window-scroll-buffer)
2864 (selection (or company-selection 0)))
2865 (let* ((selected (nth selection company-candidates))
2866 (doc-buffer (or (company-call-backend 'doc-buffer selected)
2867 (user-error "No documentation available")))
2868 start)
2869 (when (consp doc-buffer)
2870 (setq start (cdr doc-buffer)
2871 doc-buffer (car doc-buffer)))
2872 (setq other-window-scroll-buffer (get-buffer doc-buffer))
2873 (let ((win (display-buffer doc-buffer t)))
2874 (set-window-start win (if start start (point-min)))))))
2875
2876(defun company-show-doc-buffer (&optional toggle-auto-update)
2877 "Show the documentation buffer for the selection.
2878With a prefix argument TOGGLE-AUTO-UPDATE, toggle the value of
2879`company-auto-update-doc'. When `company-auto-update-doc' is non-nil,
2880automatically show the documentation buffer for each selection."
2881 (interactive "P")
2882 (when toggle-auto-update
2883 (setq company-auto-update-doc (not company-auto-update-doc)))
2884 (company--electric-do
2885 (company--show-doc-buffer)))
2886(put 'company-show-doc-buffer 'company-keep t)
2887
2888(defun company-show-location ()
2889 "Temporarily display a buffer showing the selected candidate in context."
2890 (interactive)
2891 (let (other-window-scroll-buffer)
2892 (company--electric-do
2893 (let* ((selected (nth company-selection company-candidates))
2894 (location (company-call-backend 'location selected))
2895 (pos (or (cdr location) (user-error "No location available")))
2896 (buffer (or (and (bufferp (car location)) (car location))
2897 (find-file-noselect (car location) t))))
2898 (setq other-window-scroll-buffer (get-buffer buffer))
2899 (with-selected-window (display-buffer buffer t)
2900 (save-restriction
2901 (widen)
2902 (if (bufferp (car location))
2903 (goto-char pos)
2904 (goto-char (point-min))
2905 (forward-line (1- pos))))
2906 (set-window-start nil (point)))))))
2907(put 'company-show-location 'company-keep t)
2908
2909;;; package functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2910
2911(defvar-local company-callback nil)
2912
2913(defun company-remove-callback (&optional _ignored)
2914 (remove-hook 'company-completion-finished-hook company-callback t)
2915 (remove-hook 'company-completion-cancelled-hook 'company-remove-callback t)
2916 (remove-hook 'company-completion-finished-hook 'company-remove-callback t))
2917
2918(defun company-begin-backend (backend &optional callback)
2919 "Start a completion at point using BACKEND."
2920 (interactive (let ((val (completing-read "Company backend: "
2921 obarray
2922 'functionp nil "company-")))
2923 (when val
2924 (list (intern val)))))
2925 (when (setq company-callback callback)
2926 (add-hook 'company-completion-finished-hook company-callback nil t))
2927 (add-hook 'company-completion-cancelled-hook 'company-remove-callback nil t)
2928 (add-hook 'company-completion-finished-hook 'company-remove-callback nil t)
2929 (setq company-backend backend)
2930 ;; Return non-nil if active.
2931 (or (company-manual-begin)
2932 (user-error "Cannot complete at point")))
2933
2934(defun company-begin-with (candidates
2935 &optional prefix-length require-match callback)
2936 "Start a completion at point.
2937CANDIDATES is the list of candidates to use and PREFIX-LENGTH is the length
2938of the prefix that already is in the buffer before point.
2939It defaults to 0.
2940
2941CALLBACK is a function called with the selected result if the user
2942successfully completes the input.
2943
2944Example: \(company-begin-with \\='\(\"foo\" \"foobar\" \"foobarbaz\"\)\)"
2945 (let ((begin-marker (copy-marker (point) t)))
2946 (company-begin-backend
2947 (lambda (command &optional arg &rest _ignored)
2948 (pcase command
2949 (`prefix
2950 (when (equal (point) (marker-position begin-marker))
2951 (buffer-substring (- (point) (or prefix-length 0)) (point))))
2952 (`candidates
2953 (all-completions arg candidates))
2954 (`require-match
2955 require-match)))
2956 callback)))
2957
2958(declare-function find-library-name "find-func")
2959(declare-function lm-version "lisp-mnt")
2960
2961(defun company-version (&optional show-version)
2962 "Get the Company version as string.
2963
2964If SHOW-VERSION is non-nil, show the version in the echo area."
2965 (interactive (list t))
2966 (with-temp-buffer
2967 (require 'find-func)
2968 (insert-file-contents (find-library-name "company"))
2969 (require 'lisp-mnt)
2970 (if show-version
2971 (message "Company version: %s" (lm-version))
2972 (lm-version))))
2973
2974(defun company-diag ()
2975 "Pop a buffer with information about completions at point."
2976 (interactive)
2977 (let* ((bb company-backends)
2978 (mode (symbol-name major-mode))
2979 backend
2980 (prefix (cl-loop for b in bb
2981 thereis (let ((company-backend b))
2982 (setq backend b)
2983 (company-call-backend 'prefix))))
2984 (c-a-p-f completion-at-point-functions)
2985 cc annotations)
2986 (when (or (stringp prefix) (consp prefix))
2987 (let ((company-backend backend))
2988 (condition-case nil
2989 (setq cc (company-call-backend 'candidates (company--prefix-str prefix))
2990 annotations
2991 (mapcar
2992 (lambda (c) (cons c (company-call-backend 'annotation c)))
2993 cc))
2994 (error (setq annotations 'error)))))
2995 (pop-to-buffer (get-buffer-create "*company-diag*"))
2996 (setq buffer-read-only nil)
2997 (erase-buffer)
2998 (insert (format "Emacs %s (%s) of %s on %s"
2999 emacs-version system-configuration
3000 (format-time-string "%Y-%m-%d" emacs-build-time)
3001 emacs-build-system))
3002 (insert "\nCompany " (company-version) "\n\n")
3003 (insert "company-backends: " (pp-to-string bb))
3004 (insert "\n")
3005 (insert "Used backend: " (pp-to-string backend))
3006 (insert "\n")
3007 (when (if (listp backend)
3008 (memq 'company-capf backend)
3009 (eq backend 'company-capf))
3010 (insert "Value of c-a-p-f: "
3011 (pp-to-string c-a-p-f)))
3012 (insert "Major mode: " mode)
3013 (insert "\n")
3014 (insert "Prefix: " (pp-to-string prefix))
3015 (insert "\n")
3016 (insert "Completions:")
3017 (unless cc (insert " none"))
3018 (if (eq annotations 'error)
3019 (insert "(error fetching)")
3020 (save-excursion
3021 (dolist (c annotations)
3022 (insert "\n " (prin1-to-string (car c)))
3023 (when (cdr c)
3024 (insert " " (prin1-to-string (cdr c)))))))
3025 (special-mode)))
3026
3027;;; pseudo-tooltip ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3028
3029(defvar-local company--tooltip-current-width 0)
3030
3031(defun company-tooltip--lines-update-offset (selection num-lines limit)
3032 (cl-decf limit 2)
3033 (setq company-tooltip-offset
3034 (max (min selection company-tooltip-offset)
3035 (- selection -1 limit)))
3036
3037 (when (<= company-tooltip-offset 1)
3038 (cl-incf limit)
3039 (setq company-tooltip-offset 0))
3040
3041 (when (>= company-tooltip-offset (- num-lines limit 1))
3042 (cl-incf limit)
3043 (when (= selection (1- num-lines))
3044 (cl-decf company-tooltip-offset)
3045 (when (<= company-tooltip-offset 1)
3046 (setq company-tooltip-offset 0)
3047 (cl-incf limit))))
3048
3049 limit)
3050
3051(defun company-tooltip--simple-update-offset (selection _num-lines limit)
3052 (setq company-tooltip-offset
3053 (if (< selection company-tooltip-offset)
3054 selection
3055 (max company-tooltip-offset
3056 (- selection limit -1)))))
3057
3058;;; propertize
3059
3060(defun company-round-tab (arg)
3061 (* (/ (+ arg tab-width) tab-width) tab-width))
3062
3063(defun company-plainify (str)
3064 (let ((prefix (get-text-property 0 'line-prefix str)))
3065 (when prefix ; Keep the original value unmodified, for no special reason.
3066 (setq str (concat prefix str))
3067 (remove-text-properties 0 (length str) '(line-prefix) str)))
3068 (let* ((pieces (split-string str "\t"))
3069 (copy pieces))
3070 (while (cdr copy)
3071 (setcar copy (company-safe-substring
3072 (car copy) 0 (company-round-tab (string-width (car copy)))))
3073 (pop copy))
3074 (apply 'concat pieces)))
3075
3076(defun company--common-or-matches (value)
3077 (let ((matches (company-call-backend 'match value)))
3078 (when (and matches
3079 company-common
3080 (listp matches)
3081 (= 1 (length matches))
3082 (= 0 (caar matches))
3083 (> (length company-common) (cdar matches)))
3084 (setq matches nil))
3085 (when (integerp matches)
3086 (setq matches `((0 . ,matches))))
3087 (or matches
3088 (and company-common `((0 . ,(length company-common))))
3089 nil)))
3090
3091(defun company-fill-propertize (value annotation width selected left right)
3092 (let* ((margin (length left))
3093 (company-common (and company-common (company--clean-string company-common)))
3094 (common (company--common-or-matches value))
3095 (_ (setq value (company-reformat (company--pre-render value))
3096 annotation (and annotation (company--pre-render annotation t))))
3097 (ann-ralign company-tooltip-align-annotations)
3098 (ann-padding (or company-tooltip-annotation-padding 0))
3099 (ann-truncate (< width
3100 (+ (length value) (length annotation)
3101 ann-padding)))
3102 (ann-start (+ margin
3103 (if ann-ralign
3104 (if ann-truncate
3105 (+ (length value) ann-padding)
3106 (- width (length annotation)))
3107 (+ (length value) ann-padding))))
3108 (ann-end (min (+ ann-start (length annotation)) (+ margin width)))
3109 (line (concat left
3110 (if (or ann-truncate (not ann-ralign))
3111 (company-safe-substring
3112 (concat value
3113 (when annotation
3114 (company-space-string ann-padding))
3115 annotation)
3116 0 width)
3117 (concat
3118 (company-safe-substring value 0
3119 (- width (length annotation)))
3120 annotation))
3121 right)))
3122 (setq width (+ width margin (length right)))
3123
3124 (font-lock-append-text-property 0 width 'mouse-face
3125 'company-tooltip-mouse
3126 line)
3127 (when (< ann-start ann-end)
3128 (add-face-text-property ann-start ann-end
3129 (if selected
3130 'company-tooltip-annotation-selection
3131 'company-tooltip-annotation)
3132 t line))
3133 (cl-loop
3134 with width = (- width (length right))
3135 for (comp-beg . comp-end) in common
3136 for inline-beg = (+ margin comp-beg)
3137 for inline-end = (min (+ margin comp-end) width)
3138 when (< inline-beg width)
3139 do (add-face-text-property inline-beg inline-end
3140 (if selected
3141 'company-tooltip-common-selection
3142 'company-tooltip-common)
3143 nil line))
3144 (when (let ((re (funcall company-search-regexp-function
3145 company-search-string)))
3146 (and (not (string= re ""))
3147 (string-match re value)))
3148 (pcase-dolist (`(,mbeg . ,mend) (company--search-chunks))
3149 (let ((beg (+ margin mbeg))
3150 (end (+ margin mend))
3151 (width (- width (length right))))
3152 (when (< beg width)
3153 (add-face-text-property beg (min end width)
3154 (if selected
3155 'company-tooltip-search-selection
3156 'company-tooltip-search)
3157 nil line)))))
3158 (when selected
3159 (add-face-text-property 0 width 'company-tooltip-selection t line))
3160
3161 (when (company-call-backend 'deprecated value)
3162 (add-face-text-property margin
3163 (min
3164 (+ margin (length value))
3165 (- width (length right)))
3166 'company-tooltip-deprecated t line))
3167
3168 (add-face-text-property 0 width 'company-tooltip t line)
3169 line))
3170
3171(defun company--search-chunks ()
3172 (let ((md (match-data t))
3173 res)
3174 (if (<= (length md) 2)
3175 (push (cons (nth 0 md) (nth 1 md)) res)
3176 (while (setq md (nthcdr 2 md))
3177 (when (car md)
3178 (push (cons (car md) (cadr md)) res))))
3179 res))
3180
3181(defun company--pre-render (str &optional annotation-p)
3182 (or (company-call-backend 'pre-render str annotation-p)
3183 (progn
3184 (when (or (text-property-not-all 0 (length str) 'face nil str)
3185 (text-property-not-all 0 (length str) 'mouse-face nil str))
3186 (setq str (copy-sequence str))
3187 (remove-text-properties 0 (length str)
3188 '(face nil font-lock-face nil mouse-face nil)
3189 str))
3190 str)))
3191
3192(defun company--clean-string (str)
3193 (replace-regexp-in-string
3194 "\\([^[:graph:] ]\\)\\|\\(\ufeff\\)\\|[[:multibyte:]]"
3195 (lambda (match)
3196 (cond
3197 ((match-beginning 1)
3198 ;; FIXME: Better char for 'non-printable'?
3199 ;; We shouldn't get any of these, but sometimes we might.
3200 ;; The official "replacement character" is not supported by some fonts.
3201 ;;"\ufffd"
3202 "?"
3203 )
3204 ((match-beginning 2)
3205 ;; Zero-width non-breakable space.
3206 "")
3207 ((> (string-width match) 1)
3208 (concat
3209 (make-string (1- (string-width match)) ?\ufeff)
3210 match))
3211 (t match)))
3212 str))
3213
3214;;; replace
3215
3216(defun company-buffer-lines (beg end)
3217 (goto-char beg)
3218 (let (lines lines-moved)
3219 (while (and (not (eobp)) ; http://debbugs.gnu.org/19553
3220 (> (setq lines-moved (vertical-motion 1)) 0)
3221 (<= (point) end))
3222 (let ((bound (min end (point))))
3223 ;; A visual line can contain several physical lines (e.g. with outline's
3224 ;; folding overlay). Take only the first one.
3225 (push (buffer-substring beg
3226 (save-excursion
3227 (goto-char beg)
3228 (re-search-forward "$" bound 'move)
3229 (point)))
3230 lines))
3231 ;; One physical line can be displayed as several visual ones as well:
3232 ;; add empty strings to the list, to even the count.
3233 (dotimes (_ (1- lines-moved))
3234 (push "" lines))
3235 (setq beg (point)))
3236 (unless (eq beg end)
3237 (push (buffer-substring beg end) lines))
3238 (nreverse lines)))
3239
3240(defun company-modify-line (old new offset)
3241 (concat (company-safe-substring old 0 offset)
3242 new
3243 (company-safe-substring old (+ offset (length new)))))
3244
3245(defun company--show-numbers (numbered)
3246 (format " %s" (if (<= numbered 10)
3247 (mod numbered 10)
3248 " ")))
3249(make-obsolete
3250 'company--show-numbers
3251 "use `company-quick-access-hint-key' instead,
3252but adjust the expected values appropriately."
3253 "0.9.14")
3254
3255(defsubst company--window-height ()
3256 (if (fboundp 'window-screen-lines)
3257 (floor (window-screen-lines))
3258 (window-body-height)))
3259
3260(defun company--window-width ()
3261 (let ((ww (window-body-width)))
3262 ;; Account for the line continuation column.
3263 (when (zerop (cadr (window-fringes)))
3264 (cl-decf ww))
3265 (when (bound-and-true-p display-line-numbers)
3266 (cl-decf ww (+ 2 (line-number-display-width))))
3267 ;; whitespace-mode with newline-mark
3268 (when (and buffer-display-table
3269 (aref buffer-display-table ?\n))
3270 (cl-decf ww (1- (length (aref buffer-display-table ?\n)))))
3271 ww))
3272
3273(defun company--face-attribute (face attr)
3274 ;; Like `face-attribute', but accounts for faces that have been remapped to
3275 ;; another face, a list of faces, or a face spec.
3276 (cond ((null face) nil)
3277 ((symbolp face)
3278 (let ((remap (cdr (assq face face-remapping-alist))))
3279 (if remap
3280 (company--face-attribute
3281 ;; Faces can be remapped to their unremapped selves, but that
3282 ;; would cause us infinite recursion.
3283 (if (listp remap) (remq face remap) remap)
3284 attr)
3285 (face-attribute face attr nil t))))
3286 ((keywordp (car-safe face))
3287 (or (plist-get face attr)
3288 (company--face-attribute (plist-get face :inherit) attr)))
3289 ((listp face)
3290 (cl-find-if #'stringp
3291 (mapcar (lambda (f) (company--face-attribute f attr))
3292 face)))))
3293
3294(defun company--replacement-string (lines column-offset old column nl &optional align-top)
3295 (cl-decf column column-offset)
3296
3297 (when (< column 0) (setq column 0))
3298
3299 (when (and align-top company-tooltip-flip-when-above)
3300 (setq lines (reverse lines)))
3301
3302 (let ((width (length (car lines)))
3303 (remaining-cols (- (+ (company--window-width) (window-hscroll))
3304 column)))
3305 (when (> width remaining-cols)
3306 (cl-decf column (- width remaining-cols))))
3307
3308 (let (new)
3309 (when align-top
3310 ;; untouched lines first
3311 (dotimes (_ (- (length old) (length lines)))
3312 (push (pop old) new)))
3313 ;; length into old lines.
3314 (while old
3315 (push (company-modify-line (pop old) (pop lines) column)
3316 new))
3317 ;; Append whole new lines.
3318 (while lines
3319 (push (concat (company-space-string column) (pop lines))
3320 new))
3321
3322 ;; XXX: Also see branch 'more-precise-extend'.
3323 (let* ((nl-face `(,@(when (version<= "27" emacs-version)
3324 '(:extend t))
3325 :inverse-video nil
3326 :background ,(or (company--face-attribute 'default :background)
3327 (face-attribute 'default :background nil t))))
3328 (str (apply #'concat
3329 (when nl " \n")
3330 (cl-mapcan
3331 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=42552#23
3332 (lambda (line) (list line (propertize "\n" 'face nl-face)))
3333 (nreverse new)))))
3334 ;; https://debbugs.gnu.org/38563
3335 (add-face-text-property 0 (length str) 'default t str)
3336 (when nl (put-text-property 0 1 'cursor t str))
3337 str)))
3338
3339(defun company--create-lines (selection limit)
3340 (let ((len company-candidates-length)
3341 (window-width (company--window-width))
3342 (company-tooltip-annotation-padding
3343 (or company-tooltip-annotation-padding
3344 (if company-tooltip-align-annotations 1 0)))
3345 left-margins
3346 left-margin-size
3347 lines
3348 width
3349 lines-copy
3350 items
3351 previous
3352 remainder
3353 scrollbar-bounds)
3354
3355 ;; Maybe clear old offset.
3356 (when (< len (+ company-tooltip-offset limit))
3357 (setq company-tooltip-offset 0))
3358
3359 (let ((selection (or selection 0)))
3360 ;; Scroll to offset.
3361 (if (eq company-tooltip-offset-display 'lines)
3362 (setq limit (company-tooltip--lines-update-offset selection len limit))
3363 (company-tooltip--simple-update-offset selection len limit))
3364
3365 (cond
3366 ((eq company-tooltip-offset-display 'scrollbar)
3367 (setq scrollbar-bounds (company--scrollbar-bounds company-tooltip-offset
3368 limit len)))
3369 ((eq company-tooltip-offset-display 'lines)
3370 (when (> company-tooltip-offset 0)
3371 (setq previous (format "...(%d)" company-tooltip-offset)))
3372 (setq remainder (- len limit company-tooltip-offset)
3373 remainder (when (> remainder 0)
3374 (setq remainder (format "...(%d)" remainder)))))))
3375
3376 (when selection
3377 (cl-decf selection company-tooltip-offset))
3378
3379 (setq width (max (length previous) (length remainder))
3380 lines (nthcdr company-tooltip-offset company-candidates)
3381 len (min limit len)
3382 lines-copy lines)
3383
3384 (when scrollbar-bounds (cl-decf window-width))
3385
3386 (when company-format-margin-function
3387 (let ((lines-copy lines-copy)
3388 res)
3389 (dotimes (i len)
3390 (push (funcall company-format-margin-function
3391 (pop lines-copy)
3392 (equal selection i))
3393 res))
3394 (setq left-margins (nreverse res))))
3395
3396 ;; XXX: format-function outputting shorter strings than the
3397 ;; default margin is not supported (yet?).
3398 (setq left-margin-size (apply #'max company-tooltip-margin
3399 (mapcar #'length left-margins)))
3400
3401 (cl-decf window-width company-tooltip-margin)
3402 (cl-decf window-width left-margin-size)
3403
3404 (dotimes (_ len)
3405 (let* ((value (pop lines-copy))
3406 (annotation (company-call-backend 'annotation value))
3407 (left (or (pop left-margins)
3408 (company-space-string left-margin-size))))
3409 (setq value (company--clean-string value))
3410 (when annotation
3411 (setq annotation (company--clean-string annotation))
3412 (when company-tooltip-align-annotations
3413 ;; `lisp-completion-at-point' adds a space.
3414 (setq annotation (string-trim-left annotation))))
3415 (push (list value annotation left) items)
3416 (setq width (max (+ (length value)
3417 (if annotation
3418 (+ (length annotation)
3419 company-tooltip-annotation-padding)
3420 (length annotation)))
3421 width))))
3422
3423 (setq width (min window-width
3424 company-tooltip-maximum-width
3425 (max company-tooltip-minimum-width
3426 (if company-show-quick-access
3427 (+ 2 width)
3428 width))))
3429
3430 (when company-tooltip-width-grow-only
3431 (setq width (max company--tooltip-current-width width))
3432 (setq company--tooltip-current-width width))
3433
3434 (let ((items (nreverse items))
3435 (row (if company-show-quick-access 0 99999))
3436 new)
3437 (when previous
3438 (push (company--scrollpos-line previous width left-margin-size) new))
3439
3440 (dotimes (i len)
3441 (let* ((item (pop items))
3442 (str (car item))
3443 (annotation (cadr item))
3444 (left (nth 2 item))
3445 (right (company-space-string company-tooltip-margin))
3446 (width width)
3447 (selected (equal selection i)))
3448 (when company-show-quick-access
3449 (let ((quick-access (gv-ref (if (eq company-show-quick-access 'left)
3450 left right)))
3451 (qa-hint (company-tooltip--format-quick-access-hint
3452 row selected)))
3453 (cl-decf width (string-width qa-hint))
3454 (setf (gv-deref quick-access)
3455 (concat qa-hint (gv-deref quick-access))))
3456 (cl-incf row))
3457 (push (concat
3458 (company-fill-propertize str annotation
3459 width selected
3460 left
3461 right)
3462 (when scrollbar-bounds
3463 (company--scrollbar i scrollbar-bounds)))
3464 new)))
3465
3466 (when remainder
3467 (push (company--scrollpos-line remainder width left-margin-size) new))
3468
3469 (cons
3470 left-margin-size
3471 (nreverse new)))))
3472
3473(defun company--scrollbar-bounds (offset limit length)
3474 (when (> length limit)
3475 (let* ((size (ceiling (* limit (float limit)) length))
3476 (lower (floor (* limit (float offset)) length))
3477 (upper (+ lower size -1)))
3478 (cons lower upper))))
3479
3480(defun company--scrollbar (i bounds)
3481 (propertize " " 'face
3482 (if (and (>= i (car bounds)) (<= i (cdr bounds)))
3483 'company-tooltip-scrollbar-thumb
3484 'company-tooltip-scrollbar-track)))
3485
3486(defun company--scrollpos-line (text width fancy-margin-width)
3487 (propertize (concat (company-space-string company-tooltip-margin)
3488 (company-safe-substring text 0 width)
3489 (company-space-string fancy-margin-width))
3490 'face 'company-tooltip))
3491
3492(defun company-tooltip--format-quick-access-hint (row selected)
3493 "Format a quick-access hint for outputting on a tooltip's ROW.
3494Value of SELECTED determines the added face."
3495 (propertize (format "%2s" (funcall company-quick-access-hint-function row))
3496 'face
3497 (if selected
3498 'company-tooltip-quick-access-selection
3499 'company-tooltip-quick-access)))
3500
3501;; show
3502
3503(defvar-local company-pseudo-tooltip-overlay nil)
3504
3505(defun company--inside-tooltip-p (event-col-row row height)
3506 (let* ((ovl company-pseudo-tooltip-overlay)
3507 (column (overlay-get ovl 'company-column))
3508 (width (overlay-get ovl 'company-width))
3509 (evt-col (car event-col-row))
3510 (evt-row (cdr event-col-row)))
3511 (and (>= evt-col column)
3512 (< evt-col (+ column width))
3513 (if (> height 0)
3514 (and (> evt-row row)
3515 (<= evt-row (+ row height) ))
3516 (and (< evt-row row)
3517 (>= evt-row (+ row height)))))))
3518
3519(defun company--pseudo-tooltip-height ()
3520 "Calculate the appropriate tooltip height.
3521Returns a negative number if the tooltip should be displayed above point."
3522 (let* ((lines (company--row))
3523 (below (- (company--window-height) 1 lines)))
3524 (if (and (< below (min company-tooltip-minimum company-candidates-length))
3525 (> lines below))
3526 (- (max 3 (min company-tooltip-limit lines)))
3527 (max 3 (min company-tooltip-limit below)))))
3528
3529(defun company-pseudo-tooltip-show (row column selection)
3530 (company-pseudo-tooltip-hide)
3531
3532 (let* ((height (company--pseudo-tooltip-height))
3533 above)
3534
3535 (when (< height 0)
3536 (setq row (+ row height -1)
3537 above t))
3538
3539 ;; This can happen in Emacs versions which allow arbitrary scrolling,
3540 ;; such as Yamamoto's Mac Port.
3541 (unless (pos-visible-in-window-p (window-start))
3542 (cl-decf row))
3543
3544 (let (nl beg end ov args)
3545 (save-excursion
3546 (setq nl (< (move-to-window-line row) row)
3547 beg (point)
3548 end (save-excursion
3549 (move-to-window-line (+ row (abs height)))
3550 (point))
3551 ov (make-overlay beg end nil t)
3552 args (list (mapcar 'company-plainify
3553 (company-buffer-lines beg end))
3554 column nl above)))
3555
3556 (setq company-pseudo-tooltip-overlay ov)
3557 (overlay-put ov 'company-replacement-args args)
3558
3559 (let* ((lines-and-offset (company--create-lines selection (abs height)))
3560 (lines (cdr lines-and-offset))
3561 (column-offset (car lines-and-offset)))
3562 (overlay-put ov 'company-display
3563 (apply 'company--replacement-string
3564 lines column-offset args))
3565 (overlay-put ov 'company-width (string-width (car lines))))
3566
3567 (overlay-put ov 'company-column column)
3568 (overlay-put ov 'company-height height))))
3569
3570(defun company-pseudo-tooltip-show-at-point (pos column-offset)
3571 (let* ((col-row (company--col-row pos))
3572 (col (- (car col-row) column-offset)))
3573 (when (< col 0) (setq col 0))
3574 (company-pseudo-tooltip-show (1+ (cdr col-row)) col company-selection)))
3575
3576(defun company-pseudo-tooltip-edit (selection)
3577 (let* ((height (overlay-get company-pseudo-tooltip-overlay 'company-height))
3578 (lines-and-offset (company--create-lines selection (abs height)))
3579 (lines (cdr lines-and-offset))
3580 (column-offset (car lines-and-offset)))
3581 (overlay-put company-pseudo-tooltip-overlay 'company-width
3582 (string-width (car lines)))
3583 (overlay-put company-pseudo-tooltip-overlay 'company-display
3584 (apply 'company--replacement-string
3585 lines column-offset
3586 (overlay-get company-pseudo-tooltip-overlay
3587 'company-replacement-args)))))
3588
3589(defun company-pseudo-tooltip-hide ()
3590 (when company-pseudo-tooltip-overlay
3591 (delete-overlay company-pseudo-tooltip-overlay)
3592 (setq company-pseudo-tooltip-overlay nil)))
3593
3594(defun company-pseudo-tooltip-hide-temporarily ()
3595 (when (overlayp company-pseudo-tooltip-overlay)
3596 (overlay-put company-pseudo-tooltip-overlay 'invisible nil)
3597 (overlay-put company-pseudo-tooltip-overlay 'line-prefix nil)
3598 (overlay-put company-pseudo-tooltip-overlay 'before-string nil)
3599 (overlay-put company-pseudo-tooltip-overlay 'display nil)
3600 (overlay-put company-pseudo-tooltip-overlay 'face nil)))
3601
3602(defun company-pseudo-tooltip-unhide ()
3603 (when company-pseudo-tooltip-overlay
3604 (let* ((ov company-pseudo-tooltip-overlay)
3605 (disp (overlay-get ov 'company-display)))
3606 ;; Beat outline's folding overlays.
3607 ;; And Flymake (53). And Flycheck (110).
3608 (overlay-put ov 'priority 111)
3609 ;; visual-line-mode
3610 (when (and (memq (char-before (overlay-start ov)) '(?\s ?\t))
3611 ;; not eob
3612 (not (nth 2 (overlay-get ov 'company-replacement-args))))
3613 (setq disp (concat "\n" disp)))
3614 ;; No (extra) prefix for the first line.
3615 (overlay-put ov 'line-prefix "")
3616 (overlay-put ov 'before-string disp)
3617 ;; `display' is better than `invisible':
3618 ;; https://debbugs.gnu.org/18285
3619 ;; https://debbugs.gnu.org/20847
3620 ;; https://debbugs.gnu.org/42521
3621 (overlay-put ov 'display "")
3622 (overlay-put ov 'window (selected-window)))))
3623
3624(defun company-pseudo-tooltip-guard ()
3625 (list
3626 (save-excursion (beginning-of-visual-line))
3627 (window-width)
3628 (let ((ov company-pseudo-tooltip-overlay)
3629 (overhang (save-excursion (end-of-visual-line)
3630 (- (line-end-position) (point)))))
3631 (when (>= (overlay-get ov 'company-height) 0)
3632 (cons
3633 (buffer-substring-no-properties (point) (overlay-start ov))
3634 (when (>= overhang 0) overhang))))))
3635
3636(defun company-pseudo-tooltip-frontend (command)
3637 "`company-mode' frontend similar to a tooltip but based on overlays."
3638 (cl-case command
3639 (pre-command (company-pseudo-tooltip-hide-temporarily))
3640 (unhide
3641 (let ((ov company-pseudo-tooltip-overlay))
3642 (when (> (overlay-get ov 'company-height) 0)
3643 ;; Sleight of hand: if the current line wraps, we adjust the
3644 ;; start of the overlay so that the popup does not zig-zag,
3645 ;; but don't update the popup's background. This seems just
3646 ;; non-annoying enough to avoid the work required for the latter.
3647 (save-excursion
3648 (vertical-motion 1)
3649 (unless (= (point) (overlay-start ov))
3650 (move-overlay ov (point) (overlay-end ov))))))
3651 (company-pseudo-tooltip-unhide))
3652 (post-command
3653 (unless (when (overlayp company-pseudo-tooltip-overlay)
3654 (let* ((ov company-pseudo-tooltip-overlay)
3655 (old-height (overlay-get ov 'company-height))
3656 (new-height (company--pseudo-tooltip-height)))
3657 (and
3658 (>= (* old-height new-height) 0)
3659 (>= (abs old-height) (abs new-height))
3660 (equal (company-pseudo-tooltip-guard)
3661 (overlay-get ov 'company-guard)))))
3662 ;; Redraw needed.
3663 (company-pseudo-tooltip-show-at-point (point) (length company-prefix))
3664 (overlay-put company-pseudo-tooltip-overlay
3665 'company-guard (company-pseudo-tooltip-guard)))
3666 (company-pseudo-tooltip-unhide))
3667 (show (setq company--tooltip-current-width 0))
3668 (hide (company-pseudo-tooltip-hide)
3669 (setq company-tooltip-offset 0))
3670 (update (when (overlayp company-pseudo-tooltip-overlay)
3671 (company-pseudo-tooltip-edit company-selection)))
3672 (select-mouse
3673 (let ((event-col-row (company--event-col-row company-mouse-event))
3674 (ovl-row (company--row))
3675 (ovl-height (and company-pseudo-tooltip-overlay
3676 (min (overlay-get company-pseudo-tooltip-overlay
3677 'company-height)
3678 company-candidates-length))))
3679 (cond ((and ovl-height
3680 (company--inside-tooltip-p event-col-row ovl-row ovl-height))
3681 (company-set-selection (+ (cdr event-col-row)
3682 (1- company-tooltip-offset)
3683 (if (and (eq company-tooltip-offset-display 'lines)
3684 (not (zerop company-tooltip-offset)))
3685 -1 0)
3686 (- ovl-row)
3687 (if (< ovl-height 0)
3688 (- 1 ovl-height)
3689 0)))
3690 t))))))
3691
3692(defun company-pseudo-tooltip-unless-just-one-frontend (command)
3693 "`company-pseudo-tooltip-frontend', but not shown for single candidates."
3694 (unless (and (memq command '(post-command unhide))
3695 (company--show-inline-p))
3696 (company-pseudo-tooltip-frontend command)))
3697
3698(defun company-pseudo-tooltip--ujofwd-on-timer (command)
3699 (when company-candidates
3700 (company-pseudo-tooltip-unless-just-one-frontend-with-delay command)))
3701
3702(defun company-pseudo-tooltip-unless-just-one-frontend-with-delay (command)
3703 "`compandy-pseudo-tooltip-frontend', but shown after a delay.
3704Delay is determined by `company-tooltip-idle-delay'."
3705 (defvar company-preview-overlay)
3706 (when (and (memq command '(pre-command hide))
3707 company-tooltip-timer)
3708 (cancel-timer company-tooltip-timer)
3709 (setq company-tooltip-timer nil))
3710 (cl-case command
3711 (post-command
3712 (if (or company-tooltip-timer
3713 (overlayp company-pseudo-tooltip-overlay))
3714 (if (not (overlayp company-preview-overlay))
3715 (company-pseudo-tooltip-unless-just-one-frontend command)
3716 (let (company-tooltip-timer)
3717 (company-call-frontends 'pre-command))
3718 (company-call-frontends 'post-command))
3719 (setq company-tooltip-timer
3720 (run-with-timer company-tooltip-idle-delay nil
3721 'company-pseudo-tooltip--ujofwd-on-timer
3722 'post-command))))
3723 (unhide
3724 (when (overlayp company-pseudo-tooltip-overlay)
3725 (company-pseudo-tooltip-unless-just-one-frontend command)))
3726 (t
3727 (company-pseudo-tooltip-unless-just-one-frontend command))))
3728
3729;;; overlay ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3730
3731(defvar-local company-preview-overlay nil)
3732
3733(defun company-preview-show-at-point (pos completion)
3734 (company-preview-hide)
3735
3736 (let* ((company-common (and company-common
3737 (string-prefix-p company-prefix company-common)
3738 company-common))
3739 (common (company--common-or-matches completion)))
3740 (setq completion (copy-sequence (company--pre-render completion)))
3741 (add-face-text-property 0 (length completion) 'company-preview
3742 nil completion)
3743
3744 (cl-loop for (beg . end) in common
3745 do (add-face-text-property beg end 'company-preview-common
3746 nil completion))
3747
3748 ;; Add search string
3749 (and (string-match (funcall company-search-regexp-function
3750 company-search-string)
3751 completion)
3752 (pcase-dolist (`(,mbeg . ,mend) (company--search-chunks))
3753 (add-face-text-property mbeg mend 'company-preview-search
3754 nil completion)))
3755
3756 (setq completion (if (string-prefix-p company-prefix completion
3757 (eq (company-call-backend 'ignore-case)
3758 'keep-prefix))
3759 (company-strip-prefix completion)
3760 completion))
3761
3762 (when (string-prefix-p "\n" completion)
3763 (setq completion (concat (propertize " " 'face 'company-preview) "\n"
3764 (substring completion 1))))
3765
3766 (and (equal pos (point))
3767 (not (equal completion ""))
3768 (add-text-properties 0 1 '(cursor 1) completion))
3769
3770 (let* ((beg pos)
3771 (pto company-pseudo-tooltip-overlay)
3772 (ptf-workaround (and
3773 pto
3774 (char-before pos)
3775 (eq pos (overlay-start pto)))))
3776 ;; Try to accommodate for the pseudo-tooltip overlay,
3777 ;; which may start at the same position if it's at eol.
3778 (when ptf-workaround
3779 (cl-decf beg)
3780 (setq completion (concat (buffer-substring beg pos) completion)))
3781
3782 (setq company-preview-overlay (make-overlay beg pos))
3783
3784 (let ((ov company-preview-overlay))
3785 (overlay-put ov (if ptf-workaround 'display 'after-string)
3786 completion)
3787 (overlay-put ov 'window (selected-window))))))
3788
3789(defun company-preview-hide ()
3790 (when company-preview-overlay
3791 (delete-overlay company-preview-overlay)
3792 (setq company-preview-overlay nil)))
3793
3794(defun company-preview-frontend (command)
3795 "`company-mode' frontend showing the selection as if it had been inserted."
3796 (pcase command
3797 (`pre-command (company-preview-hide))
3798 (`unhide
3799 (when company-selection
3800 (let* ((current (nth company-selection company-candidates))
3801 (company-prefix (if (equal current company-prefix)
3802 ;; Would be more accurate to compare lengths,
3803 ;; but this is shorter.
3804 current
3805 (buffer-substring
3806 (- company-point (length company-prefix))
3807 (point)))))
3808 (company-preview-show-at-point (point) current))))
3809 (`post-command
3810 (when company-selection
3811 (company-preview-show-at-point (point)
3812 (nth company-selection company-candidates))))
3813 (`hide (company-preview-hide))))
3814
3815(defun company-preview-if-just-one-frontend (command)
3816 "`company-preview-frontend', but only shown for single candidates."
3817 (when (or (not (memq command '(post-command unhide)))
3818 (company--show-inline-p))
3819 (company-preview-frontend command)))
3820
3821(defun company--show-inline-p ()
3822 (and (not (cdr company-candidates))
3823 company-common
3824 (not (eq t (compare-strings company-prefix nil nil
3825 (car company-candidates) nil nil
3826 t)))
3827 (or (eq (company-call-backend 'ignore-case) 'keep-prefix)
3828 (string-prefix-p company-prefix company-common))))
3829
3830(defun company-tooltip-visible-p ()
3831 "Returns whether the tooltip is visible."
3832 (when (overlayp company-pseudo-tooltip-overlay)
3833 (not (overlay-get company-pseudo-tooltip-overlay 'invisible))))
3834
3835(defun company-preview-common--show-p ()
3836 "Returns whether the preview of common can be showed or not"
3837 (and company-common
3838 (or (eq (company-call-backend 'ignore-case) 'keep-prefix)
3839 (string-prefix-p company-prefix company-common))))
3840
3841(defun company-preview-common-frontend (command)
3842 "`company-mode' frontend preview the common part of candidates."
3843 (when (or (not (memq command '(post-command unhide)))
3844 (company-preview-common--show-p))
3845 (pcase command
3846 (`pre-command (company-preview-hide))
3847 ((or 'post-command 'unhide)
3848 (company-preview-show-at-point (point) company-common))
3849 (`hide (company-preview-hide)))))
3850
3851;;; echo ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3852
3853(defvar-local company-echo-last-msg nil)
3854
3855(defvar company-echo-timer nil)
3856
3857(defvar company-echo-delay .01)
3858
3859(defcustom company-echo-truncate-lines t
3860 "Whether frontend messages written to the echo area should be truncated."
3861 :type 'boolean
3862 :package-version '(company . "0.9.3"))
3863
3864(defun company-echo-show (&optional getter)
3865 (let ((last-msg company-echo-last-msg)
3866 (message-log-max nil)
3867 (message-truncate-lines company-echo-truncate-lines))
3868 (when getter
3869 (setq company-echo-last-msg (funcall getter)))
3870 ;; Avoid modifying the echo area if we don't have anything to say, and we
3871 ;; didn't put the previous message there (thus there's nothing to clear),
3872 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=62816#20
3873 (if (not (member company-echo-last-msg '(nil "")))
3874 (message "%s" company-echo-last-msg)
3875 (unless (member last-msg '(nil ""))
3876 (message "")))))
3877
3878(defun company-echo-show-soon (&optional getter delay)
3879 (company-echo-cancel)
3880 (setq company-echo-timer (run-with-timer (or delay company-echo-delay)
3881 nil
3882 'company-echo-show getter)))
3883
3884(defun company-echo-cancel (&optional unset)
3885 (when company-echo-timer
3886 (cancel-timer company-echo-timer))
3887 (when unset
3888 (setq company-echo-timer nil)))
3889
3890(defun company-echo-format ()
3891 (let ((selection (or company-selection 0)))
3892 (let ((limit (window-body-width (minibuffer-window)))
3893 (len -1)
3894 (candidates (nthcdr selection company-candidates))
3895 (numbered (if company-show-quick-access selection 99999))
3896 (qa-keys-len (length company-quick-access-keys))
3897 comp msg)
3898
3899 (while candidates
3900 (setq comp (propertize
3901 (company-reformat (company--clean-string (pop candidates)))
3902 'face
3903 'company-echo)
3904 len (+ len 1 (length comp)))
3905 (let ((beg 0)
3906 (end (string-width (or company-common ""))))
3907 (when (< numbered qa-keys-len)
3908 (let ((qa-hint
3909 (format "%s: " (funcall
3910 company-quick-access-hint-function
3911 numbered))))
3912 (setq beg (string-width qa-hint)
3913 end (+ beg end))
3914 (cl-incf len beg)
3915 (setq comp (propertize (concat qa-hint comp) 'face 'company-echo)))
3916 (cl-incf numbered))
3917 ;; FIXME: Add support for the `match' backend action, and thus,
3918 ;; non-prefix matches.
3919 (add-text-properties beg end '(face company-echo-common) comp))
3920 (if (>= len limit)
3921 (setq candidates nil)
3922 (push comp msg)))
3923
3924 (mapconcat 'identity (nreverse msg) " "))))
3925
3926(defun company-echo-strip-common-format ()
3927 (let ((selection (or company-selection 0)))
3928 (let ((limit (window-body-width (minibuffer-window)))
3929 (len (+ (length company-prefix) 2))
3930 (candidates (nthcdr selection company-candidates))
3931 (numbered (if company-show-quick-access selection 99999))
3932 (qa-keys-len (length company-quick-access-keys))
3933 comp msg)
3934
3935 (while candidates
3936 (setq comp (company-strip-prefix (pop candidates))
3937 len (+ len 2 (length comp)))
3938 (when (< numbered qa-keys-len)
3939 (let ((qa-hint (format " (%s)"
3940 (funcall company-quick-access-hint-function
3941 numbered))))
3942 (setq comp (concat comp qa-hint))
3943 (cl-incf len (string-width qa-hint)))
3944 (cl-incf numbered))
3945 (if (>= len limit)
3946 (setq candidates nil)
3947 (push (propertize comp 'face 'company-echo) msg)))
3948
3949 (concat (propertize company-prefix 'face 'company-echo-common) "{"
3950 (mapconcat 'identity (nreverse msg) ", ")
3951 "}"))))
3952
3953(defun company-echo-hide ()
3954 (unless (equal company-echo-last-msg "")
3955 (setq company-echo-last-msg "")
3956 (company-echo-show)))
3957
3958(defun company-echo-frontend (command)
3959 "`company-mode' frontend showing the candidates in the echo area."
3960 (pcase command
3961 (`post-command (company-echo-show-soon 'company-echo-format 0))
3962 (`hide (company-echo-hide))))
3963
3964(defun company-echo-strip-common-frontend (command)
3965 "`company-mode' frontend showing the candidates in the echo area."
3966 (pcase command
3967 (`post-command (company-echo-show-soon 'company-echo-strip-common-format 0))
3968 (`hide (company-echo-hide))))
3969
3970(defun company-echo-metadata-frontend (command)
3971 "`company-mode' frontend showing the documentation in the echo area."
3972 (pcase command
3973 (`post-command (company-echo-show-soon 'company-fetch-metadata))
3974 (`unhide (company-echo-show))
3975 (`hide (company-echo-hide))))
3976
3977(provide 'company)
3978;;; company.el ends here