This repository has been archived by the owner on Jul 27, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 49
/
nvim-completion-manager.txt
797 lines (655 loc) · 27.4 KB
/
nvim-completion-manager.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
*nvim-completion-manager.txt* Fast, Extensible, Async Completion Framework
Fast, Extensible, Async Completion Framework For Neovim~
Author: roxma <roxma@qq.com>
License: MIT
nvim-completion-manager *nvim-completion-manager* *NCM*
1. Introduction |NCM-introduction|
2. Install |NCM-install|
3. Optional Configuration Tips |NCM-tips|
4. Settings |NCM-settings|
5. API |NCM-API|
6. Why |NCM-why|
7. Minimal Source Examples |NCM-source-examples|
8. Trouble shooting |NCM-trouble-shooting|
9. Known issues |NCM-known-issues|
==============================================================================
1. Introduction *NCM-introduction*
|NCM| (short for nvim-completion-manager) is a fast, extensible, async
completion framework for neovim.
Main features:
1. Asynchronous completion support like |deoplete|.
2. Faster, all completions should run in parallel.
3. Smarter on files with different languages, for example, css/javascript
completion in html style/script tag.
4. Extensible async vimscript API and python3 API.
5. Function parameter expansion via |Ultisnips|, |neosnippet| or |SnipMate|.
==============================================================================
2. Install *NCM-install*
Requirements:
- For Neovim:
- `has("python3")`
- For Vim 8:
- [roxma/vim-hug-neovim-rpc](https://github.com/roxma/vim-hug-neovim-rpc)
- `g:python3_host_prog` pointed to your python3 executable, or `echo
exepath('python3')` is not empty.
- [neovim python client](https://github.com/neovim/python-client) (`pip3
install neovim`)
Install the required pip modules for your python3:
>
# neovim module is required
# jedi library for python completion
# mistune for language specific completion on markdown
# psutil and setproctitle are optional utilities
pip3 install --user neovim jedi mistune psutil setproctitle
<
Note: If you're using vim8, you also need to install the `neovim` pip module
for the python, depending which on of `has("python")` has `has("python3")` you
are using. You also need to install |vim-hug-neovim-rpc| Plugin:
https://github.com/roxma/vim-hug-neovim-rpc
==============================================================================
3. Optional Configuration Tips *NCM-tips*
Supress the annoying completion messages:
>
" don't give |ins-completion-menu| messages. For example,
" '-- XXX completion (YYY)', 'match 1 of 2', 'The only match',
set shortmess+=c
<
When the <Enter> key is pressed while the popup menu is visible, it only hides
the menu. Use this mapping to hide the menu and also start a new line.
>
inoremap <expr> <CR> (pumvisible() ? "\<c-y>\<cr>" : "\<CR>")
<
Here is an example for expanding snippet in the popup menu with <Enter> key.
Suppose you use the <C-U> key for expanding snippet.
>
imap <expr> <CR> (pumvisible() ? "\<c-y>\<Plug>(expand_or_nl)" : "\<CR>")
imap <expr> <Plug>(expand_or_nl) (cm#completed_is_snippet() ? "\<C-U>":"\<CR>")
<
When using CTRL-C to leave insert mode, it does not trigger the autocmd
|InsertLeave|. You should use CTRL-[, or map the CTRL-C to <ESC>.
>
inoremap <c-c> <ESC>
<
Use <TAB> to select the popup menu:
>
inoremap <expr> <Tab> pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
<
If 'omnifunc' is the only available option, you may register it as a source
for NCM.
>
" css completion via `csscomplete#CompleteCSS`
" The `'cm_refresh_patterns'` is PCRE.
" Be careful with `'scoping': 1` here, not all sources, especially omnifunc,
" can handle this feature properly.
au User CmSetup call cm#register_source({'name' : 'cm-css',
\ 'priority': 9,
\ 'scoping': 1,
\ 'scopes': ['css','scss'],
\ 'abbreviation': 'css',
\ 'word_pattern': '[\w\-]+',
\ 'cm_refresh_patterns':['[\w\-]+\s*:\s+'],
\ 'cm_refresh': {'omnifunc': 'csscomplete#CompleteCSS'},
\ })
<
Note: 'omnifunc' is implemented in a synchronouse style, and vim-vimscript is
single threaded, it would potentially block the ui with the introduction of a
heavy weight 'omnifunc', for example the builtin phpcomplete. If you get some
time, please try implementing a source for NCM as a replacement for the old
style 'omnifunc'.
There's no guarantee that this plugin will be compatible with other completion
plugin in the same buffer. Use `let g:cm_smart_enable=0` and call
|cm#enable_for_buffer()| to use this plugin for specific buffer.
This example shows how to disable NCM's builtin tag completion. It's also
possible to use |g:cm_sources_override| to override other default options of a
completion source.
>
let g:cm_sources_override = {
\ 'cm-tags': {'enable':0}
\ }
<
*NCM-parameter-expansion*
*NCM-snippet*
Config <c-u>, <c-j> and <c-k> for parameter expansion and jumping around
placeholders.
*NCM-Ultisnips*
If you have |Ultisnips|:
>
let g:UltiSnipsExpandTrigger = "<Plug>(ultisnips_expand)"
let g:UltiSnipsJumpForwardTrigger = "<c-j>"
let g:UltiSnipsJumpBackwardTrigger = "<c-k>"
let g:UltiSnipsRemoveSelectModeMappings = 0
" optional
inoremap <silent> <c-u> <c-r>=cm#sources#ultisnips#trigger_or_popup("\<Plug>(ultisnips_expand)")<cr>
<
*NCM-SnipMate*
Or if you have |SnipMate|:
>
let g:snips_no_mappings = 1
" imap <expr> <c-u> pumvisible() ? "\<c-y>\<Plug>snipMateTrigger" : "\<Plug>snipMateTrigger"
" wrap the mapping
imap <expr> <Plug>(snipmate_force_trigger) pumvisible() ? "\<c-y>\<Plug>snipMateTrigger" : "\<Plug>snipMateTrigger"
" show a list of snippets when no the user has typed nothing
inoremap <silent> <c-u> <c-r>=cm#sources#snipmate#trigger_or_popup("\<Plug>(snipmate_force_trigger)")<cr>
vmap <c-u> <Plug>snipMateTrigger
imap <expr> <c-j> pumvisible() ? "\<c-y>\<Plug>snipMateNextOrTrigger" : "\<Plug>snipMateNextOrTrigger"
vmap <c-j> <Plug>snipMateNextOrTrigger
imap <expr> <c-k> pumvisible() ? "\<c-y>\<Plug>snipMateBack" : "\<Plug>snipMateBack"
vmap <c-k> <Plug>snipMateBack
<
*NCM-neosnippet*
Or if you have |neosnippet|:
>
imap <c-j> <Plug>(neosnippet_expand_or_jump)
vmap <c-j> <Plug>(neosnippet_expand_or_jump)
inoremap <silent> <c-u> <c-r>=cm#sources#neosnippet#trigger_or_popup("\<Plug>(neosnippet_expand_or_jump)")<cr>
vmap <c-u> <Plug>(neosnippet_expand_target)
" expand parameters
let g:neosnippet#enable_completed_snippet=1
<
==============================================================================
4. Settings *NCM-settings*
*g:cm_smart_enable*
g:cm_smart_enable
Enable the |NCM| for buffers automatically. unless the
buffer size reach the limit specified by
|g:cm_buffer_size_limit|, or 'buftype' option is not
empty, which means that it's not a normal buffer.
Default: 1
g:cm_buffer_size_limit
Used together with |g:cm_smart_enable|.
Default: 1000000
*g:cm_sources_enable*
g:cm_sources_enable
Automatically enable all registered sources by
default. Set it to 0 if you want to manually enable
the registered sources you want by setting the
|g:cm_sources_override|.
Default: 1
*g:cm_sources_override*
g:cm_sources_override
Override the options used to register the source.
This example shows how to disable NCM's builtin tag
completion: >
let g:cm_sources_override = {
\ 'cm-tags': {'enable':0}
\ }
< See |cm#register_source()| for more information.
*g:cm_complete_start_delay*
g:cm_complete_start_delay
Wait for an interval, in milliseconds, before
candidate calculation, to improve editor performance
for fast typing. This is useful when dealing with
slow, sync completion source.
Default: 0
*g:cm_complete_popup_delay*
g:cm_complete_popup_delay
After candidate calculation has started, wait for an
interval, in milliseconds, before popping up. This
would reduce the popup menu flickering when multiple
sources are updating the popup menu in a short
interval. Use an interval long enough for computer and
short enough for human.
Default: 50
*g:cm_matcher*
g:cm_matcher
A |Dict| specifies the matcher for filtering and
sorting the completion candidates.
Default:
`{'module': 'cm_matchers.prefix_matcher', 'case': 'smartcase'})`
See |g:cm_matcher.module| and |g:cm_matcher.case|.
*g:cm_matcher.module*
g:cm_matcher.module
The matcher module. Available options are:
`"cm_matchers.prefix_matcher"`
Prefix matching. When you type "ab", it only
matches candidates start with with "ab".
`"cm_matchers.substr_matcher"`
Sub-string matching. When you type "round", it
matchings "round", "around", "surroundings"
and so on.
`"cm_matchers.fuzzy_matcher"`
Fuzzy matching.
Note: Known issue #8 on github, there may be
undesired cursor flickering with fuzzy
matcher.
`"cm_matchers.abbrev_matcher"`
A more intuitive version of fuzzy matching.
Note: If you use non-prefix matcher, and haven't set
the |g:cm_completekeys| option, NCM will use
`"<Plug>(cm_completefunc)"` as the default value,
which will change the behavior of the <c-u> key.
*g:cm_matcher.case*
g:cm_matcher.case
Case sensitivity. Available options:
`"case"`
case-sensitive.
`"icase"`
Ignore case.
`"smartcase"`
A lowercase typing will match lower and upper
case candidates. But an uppercase typing will
only match uppercase candidates.
*g:cm_completed_snippet_enable*
g:cm_completed_snippet_enable
Snippet support for completed item (:help
|v:completed_item|). This is useful for function
parameter expension.
Enable by default if any one of the conditions is
satisfied:
- You have installed neosnippet with
|g:neosnippet#enable_completed_snippet| set to 1
- You have installed ultisnips
- You have installed snipMate
*g:cm_completed_snippet_engine*
g:cm_completed_snippet_engine
Available options:
- "ultisnips" by default if UltiSnips is installed
- "snipmate" by default if snipMate is installed
- "neosnippet" by default if neosnippet is installed
*g:cm_completekeys*
g:cm_completekeys
Available options:
`"\<Plug>(cm_complete)"`
This is the default.
`"\<Plug>(cm_completefunc)"`
This is the default when you're not using a
prefix matcher. This key uses the
|i_CTRL-X_CTRL-U| key to trigger the popup
menu, so which will change the behafior of
CTRL-U key. To avoid this behavior, use
`"\<Plug>(cm_omnifunc)"`.
`"\<Plug>(cm_omnifunc)"`
*g:cm_auto_popup*
g:cm_auto_popup
If set to 0, then you have to map the
`<Plug>(cm_force_refresh)` key, and use this key to
trigger the popup menu.
Default: 1
*g:cm_refresh_length*
g:cm_refresh_length
The default value for |cm_refresh_length|.
Default: `[[1,4],[7,3]]`
Format: a |List| as [[ min priority, min len ],...],
or single integer value.
The default value means that sources with priority
between 1 and 6 will have the value of 4, and sources
with priority >= 7 will have the value of 3.
Priority >= 7 is more semantic completion source, So
it's better to use a smaller value to trigger the
popup than others.
By the way, There are users who tend to use longer
typing to trigger the popup to keep them from
distraction. In this case, I would recommend using the
`<Plug>(cm_force_refresh)` key to trigger popup
manually with short typing.
*g:cm_multi_threading*
g:cm_multi_threading
If this options is set to 0. NCM could run in
multi-process mode, each source is a standalone
process. This is useful for debugging.
Default: 1 if environment variable
`$NVIM_NCM_MULTI_THREAD` is not set.
*g:cm_completeopt*
g:cm_completeopt
The value of 'completeopt' when NCM is active.
Default: "menu,menuone,noinsert,noselect"
==============================================================================
5. API *NCM-API*
*cm#register_source()*
cm#register_source({source})
Register a completion source. {source} is a |Dict| that defines the
source, it may contain these fields:
name *NCM-name*
Required, the unique name of the completion source.
abbreviation *NCM-abbreviation*
May be displayed in the popup item to indicate which
completion source the item comes from.
enable If it is zero, this source will not be used.
Default: |g:cm_sources_enable|
priority *NCM-priority*
Required, the priority is used to sort between other
sources. A higher value indicates that the completion
item of this source sorts before sources with lower
priority value.
*NCM-priority-values*
Recommended priority definitions:
2 keyword from the otherfiles, from user's
openning browsers, etc.
4 keyword from openning buffers
5 keyword from current buffer
6 file path
7 snippet hint
8 language specific keyword, but not smart
9 smart programming language aware completion
scopes *NCM-scopes*
A |List| of scope. The source will be activated when
the current editting scope (e.g. current 'filetype')
is in the source's scopes list.
If this field is not set, it means this is a general
purpose completion source, like keyword from buffer,
it will be activated for all buffers.
See |NCM-scoping| for more information.
word_pattern *NCM-word_pattern*
The pattern used to calculate |NCM-startcol|.
Default: see pythonx/cm_default.py
*cm_refresh_patterns*
cm_refresh_patterns *NCM-cm_refresh_patterns*
An extra |List| of PCRE patterns (python regex),
besides |cm_refresh_length|, for auto triggering
popup menu.
*cm_refresh*
cm_refresh *NCM-cm_refresh*
Required for |NCM-vimscript-source|. A handler for the
|cm_refresh-notification|. It is normally a |String|
storing the name of the handler function.
This field should not be set for source implemented
via |NCM-python-source|.
If the handler is a legacy 'omnifunc', which confirms
to the |completion-functions| protocol, use a |Dict|
like this instead:
`{'omnifunc': 'csscomplete#CompleteCSS'}`
*NCM-cm_refresh_length*
cm_refresh_length *cm_refresh_length*
The minimum length of the matching word for auto
triggering popup menu.
If it contains a negative value,
|cm_refresh-notification| will only get triggered by
|cm_refresh_patterns|.
Otherwise, if len(matching word) >= cm_refresh_length,
a |cm_refresh-notification| will be triggered for the
source.
Default: |g:cm_refresh_length|
early_cache *NCM-early_cache*
Cache the completion candidates whenever a word
pattern matches, the result will not be popped up
until the word gets long enough
(|cm_refresh_length|) or matches
|cm_refresh_patterns|. It feels faster when candidates
are already cached before the popup menu is displayed.
Default: 0.
auto_popup
If 0, only the |<Plug>(cm_force_refresh)| key can
trigger the |cm_refresh-notification| for this source.
Default: 1
*NCM-source-options*
options *NCM-options*
This field is ignored by NCM framework, but it will be
passed to the source handler when handling
|cm_refresh-notification|, it is recommended to use
this field to store source specific options.
*cm#complete()*
cm#complete({name}, {context}, {startcol}, {matches}[, {refresh}])
Call this function to trigger the popup menu whenever you have
completions candidates available. Usually this function is called
after a |cm_refresh-notification| is sent to a source.
{name} is the |NCM-name| used to register the source.
{context} is an arugment passed to the |NCM-cm_refresh| handler. It
is used for synchronization, if the user types more characters before
|cm#complete()| is called, NCM will know the {context} is outdated,
and then ignore the {matches} from this call.
See |cm#context()| for more information.
{startcol} and {matches} are used the same way as vim's builtin
|complete()| function.
{refresh} is 0 by default. Normally |NCM| will cache the result until
another word started. And if there's cached result of a source, the
|cm_refresh-notification| will not be sent to the source.
If {refresh} is 1, |NCM| will send the notification reguardless of the
cache of this |cm#complete()| call.
*NCM-CmSetup* *CmSetup*
autocmd User CmSetup
This autocmd will be triggered once |NCM| started.
Registering a source via this autocmd will avoid error when |NCM| has
not been installed yet. And it also avoid the loading of
autoload/cm.vim at neovim startup, so that |NCM| won't affect neovim's
startup time.
*cm#disable_source()*
cm#disable_source({name})
Disable the registered source.
*cm#context()*
cm#context()
Get the current typing context. This function returns a |Dict| with
the following fields:
bufnr
Same as `bufnr('%')`.
lnum
Same as `line('.')`.
col
Same as `col('.')`.
filetype
Same as 'filetype' of the buffer.
typed *cm#context().typed*
The typed text. For example: >
^foo bar|baz
<
Where `^` indicates the start of line, and `|`
indicates cursor position. This field should be: >
"foo bar"
<
Note: In python, the value of `len(context["typed"])`
may be different from the value of `context["col"]-1`.
As specified by to |col()| function, the column number
is the by index of the column position. This only
matters if you're dealing with non English Unicode
characters.
filepath
The path of current editting file. Same as
`expand('%:p')`
Note: When the context is passed via |cm_refresh-notification|, it has
some extra fields:
scope
Current editting scope. See |NCM-scoping|
startcol *NCM-startcol*
Calaulated by NCM for convenience to pass it as an
argument to the |cm#complete()| function.
NCM use |NCM-word_pattern| to get the last typed word,
then set startcol to the beginning of the word. If the
typing ends with non-word-sequence, startcol will be
set to current col.
Note: You're not required to use the startcol provided
by NCM.
base
Set according to the startcol. The value is the same
as the {base} passed to |complete-functions|.
force
Non-zero value if this notification is triggered by
`<Plug>(cm_force_refresh)`.
early_cache
Non-zero value if this notification is triggered by
early caching, the popup menu will no be updated for
early caching.
Other undocumented fields are necessary for the framework, a
completion source should not change these values.
*cm#context_changed()*
cm#context_changed({context})
Check if the {context} is outdated.
*cm#enable_for_buffer()*
cm#enable_for_buffer()
Enable |NCM| for current buffer.
*cm#disable_for_buffer()*
cm#disable_for_buffer()
Disable |NCM| for current buffer.
cm#completed_is_snippet()
Here is an example for expanding snippet in the popup menu with
<Enter> key. Suppose you use the <C-U> key for expanding snippet.
>
imap <expr> <CR> (pumvisible() ? "\<c-y>\<Plug>(expand_or_nl)" : "\<CR>")
imap <expr> <Plug>(expand_or_nl) (cm#completed_is_snippet() ? "\<C-U>":"\<CR>")
<
*<Plug>(cm_force_refresh)*
<Plug>(cm_force_refresh)
A key to trigger the popup manually.
Disable |g:cm_auto_popup| to display popup only with
this key.
==============================================================================
6. Why *NCM-why*
This project was started just for fun, and it's working pleasingly for me now.
However, it seems there's lots of differences between deoplete, YCM, and
nvim-completion-manager, by implementation.
I haven't read the source of YCM yet. So here I'm describing the basic
implementation of NCM (short for nvim-completion-manager) and some of the
differences between deoplete and this plugin.
*NCM-async-architecture*
*cm_refresh-notification*
6.1 Async architecture
Each completion source should be a thread or a standalone process, the manager
notifies the completion source for any text changing, even when popup menu is
visible. The completion source notifies the manager if there's any complete
matches available. After some basic priority sorting between completion
sources, and some simple filtering, the completion popup menu will be
triggered with the `complete()` function by the completion manager.
If some of the completion source is calculating matches for a long long time,
the popup menu will still be shown quickly if other completion sources work
properly. And if the user hasn't changed anything, the popup menu will be
updated after the slow completion source finishes the work.
As the time as of this plugin being created, the completion sources of
deoplete are gathered with `gather_candidates()` of the `Source` object,
inside a for loop, in deoplete's process. A slow completion source may defer
the display of popup menu. Of course it will not block the ui.
The good news is that deoplete has supported async `gather_candidates` now.
But still, NCM is potentially faster because all completion sources run in
parallel.
6.2 Scoping *NCM-scoping*
I write markdown files with code blocks quite often, so I've also implemented
language specific completion for markdown file. This is a framework feature,
which is called scoping. It should work for any markdown code block whose
language completion source is avaible to NCM. I've also added support for
javascript completion in script tag of html files, and css completion in style
tag.
The idea was originated in
[vim-syntax-compl-pop](https://github.com/roxma/vim-syntax-compl-pop). Since
it's pure vimscript implementation, and there are some limitations currently
with neovim's syntax api. It's very likely that vim-syntax-compl-pop doesn't
work, for example, javascript completion in markdown or html script tag. So I
use custom parser in NCM to implement the scoping features.
6.3 Experimental hacking
Note that there's some hacking done in NCM. It uses a per 30ms timer to detect
changes even popup menu is visible, as well as using the `TextChangedI` event,
which only triggers when no popup menu is visible. This is important for
implementing the async architecture. I'm hoping one day neovim will offer
better option rather than a timer or the limited `TextChangedI`.
==============================================================================
7. Minimal Source Examples *NCM-source-examples*
NCM has both vimscript API and python API for writing completion source.
If you just want to write a completion source, it's easier to use the python
API. The completion source will run in NCM's process.
Sometimes it's more memory efficient for a feature-rich plugin to keep the
completion running in the same system process along with other features. In
this case, you should call the vimscript API from your plugin process.
7.1 Implementation in pure vimscript *NCM-vimscript-source*
This minimal example shows how to popup "foo_bar" and "foo_baz" when "/" is
typed.
For more complete example, you mignt need to read the source code of
autoload/cm/sources/ultisnips.vim of this plugin.
Note: The `au User CmSetup` sould be place into your vimrc or the 'rtp'/plugin
directory in order to register the autocmd before |NCM| started.
>
au User CmSetup call cm#register_source({'name' : 'foo bar',
\ 'abbreviation': 'foo',
\ 'priority': 8,
\ 'cm_refresh_patterns': ['/'],
\ 'cm_refresh': 'g:Foo_auto_popup',
\ })
func! g:Foo_auto_popup(opt,ctx)
let l:matches = ['foo_bar','foo_baz']
call cm#complete(a:opt['name'], a:ctx, a:ctx['startcol'], l:matches)
endfunc
>
There're two arguments pass to |cm_refresh| handler.
The first {opt} is the {source} which is used for |cm#register_source()|.
See |cm#context()| for more information on the second argument {ctx}.
7.2 Implementation via NCM python framework *NCM-python-source*
This minimal example shows how to popup "foo_bar" and "foo_baz" when "/" is
typed.
For more complete example, you mignt need to read the source code of
pythonx/cm_sources/cm_gocode.py of this plugin.
Note: This file foo.py should be placed into 'rtp'/pythonx/cm_sources/
directory.
>
# -*- coding: utf-8 -*-
from cm import register_source, Base, getLogger
register_source(name='foo_bar',
abbreviation='foo',
cm_refresh_patterns=[r'/'],
priority=8)
import re
logger = getLogger(__name__)
class Source(Base):
def cm_refresh(self, info, ctx):
matches = ['foo_bar','foo_baz']
startcol = ctx['startcol']
self.complete(info, ctx, startcol, matches)
<
You could enable logging for debugging. Read |NCM-trouble-shooting| for
more information.
Here's explanation on how |cm_refresh| is triggered, with the typing of
`foo_b/foo` for example.
1. `f|`
2. `fo|`
3. `foo|`
|cm_refresh| is triggered, with |NCM-startcol|=1, since the default
|cm_refresh_length|=3 is matched. Popup menu displays.
4. `foo_|`
Popup menu displays, with the cached results 'foo_bar' and 'foo_baz'.
5. `foo_b|`
As above
6. `foo_b/|`
|cm_refresh| is triggered, with |NCM-startcol|=7, since the '/' of
|cm_refresh_patterns| is matched. Popup menu displays.
7. `foo_b/f|`
Popup menu displays, with the cached results 'foo_bar' and 'foo_baz'.
8. `foo_b/fo|`
As above
9. `foo_b/foo|`
As above
==============================================================================
8. Trouble shooting *NCM-trouble-shooting*
If something is broken when you play with NCM. Add something like this to your
vimrc to generate log files.
>
let $NVIM_PYTHON_LOG_FILE="/tmp/nvim_log"
let $NVIM_NCM_LOG_LEVEL="DEBUG"
let $NVIM_NCM_MULTI_THREAD=0
<
After you've reproduced the error, check the content of the log files
generated by NCM in current directory, especially `nvim.log_py3_cm_core`.
If no log file is generated, and you get the message "nvim-completion-manager
core channel terminated", then you have to try starting NCM manually, and see
what's happaning. Follow these steps:
1. If you are using vim-hug-neovim-rpc on vim8, use `:echo
neovim_rpc#serveraddr()` to get the rpc server address. (eg.
`127.0.0.1:37744`).
2. If you're on neovim, use `:echo v:servername` to get the rpc server
address. (eg. `/tmp/nvim5UoeSg/0`)
3. Find the `pythonx/cm_start.py` in NCM's installation directory, then you
can start it manually.
>
# python3 pythonx/cm_start.py core {addr}
python3 pythonx/cm_start.py core /tmp/nvim5UoeSg/0
<
If NCM is working, but some completion source is broken. For example, python
completion is not working, you need to check the contents of the file
`nvim.log_py3_cm_sources.cm_jedi`. If this log file is not generated, the
python completion source may have failed to start somehow. Follow these steps
to start it manually:
1. Find the rpc server address as before.
2. Find the completion source name via `:echo g:_cm_sources` or simply `:echo
keys(g:_cm_sources)`. For python completion, It is `cm-jedi`, then use
`:echo g:_cm_sources['cm-jedi']['channel']['module']` to get the module
name, which would be `cm_sources.cm_jedi`.
3. Use the source name and the module name to start the source manually,
>
# python3 pythonx/cm_start.py channel {source_name} {module_name} {addr}
python3 pythonx/cm_start.py channel cm-jedi cm_sources.cm_jedi /tmp/nvim5UoeSg/0
<
==============================================================================
9. Known issues *NCM-known-issues*
9.1 CTRL-L of |popupmenu-keys| is broken *NCM-issue#127*
It seems this key is in-compatible with vim's |complete()| function.
Try This option:
let g:cm_completekeys = "\<Plug>(cm_omnifunc)"
or
let g:cm_completekeys = "\<Plug>(cm_completefunc)"
But this attempt won't help you with non-prefix-matcher.
==============================================================================
vim: tw=78:ts=8:softtabstop=8:sw=8:ft=help:norl:noexpandtab:fen:noet: