rc

company.el

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