├── LICENSE ├── Readme.md ├── autoload ├── mucomplete.vim └── mucomplete │ ├── auto.vim │ ├── compat.vim │ ├── list.vim │ ├── msg.vim │ ├── neosnippet.vim │ ├── path.vim │ ├── spel.vim │ ├── timer.vim │ └── ultisnips.vim ├── doc ├── mucomplete.txt └── tags ├── plugin └── mucomplete.vim ├── test ├── Readme.md ├── profile_mucomplete.vim ├── test.vim └── test_mucomplete.vim └── troubleshooting_vimrc.vim /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright ©2020–2021 Lifepillar 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | >We're coming down to the ground 2 | > 3 | >There's no better place to go 4 | > 5 | >(Peter Gabriel) 6 | 7 | # What is it? 8 | 9 | MUcomplete is a minimalist autocompletion plugin for Vim. 10 | 11 | MUcomplete is an implementation of *chained (fallback) completion*, whereby 12 | several completion methods are attempted one after another until a result is 13 | returned. 14 | 15 | Under the hood, MUcomplete does nothing more than typing some completion 16 | mappings for you, either when you press ``/`` or automatically 17 | while you are typing. You choose which completion methods to use and in which 18 | order, and MUcomplete does the rest. It does no caching, no asynchronous 19 | computation, no intelligent guessing. It just makes use of core Vim features. 20 | 21 | MUcomplete brings Vim completion down to earth again. 22 | 23 | [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7VXF4VMBTLKDQ) 24 | 25 | 26 | # Getting Started 27 | 28 | MUcomplete requires Vim 7.2 compiled with `+insert_expand` and `+menu`. 29 | Automatic completion is available in Vim 7.4.143 or later, although Vim 30 | 8.0.0283 is recommended. MUcomplete is developed and tested on Vim 8. 31 | 32 | Installation does not require anything special. If you need help, please read 33 | [How to Install](https://github.com/lifepillar/vim-mucomplete/wiki/How-to-Install). 34 | 35 | Mandatory Vim settings: 36 | 37 | ```vim 38 | set completeopt+=menuone 39 | ``` 40 | 41 | For automatic completion, if you use Vim 7.4.775 or later you also need one of 42 | the following: 43 | 44 | ```vim 45 | set completeopt+=noselect 46 | ``` 47 | 48 | or 49 | 50 | ```vim 51 | set completeopt+=noinsert 52 | ``` 53 | 54 | Other recommended settings: 55 | 56 | ```vim 57 | set shortmess+=c " Shut off completion messages 58 | set belloff+=ctrlg " Add only if Vim beeps during completion 59 | ``` 60 | 61 | No other configuration is needed. Just start pressing `` or `` to 62 | complete a word. If you want to enable automatic completion at startup, put 63 | 64 | ```vim 65 | let g:mucomplete#enable_auto_at_startup = 1 66 | ``` 67 | 68 | in your `.vimrc`. Automatic completion may be enabled and disabled at any time 69 | with `:MUcompleteAutoToggle`. If autocompletion looks a little overzealous to 70 | you, you may set: 71 | 72 | ```vim 73 | let g:mucomplete#completion_delay = 1 74 | ``` 75 | 76 | Then, MUcomplete will kick in only when you pause typing. The delay can be 77 | adjusted, of course: see `:help mucomplete-customization`. 78 | 79 | By default, MUcomplete attempts: 80 | 81 | 1. path completion, if the text in front of the cursor looks like a path; 82 | 2. omni-completion, if enabled in the current buffer; 83 | 3. buffer keyword completion; 84 | 4. dictionary completion, if a dictionary is set for the current buffer; 85 | 5. spelling completion, if `'spell'` is on and `'spelllang'` is set; 86 | 87 | in this order (this is called a *completion chain*). At the first successful 88 | attempt, the pop-up menu shows the results. When the pop-up menu is visible, you 89 | may cycle back and forth through the completion chain and try different 90 | completion methods by pressing `` and ``, respectively. In other 91 | words, `` and `` mean: “cancel the current menu and try completing the 92 | text I originally typed in a different way”. See below for an example. 93 | 94 | MUcomplete is fully customizable. See `:help mucomplete.txt` for detailed 95 | documentation. 96 | 97 | **Note:** *MUcomplete maps `` and `` to act as manual completion 98 | triggers by default. It also changes how `` and `` work when the 99 | pop-up menu is visible (and only in that situation). You may override 100 | MUcomplete's defaults, of course, or prevent MUcomplete to define any mappings 101 | at all. Read the documentation for options and for hints about making MUcomplete 102 | work with plugins having conflicting mappings.* 103 | 104 | **Important:** by itself, MUcomplete does not provide any 105 | “intellisense”/semantic completion. If you want that, you also need to install 106 | suitable omni completion plugins for the languages you are using (see the 107 | examples below). 108 | 109 | 110 | # MUcomplete in action 111 | 112 | With jedi-vim (Python) | With SQL (Vim) 113 | :-------------------------:|:-------------------------: 114 | ![](https://raw.github.com/lifepillar/Resources/master/mucomplete/jedi.gif) | ![](https://raw.github.com/lifepillar/Resources/master/mucomplete/sql.gif) 115 | 116 | The first example shows MUcomplete automatically offering suggestions from 117 | [jedi-vim](https://github.com/davidhalter/jedi-vim), which provides semantic 118 | completion for Python. Used settings: 119 | 120 | ```vim 121 | set completeopt-=preview 122 | set completeopt+=longest,menuone,noselect 123 | let g:jedi#popup_on_dot = 0 " It may be 1 as well 124 | let g:mucomplete#enable_auto_at_startup = 1 125 | ``` 126 | 127 | The second example shows how different completion methods (omni completion, 128 | keyword completion, file completion) are automatically selected in different 129 | contexts. Used settings: 130 | 131 | ```vim 132 | set completeopt+=menuone,noselect 133 | let g:mucomplete#user_mappings = { 'sqla' : "\a" } 134 | let g:mucomplete#chains = { 'sql' : ['file', 'sqla', 'keyn'] } 135 | ``` 136 | 137 | This example also shows how you can define custom completion methods. In this 138 | case, a method called `'sqla'` (the name is arbitrary) is mapped to the key 139 | sequence `a` (see `:help sql-completion`). 140 | 141 | With clang_complete | Extending completion 142 | :-------------------------:|:-------------------------: 143 | ![](https://raw.github.com/lifepillar/Resources/master/mucomplete/clang.gif) | ![](https://raw.github.com/lifepillar/Resources/master/mucomplete/ctrlx-ctrln.gif) 144 | 145 | The example above shows MUcomplete used with 146 | [clang-complete](https://github.com/Rip-Rip/clang_complete). You may also see 147 | how it is possible to switch between different completion methods (omni 148 | completion and keyword completion in this case) when the pop-up menu is visible, 149 | using `` and `` (pay attention when `lo` is completed). Relevant 150 | settings: 151 | 152 | ```vim 153 | set noinfercase 154 | set completeopt-=preview 155 | set completeopt+=menuone,noselect 156 | " The following line assumes `brew install llvm` in macOS 157 | let g:clang_library_path = '/usr/local/opt/llvm/lib/libclang.dylib' 158 | let g:clang_user_options = '-std=c++14' 159 | let g:clang_complete_auto = 1 160 | let g:mucomplete#enable_auto_at_startup = 1 161 | ``` 162 | 163 | The last example shows how the current completion can be extended with words 164 | following the previous expansion in other contexts. This is useful, for 165 | instance, to complete sentences or terms made of several words (e.g., to 166 | extend *New* to *New York* or *New Zealand*). Relevant settings: 167 | 168 | ```vim 169 | imap mucomplete#extend_fwd("\") 170 | ``` 171 | 172 | In the example, `` was typed to trigger a completion, then `` was 173 | pressed repeatedly to extend the completion. To my knowledge, MUcomplete is the 174 | only completion plugin that streamlines this Vim feature. See `:help 175 | mucomplete-extend-compl` for more details. 176 | 177 | 178 | 179 | # Compatibility 180 | 181 | See `:help mucomplete-compatibility`. 182 | 183 | 184 | # Troubleshooting 185 | 186 | See `:help mucomplete-troubleshooting`. 187 | -------------------------------------------------------------------------------- /autoload/mucomplete.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | imap (MUcompleteTry) try_completion() 9 | imap (MUcompleteVerify) verify_completion() 10 | if has("patch-8.2.3389") 11 | inoremap (MUcompleteOut) 12 | else 13 | inoremap (MUcompleteOut) 14 | endif 15 | inoremap (MUcompleteTab) 16 | inoremap (MUcompleteCtd) 17 | inoremap (MUcompleteCte) 18 | imap (MUcompleteCyc) cycle() 19 | inoremap (MUcompleteUp) 20 | inoremap (MUcompleteDown) 21 | 22 | fun! s:errmsg(msg) 23 | echohl ErrorMsg 24 | echomsg "[MUcomplete]" a:msg 25 | echohl NONE 26 | endf 27 | 28 | fun! mucomplete#map(mode, lhs, rhs) 29 | try 30 | execute a:mode ' ' a:lhs a:rhs 31 | catch /^Vim\%((\a\+)\)\=:E227/ 32 | call s:errmsg(a:lhs . ' is already mapped (use `:verbose '.a:mode.' '.a:lhs.'` to see by whom). See :help mucomplete-compatibility.') 33 | endtry 34 | endf 35 | 36 | if !get(g:, 'mucomplete#no_mappings', get(g:, 'no_plugin_maps', 0)) 37 | if !hasmapto('(MUcompleteCycFwd)', 'i') 38 | inoremap (MUcompleteFwdKey) 39 | call mucomplete#map('imap', '', '(MUcompleteCycFwd)') 40 | endif 41 | if !hasmapto('(MUcompleteCycBwd)', 'i') 42 | inoremap (MUcompleteBwdKey) 43 | call mucomplete#map('imap', '', '(MUcompleteCycBwd)') 44 | endif 45 | endif 46 | 47 | if exists('g:mucomplete#smart_enter') 48 | call s:errmsg("g:mucomplete#smart_enter has been removed. See :help mucomplete-tips.") 49 | endif 50 | 51 | let s:ctrlx_out = "\(MUcompleteOut)" 52 | let s:compl_mappings = extend({ 53 | \ 'c-n' : s:ctrlx_out."\", 54 | \ 'c-p' : s:ctrlx_out."\", 55 | \ 'cmd' : "\\", 56 | \ 'defs': "\\", 57 | \ 'dict': "\\", 58 | \ 'file': "\\", 59 | \ 'incl': "\\", 60 | \ 'keyn': "\\", 61 | \ 'keyp': "\\", 62 | \ 'line': s:ctrlx_out."\\", 63 | \ 'omni': "\\", 64 | \ 'spel': "\s" , 65 | \ 'tags': "\\", 66 | \ 'thes': "\\", 67 | \ 'user': "\\", 68 | \ 'list': "\=mucomplete#list#complete()\", 69 | \ 'path': "\=mucomplete#path#complete()\", 70 | \ 'uspl': s:ctrlx_out."\=mucomplete#spel#complete()\", 71 | \ 'nsnp': "\=mucomplete#neosnippet#complete()\", 72 | \ 'snip': "\snipMateShow", 73 | \ 'ulti': "\=mucomplete#ultisnips#complete()\", 74 | \ }, get(g:, 'mucomplete#user_mappings', {}), 'error') 75 | let s:default_dir = { 'c-p' : -1, 'keyp': -1, 'line': -1 } 76 | let s:pathsep = exists('+shellslash') && !&shellslash 77 | \ ? (get(g:, 'mucomplete#use_only_windows_paths', 0) ? '[\\]' : '[/\\]') 78 | \ : '[/]' 79 | 80 | fun! mucomplete#add_user_mapping(name, mapping) 81 | return extend(s:compl_mappings, { a:name: a:mapping }, 'keep') 82 | endf 83 | 84 | " Internal state 85 | let s:compl_methods = ['keyn'] " Current completion chain 86 | let s:N = 0 " Length of the current completion chain 87 | let s:i = 0 " Index of the current completion method in the completion chain 88 | let s:countdown = 0 " Keeps track of how many other completion attempts to try 89 | let s:compl_text = '' " Text to be completed 90 | let s:dir = 1 " Direction to search for the next completion method (1=fwd, -1=bwd) 91 | let s:complete_empty_text = 0 " When set to 1, completion is tried even at the start of the line or after a space 92 | let s:noselect = 0 " Set to 1 when completeopt contains 'noselect'; 0 otherwise 93 | let s:noinsert = 0 " Set to 1 when completeopt contains 'noinsert'; 0 otherwise 94 | let g:mucomplete_with_key = 1 " Was completion triggered by a key? 95 | 96 | " Completion chains 97 | let g:mucomplete#chains = extend({ 98 | \ 'default' : ['path', 'omni', 'keyn', 'dict', 'uspl'], 99 | \ 'vim' : ['path', 'cmd', 'keyn'] 100 | \ }, get(g:, 'mucomplete#chains', {})) 101 | 102 | " Regex with special umlaut characters for spel/uspl completion 103 | let g:mucomplete#spel#regex = get(g:, 'mucomplete#spel#regex', 104 | \ '[A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]') 105 | 106 | " Conditions to be verified for a given method to be applied. 107 | if has('lambda') 108 | if get(g:, 'mucomplete#force_manual', 0) 109 | fun! s:fm(f) 110 | return { t -> g:mucomplete_with_key && a:f(t) } 111 | endf 112 | else 113 | fun! s:fm(f) 114 | return a:f 115 | endf 116 | endif 117 | 118 | let s:yes_you_can = { _ -> 1 } " Try always 119 | let s:is_keyword = { t -> t =~# '\m\k\{'.get(g:, 'mucomplete#minimum_prefix_length', 2).'\}$' 120 | \ || (g:mucomplete_with_key && (s:complete_empty_text || t =~# '\m\k$')) } 121 | let s:omni_c = { t -> strlen(&l:omnifunc) > 0 && 122 | \ (t =~# '\m\%(\k\{'.get(g:, 'mucomplete#minimum_prefix_length', 2).'\}\|\S->\|\S\.\)$' 123 | \ || (g:mucomplete_with_key && (s:complete_empty_text || t =~# '\m\%(\k\|\S->\|\S\.\)$')) 124 | \ )} 125 | let s:omni_py = { t -> strlen(&l:omnifunc) > 0 && 126 | \ (t =~# '\m\%(\k\{'.get(g:, 'mucomplete#minimum_prefix_length', 2).'\}\|\k\.\)$' 127 | \ || (g:mucomplete_with_key && (s:complete_empty_text || t =~# '\m\%(\k\|\.\)$')) 128 | \ )} 129 | let s:omni_xml = { t -> strlen(&l:omnifunc) > 0 && 130 | \ (t =~# '\m\%(\k\{'.get(g:, 'mucomplete#minimum_prefix_length', 2).'\}\|<\| strlen(&dictionary) > 0 && (t =~# '\m\a\a$' || (g:mucomplete_with_key && t =~# '\m\a$')) }), 141 | \ 'file': s:fm({ t -> t =~# '\m\%(\%(\f\&[^/\\]\)'.s:pathsep.'\|\%(^\|\s\|\f\|["'']\)'.s:pathsep.'\%(\f\&[^/\\]\)\+\)$' 142 | \ || (g:mucomplete_with_key && t =~# '\m\%(\~\|\%(^\|\s\|\f\|["'']\)'.s:pathsep.'\)\f*$') }), 143 | \ 'incl': s:fm(s:is_keyword), 144 | \ 'keyn': s:fm(s:is_keyword), 145 | \ 'keyp': s:fm(s:is_keyword), 146 | \ 'line': s:fm(s:is_keyword), 147 | \ 'list': s:fm({ t -> t =~# '\m\S\{'.get(g:, 'mucomplete#minimum_prefix_length', 2).'\}$' 148 | \ || (g:mucomplete_with_key && (s:complete_empty_text || t =~# '\m\S$')) }), 149 | \ 'omni': s:fm({ t -> strlen(&l:omnifunc) > 0 && s:is_keyword(t) }), 150 | \ 'path': s:fm({ t -> t =~# '\m\%(\%(\f\&[^/\\]\)'.s:pathsep.'\|\%(^\|\s\|\f\|["'']\)'.s:pathsep.'\%(\f\&[^/\\]\|\s\)\+\)$' 151 | \ || (g:mucomplete_with_key && t =~# '\m\%(\~\|\%(^\|\s\|\f\|["'']\)'.s:pathsep.'\)\%(\f\|\s\)*$') }), 152 | \ 'spel': s:fm({ t -> &l:spell && !empty(&l:spelllang) && t =~# '\m'.g:mucomplete#spel#regex.'\{3}$' }), 153 | \ 'tags': s:fm({ t -> !empty(tagfiles()) && s:is_keyword(t) }), 154 | \ 'thes': s:fm({ t -> strlen(&thesaurus) > 0 && t =~# '\m\a\a\a$' }), 155 | \ 'user': s:fm({ t -> strlen(&l:completefunc) > 0 && s:is_keyword(t) }), 156 | \ 'uspl': s:fm({ t -> &l:spell && !empty(&l:spelllang) && t =~# '\m'.g:mucomplete#spel#regex.'\{3}$' }), 157 | \ 'nsnp': s:fm({ t -> get(g:, 'loaded_neosnippet', 0) && s:is_keyword(t) }), 158 | \ 'snip': s:fm({ t -> get(g:, 'loaded_snips', 0) && s:is_keyword(t) }), 159 | \ 'ulti': s:fm({ t -> get(g:, 'did_plugin_ultisnips', 0) && s:is_keyword(t) }), 160 | \ }, get(s:cc, 'default', {})), 161 | \ 'c' : extend({ 'omni': s:fm(s:omni_c) }, get(s:cc, 'c', {})), 162 | \ 'cpp' : extend({ 'omni': s:fm(s:omni_c) }, get(s:cc, 'cpp', {})), 163 | \ 'html' : extend({ 'omni': s:fm(s:omni_xml) }, get(s:cc, 'html', {})), 164 | \ 'xml' : extend({ 'omni': s:fm(s:omni_xml) }, get(s:cc, 'xml', {})), 165 | \ }, s:cc, 'keep') 166 | if has('python') || has('python3') 167 | call extend(extend(g:mucomplete#can_complete, { 'python': {} }, 'keep')['python'], { 'omni': s:fm(s:omni_py) }, 'keep') 168 | endif 169 | unlet s:cc s:omni_xml s:omni_py s:omni_c 170 | else 171 | let s:yes_you_can = function('mucomplete#compat#yes_you_can') 172 | let g:mucomplete#can_complete = mucomplete#compat#can_complete() 173 | endif 174 | 175 | fun! s:can_complete(i) " Is the i-th completion method applicable? 176 | return get(get(g:mucomplete#can_complete, getbufvar("%","&ft"), {}), 177 | \ s:compl_methods[a:i], 178 | \ get(g:mucomplete#can_complete['default'], s:compl_methods[a:i], s:yes_you_can) 179 | \ )(s:compl_text) 180 | endf 181 | 182 | fun! s:select_dir() 183 | return extend({ 'c-p' : -1, 'keyp': -1, 'line': -1 }, get(g:, 'mucomplete#popup_direction', {})) 184 | endf 185 | 186 | if has("patch-7.4.775") || (v:version == 704 && has("patch775")) " noinsert and noselect added there 187 | fun! s:set_cot() 188 | let s:noselect = (stridx(&l:completeopt, 'noselect') != -1) 189 | let s:noinsert = (stridx(&l:completeopt, 'noinsert') != -1) 190 | endf 191 | 192 | fun! s:fix_auto_select() " Select the correct entry taking into account g:mucomplete#popup_direction 193 | let l:m = s:compl_methods[s:i] 194 | return get(s:default_dir, l:m, 1) == get(s:select_dir(), l:m, 1) || s:noselect 195 | \ ? '' 196 | \ : (get(s:default_dir, l:m, 1) > get(s:select_dir(), l:m, 1) 197 | \ ? "\(MUcompleteUp)\(MUcompleteUp)" 198 | \ : "\(MUcompleteDown)\(MUcompleteDown)") 199 | endf 200 | else " In Vim without 7.4.775, first menu entry is always selected and inserted 201 | fun! s:set_cot() 202 | " noop 203 | endf 204 | 205 | fun! s:fix_auto_select() " Behave as if 'noselect' were set 206 | let l:m = s:compl_methods[s:i] 207 | return strridx(&l:completeopt, 'longest') != -1 208 | \ ? '' 209 | \ : (get(s:default_dir, l:m, 1) > 0 ? "\" : "\") 210 | endf 211 | endif 212 | 213 | 214 | fun! s:insert_entry() " Select and insert a pop-up entry, overriding noselect and noinsert 215 | let l:m = s:compl_methods[s:i] 216 | return get(s:default_dir, l:m, 1) == get(s:select_dir(), l:m, 1) 217 | \ ? (s:noselect 218 | \ ? (get(s:default_dir, l:m, 1) > 0 ? "\" : "\") 219 | \ : (s:noinsert ? "\(MUcompleteUp)\" : '') 220 | \ ) 221 | \ : (get(s:default_dir, l:m, 1) > get(s:select_dir(), l:m, 1) 222 | \ ? (s:noselect ? "\" : "\\") 223 | \ : (s:noselect ? "\" : "\\") 224 | \ ) 225 | endf 226 | 227 | fun! s:notify_completion_type() 228 | let g:mucomplete_current_method = s:compl_methods[s:i] 229 | silent doautocmd User MUcompletePmenu 230 | endf 231 | 232 | fun! s:act_on_pumvisible() 233 | call s:set_cot() 234 | call s:notify_completion_type() 235 | return !g:mucomplete_with_key || get(g:, 'mucomplete#always_use_completeopt', 0) || (index(['spel','uspl'], get(s:compl_methods, s:i, '')) > - 1) 236 | \ ? s:fix_auto_select() 237 | \ : s:insert_entry() 238 | endf 239 | 240 | fun! s:try_completion() " Assumes s:i in [0, s:N - 1] 241 | return s:compl_mappings[s:compl_methods[s:i]] . "\\=''\\(MUcompleteVerify)" 242 | endf 243 | 244 | " Precondition: pumvisible() is false. 245 | fun! s:next_method() 246 | while s:countdown > 0 247 | let s:countdown -= 1 248 | let s:i = (s:i + s:dir + s:N) % s:N 249 | if s:can_complete(s:i) 250 | return s:try_completion() 251 | endif 252 | endwhile 253 | " No result, make sure completion mode is reset. 254 | " Also, insert Tab character if enabled by user option. 255 | return s:ctrlx_out 256 | \ . (g:mucomplete_with_key && get(g:, 'mucomplete#tab_when_no_results', 0) 257 | \ ? "\(MUcompleteTab)" 258 | \ : '') 259 | endf 260 | 261 | fun! s:verify_completion() 262 | return pumvisible() 263 | \ ? s:act_on_pumvisible() 264 | \ : (s:compl_methods[s:i] ==# 'cmd' ? s:ctrlx_out : '') 265 | \ . s:next_method() 266 | endf 267 | 268 | fun! s:extend_completion(dir, keys) 269 | return pumvisible() && index(['keyn', 'keyp', 'c-n', 'c-p', 'defs', 'incl', 'line'], s:compl_methods[s:i]) > -1 270 | \ ? (index(['keyn','keyp','c-n','c-p'], s:compl_methods[s:i]) > -1 271 | \ ? (a:dir > 0 ? "\\" : "\\") 272 | \ : (s:compl_methods[s:i] ==# 'line' ? "\\" : s:compl_mappings[s:compl_methods[s:i]] 273 | \ ) 274 | \ ) 275 | \ . 276 | \ (a:dir > 0 277 | \ ? (s:noselect 278 | \ ? "\(MUcompleteDown)\\" 279 | \ : (s:noinsert ? "\(MUcompleteUp)\" : '') 280 | \ ) 281 | \ : (s:noselect 282 | \ ? "\(MUcompleteUp)\\" 283 | \ : (s:noinsert ? "\(MUcompleteDown)\" : '') 284 | \ ) 285 | \ ) 286 | \ : a:keys 287 | endf 288 | 289 | fun! mucomplete#extend_fwd(keys) 290 | return s:extend_completion(1, a:keys) 291 | endf 292 | 293 | fun! mucomplete#extend_bwd(keys) 294 | return s:extend_completion(-1, a:keys) 295 | endf 296 | 297 | fun! s:cycle() 298 | let g:mucomplete_with_key = g:mucomplete_with_key || get(g:, 'mucomplete#cycle_all', 0) 299 | let s:compl_text = mucomplete#get_compl_text() 300 | let s:countdown = s:N " Reset counter 301 | return s:next_method() 302 | endf 303 | 304 | fun! mucomplete#cycle(dir) 305 | let s:dir = a:dir 306 | return pumvisible() 307 | \ ? "\(MUcompleteCte)\(MUcompleteCyc)" 308 | \ : (a:dir > 0 ? "\(MUcompleteFwdKey)" : "\(MUcompleteBwdKey)") 309 | endf 310 | 311 | " Precondition: pumvisible() is true. 312 | fun! mucomplete#cycle_or_select(dir) 313 | return get(g:, 'mucomplete#cycle_with_trigger', 0) 314 | \ ? mucomplete#cycle(a:dir) 315 | \ : (get(s:select_dir(), s:compl_methods[s:i], 1) * a:dir > 0 ? "\" : "\") 316 | endf 317 | 318 | fun! s:match_scoped_item(chain, syn) 319 | for l:regex in keys(a:chain) 320 | if a:syn =~? l:regex 321 | return a:chain[l:regex] 322 | endif 323 | endfor 324 | return has_key(a:chain, 'default') 325 | \ ? a:chain['default'] 326 | \ : s:scope_chain(g:mucomplete#chains['default']) 327 | endf 328 | 329 | fun! s:get_scoped_item(chain, syn) 330 | return has_key(a:chain, a:syn) ? a:chain[a:syn] : s:match_scoped_item(a:chain, a:syn) 331 | endf 332 | 333 | " If the argument is a completion chain (type() returns v:t_list), return it; 334 | " otherwise, get the completion chain for the current syntax item. 335 | fun! s:scope_chain(c) 336 | return type(a:c) == 3 337 | \ ? a:c 338 | \ : s:get_scoped_item(a:c, synIDattr(synID('.', col('.') - 1, 0), 'name')) 339 | endfun 340 | 341 | " Precondition: pumvisible() is false. 342 | fun! mucomplete#init(dir, tab_completion) " Initialize/reset internal state 343 | let g:mucomplete_with_key = a:tab_completion 344 | let s:dir = a:dir 345 | let s:compl_methods = s:scope_chain(get(b:, 'mucomplete_chain', 346 | \ get(g:mucomplete#chains, getbufvar("%", "&ft"), 347 | \ g:mucomplete#chains['default']))) 348 | let s:N = len(s:compl_methods) 349 | let s:countdown = s:N 350 | let s:i = s:dir > 0 ? -1 : s:N 351 | endf 352 | 353 | fun! mucomplete#get_compl_text() 354 | return col('.') <= get(g:, 'mucomplete#look_behind', 30) 355 | \ ? (col('.') == 1 356 | \ ? '' 357 | \ : getline('.')[0:col('.') - 2]) 358 | \ : getline('.')[col('.') - 1 - get(g:, 'mucomplete#look_behind', 30):col('.') - 2] 359 | endf 360 | 361 | fun! mucomplete#tab_complete(dir) 362 | if pumvisible() 363 | return mucomplete#cycle_or_select(a:dir) 364 | else 365 | if get(g:, 'mucomplete#completion_delay', 0) > 1 366 | call mucomplete#timer#stop() 367 | endif 368 | let s:compl_text = mucomplete#get_compl_text() 369 | let s:complete_empty_text = get(b:, 'mucomplete_empty_text', get(g:, 'mucomplete#empty_text', 0)) 370 | if (empty(s:compl_text) || s:compl_text =~# '\m\s$') && !s:complete_empty_text 371 | return (a:dir > 0 ? "\(MUcompleteTab)" : "\(MUcompleteCtd)") 372 | endif 373 | call mucomplete#init(a:dir, 1) 374 | return s:next_method() 375 | endif 376 | endf 377 | 378 | fun! mucomplete#auto_complete() 379 | let s:compl_text = mucomplete#get_compl_text() 380 | call mucomplete#init(1, 0) 381 | while s:countdown > 0 382 | let s:countdown -= 1 383 | let s:i += 1 384 | if s:can_complete(s:i) 385 | return feedkeys("\(MUcompleteTry)", 'i') 386 | endif 387 | endwhile 388 | endf 389 | 390 | let &cpo = s:save_cpo 391 | unlet s:save_cpo 392 | 393 | " vim: et ts=2 sts=2 sw=2 394 | -------------------------------------------------------------------------------- /autoload/mucomplete/auto.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | fun! mucomplete#auto#enable() 9 | let s:v_char_expr = get(b:, 'mucomplete_empty_text_auto', get(g:, 'mucomplete#empty_text_auto', 0)) 10 | \ ? '\m\p' 11 | \ : '\m\S' 12 | if get(g:, 'mucomplete#completion_delay', 0) > 1 && has('timers') 13 | call mucomplete#timer#enable() 14 | else 15 | augroup MUcompleteAuto 16 | autocmd! 17 | autocmd InsertCharPre * noautocmd call mucomplete#auto#insertcharpre() 18 | if get(g:, 'mucomplete#completion_delay', 0) 19 | autocmd TextChangedI * noautocmd call mucomplete#auto#ic_auto_complete() 20 | autocmd CursorHoldI * noautocmd call mucomplete#auto#auto_complete() 21 | else 22 | autocmd TextChangedI * noautocmd call mucomplete#auto#auto_complete() 23 | endif 24 | augroup END 25 | endif 26 | endf 27 | 28 | fun! mucomplete#auto#disable() 29 | if exists('#MUcompleteAuto') 30 | autocmd! MUcompleteAuto 31 | augroup! MUcompleteAuto 32 | endif 33 | unlet! s:v_char_expr 34 | endf 35 | 36 | fun! mucomplete#auto#toggle() 37 | if exists('#MUcompleteAuto') 38 | call mucomplete#auto#disable() 39 | echomsg '[MUcomplete] Auto off' 40 | else 41 | call mucomplete#auto#enable() 42 | echomsg '[MUcomplete] Auto on' 43 | endif 44 | endf 45 | 46 | if has('patch-8.0.0283') 47 | let s:insertcharpre = 0 48 | 49 | fun! mucomplete#auto#insertcharpre() 50 | let s:insertcharpre = !pumvisible() && (v:char =~# s:v_char_expr) 51 | endf 52 | 53 | fun! mucomplete#auto#ic_auto_complete() 54 | " In Insert completion mode, CursorHoldI in not invoked. 55 | " With delay on, wait for timer to expire (if using timers). 56 | if mode(1) ==# 'ic' && get(g:, 'mucomplete#reopen_immediately', 1) 57 | call mucomplete#auto_complete() 58 | endif 59 | endf 60 | 61 | fun! mucomplete#auto#auto_complete() 62 | if s:insertcharpre || mode(1) ==# 'ic' 63 | let s:insertcharpre = 0 64 | call mucomplete#auto_complete() 65 | endif 66 | endf 67 | 68 | let &cpo = s:save_cpo 69 | unlet s:save_cpo 70 | 71 | finish 72 | endif 73 | 74 | " Code for Vim 8.0.0282 and older 75 | if !(get(g:, 'mucomplete#no_popup_mappings', 0) || get(g:, 'mucomplete#no_mappings', 0) || get(g:, 'no_plugin_maps', 0)) 76 | if !hasmapto('(MUcompletePopupCancel)', 'i') 77 | call mucomplete#map('imap', '', '(MUcompletePopupCancel)') 78 | endif 79 | if !hasmapto('(MUcompletePopupAccept)', 'i') 80 | call mucomplete#map('imap', '', '(MUcompletePopupAccept)') 81 | endif 82 | if !hasmapto('(MUcompleteCR)', 'i') 83 | call mucomplete#map('imap', '', '(MUcompleteCR)') 84 | endif 85 | endif 86 | 87 | let s:cancel_auto = 0 88 | let s:insertcharpre = 0 89 | 90 | fun! mucomplete#auto#popup_exit(keys) 91 | let s:cancel_auto = pumvisible() 92 | return a:keys 93 | endf 94 | 95 | fun! mucomplete#auto#insertcharpre() 96 | let s:insertcharpre = (v:char =~# '\m\S') 97 | endf 98 | 99 | fun! mucomplete#auto#ic_auto_complete() 100 | if s:cancel_auto 101 | let s:cancel_auto = 0 102 | return 103 | endif 104 | if !s:insertcharpre 105 | call mucomplete#auto_complete() 106 | endif 107 | endf 108 | 109 | fun! mucomplete#auto#auto_complete() 110 | if s:cancel_auto 111 | let [s:cancel_auto, s:insertcharpre] = [0,0] 112 | return 113 | endif 114 | if s:insertcharpre 115 | let s:insertcharpre = 0 116 | call mucomplete#auto_complete() 117 | endif 118 | endf 119 | 120 | let &cpo = s:save_cpo 121 | unlet s:save_cpo 122 | 123 | -------------------------------------------------------------------------------- /autoload/mucomplete/compat.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | let s:pathsep = exists('+shellslash') && !&shellslash 9 | \ ? (get(g:, 'mucomplete#use_only_windows_paths', 0) ? '[\\]' : '[/\\]') 10 | \ : '[/]' 11 | 12 | fun! mucomplete#compat#yes_you_can(t) 13 | return 1 14 | endf 15 | 16 | fun! mucomplete#compat#default(t) 17 | return a:t =~# '\m\k\{'.get(g:, 'mucomplete#minimum_prefix_length', 2).'\}$' || 18 | \ (g:mucomplete_with_key && (get(b:, 'mucomplete_empty_text', get(g:, 'mucomplete#empty_text', 0)) || a:t =~# '\m\k$')) 19 | endf 20 | 21 | fun! mucomplete#compat#dict(t) 22 | return strlen(&dictionary) > 0 && (a:t =~# '\m\a\a$' || (g:mucomplete_with_key && a:t =~# '\m\a$')) 23 | endf 24 | 25 | fun! mucomplete#compat#file(t) 26 | return a:t =~# '\m\%(\%(\f\&[^/\\]\)'.s:pathsep.'\|\%(^\|\s\|\f\|["'']\)'.s:pathsep.'\%(\f\&[^/\\]\)\+\)$' 27 | \ || (g:mucomplete_with_key && a:t =~# '\m\%(\~\|\%(^\|\s\|\f\|["'']\)'.s:pathsep.'\)\f*$') 28 | endf 29 | 30 | fun! mucomplete#compat#omni(t) 31 | return strlen(&l:omnifunc) > 0 && mucomplete#compat#default(a:t) 32 | endf 33 | 34 | fun! mucomplete#compat#spel(t) 35 | return &l:spell && !empty(&l:spelllang) && a:t =~# '\m'.g:mucomplete#spel#regex.'\{3}$' 36 | endf 37 | 38 | fun! mucomplete#compat#tags(t) 39 | return !empty(tagfiles()) && mucomplete#compat#default(a:t) 40 | endf 41 | 42 | fun! mucomplete#compat#thes(t) 43 | return strlen(&thesaurus) > 0 && a:t =~# '\m\a\a\a$' 44 | endf 45 | 46 | fun! mucomplete#compat#user(t) 47 | return strlen(&l:completefunc) > 0 && mucomplete#compat#default(a:t) 48 | endf 49 | 50 | fun! mucomplete#compat#list(t) 51 | return a:t =~# '\m\S\{'.get(g:, 'mucomplete#minimum_prefix_length', 2).'\}$' || 52 | \ (g:mucomplete_with_key && (s:complete_empty_text || t =~# '\m\S$')) 53 | endf 54 | 55 | fun! mucomplete#compat#path(t) 56 | return a:t =~# '\m\%(\%(\f\&[^/\\]\)'.s:pathsep.'\|\%(^\|\s\|\f\|["'']\)'.s:pathsep.'\%(\f\&[^/\\]\|\s\)\+\)$' 57 | \ || (g:mucomplete_with_key && a:t =~# '\m\%(\~\|\%(^\|\s\|\f\|["'']\)'.s:pathsep.'\)\%(\f\|\s\)*$') 58 | endf 59 | 60 | fun! mucomplete#compat#nsnp(t) 61 | return get(g:, 'loaded_neosnippet', 0) && mucomplete#compat#default(a:t) 62 | endf 63 | 64 | fun! mucomplete#compat#snip(t) 65 | return get(g:, 'loaded_snips', 0) && mucomplete#compat#default(a:t) 66 | endf 67 | 68 | fun! mucomplete#compat#ulti(t) 69 | return get(g:, 'did_plugin_ultisnips', 0) && mucomplete#compat#default(a:t) 70 | endf 71 | 72 | fun! mucomplete#compat#omni_c(t) 73 | return strlen(&l:omnifunc) > 0 && a:t =~# '\m\%(\k\{'.get(g:, 'mucomplete#minimum_prefix_length', 2).'\}\|\S->\|\S\.\)$' 74 | \ || (g:mucomplete_with_key && (s:complete_empty_text || a:t =~# '\m\%(\k\|\S->\|\S\.\)$')) 75 | endf 76 | 77 | fun! mucomplete#compat#omni_python(t) 78 | return a:t =~# '\m\%(\k\{'.get(g:, 'mucomplete#minimum_prefix_length', 2).'\}\|\k\.\)$' 79 | \ || (g:mucomplete_with_key && (get(b:, 'mucomplete_empty_text', get(g:, 'mucomplete#empty_text', 0)) || a:t =~# '\m\%(\k\|\.\)$')) 80 | endf 81 | 82 | fun! mucomplete#compat#omni_xml(t) 83 | return strlen(&l:omnifunc) > 0 && a:t =~# '\m\%(\k\{'.get(g:, 'mucomplete#minimum_prefix_length', 2).'\}\| 3 | " License: MIT 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | if exists('*matchstrpos') 9 | fun! s:getword() 10 | return matchstrpos(getline('.'), '\S\+\%'.col('.').'c') 11 | endf 12 | else 13 | fun! s:getword() 14 | return [matchstr(getline('.'), '\S\+\%'.col('.').'c'), match(getline('.'), '\S\+\%'.col('.').'c'), 0] 15 | endf 16 | endif 17 | 18 | fun! mucomplete#list#complete() abort 19 | let [l:word, l:col, l:_] = s:getword() 20 | let l:suggestions = mucomplete#list#completefunc(0, l:word) 21 | if !empty(l:suggestions) 22 | call complete(1 + l:col, l:suggestions) 23 | endif 24 | return '' 25 | endf 26 | 27 | fun! s:wordlist() 28 | return get(b:, 'mucomplete_wordlist', 29 | \ get(get(g:, 'mucomplete#wordlist', {}), getbufvar("%","&ft"), 30 | \ get(get(g:, 'mucomplete#wordlist', {}), 'default', []))) 31 | endf 32 | 33 | fun! mucomplete#list#completefunc(findstart, base) 34 | if a:findstart 35 | return match(getline('.'), '\S\+\%'.col('.').'c') 36 | else 37 | let l:res = [] 38 | let l:len = len(s:wordlist()) 39 | let l:lft = 0 40 | let l:rgt = l:len 41 | while l:lft < l:rgt " Find the leftmost index matching base 42 | let l:i = (l:lft + l:rgt) / 2 43 | if s:wordlist()[l:i] < a:base 44 | let l:lft = l:i + 1 45 | else 46 | let l:rgt = l:i 47 | endif 48 | endwhile 49 | while l:lft < l:len && s:wordlist()[l:lft] =~ '^' . a:base 50 | call add(l:res, s:wordlist()[l:lft]) 51 | let l:lft += 1 52 | endwhile 53 | return l:res 54 | endif 55 | endfun 56 | 57 | let &cpo = s:save_cpo 58 | unlet s:save_cpo 59 | 60 | -------------------------------------------------------------------------------- /autoload/mucomplete/msg.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | fun! s:show_current_method(abbr) 9 | unsilent echo '[MUcomplete]' 10 | \ get(a:abbr ? g:mucomplete#msg#short_methods : g:mucomplete#msg#methods, 11 | \ get(g:, 'mucomplete_current_method', ''), 'Custom method') 12 | let g:mucomplete_current_method = '' 13 | " Force placing the cursor back into the buffer 14 | " Without this, the cursor may get stuck in the command line after the 15 | " message is printed until another character is typed. 16 | " Note: this works only if the status line is visible! 17 | let &ro=&ro 18 | endf 19 | 20 | fun! s:notify_at_level(n) 21 | augroup MUcompleteNotifications 22 | autocmd! 23 | if a:n == 1 24 | autocmd User MUcompletePmenu call s:show_current_method(1) 25 | autocmd CompleteDone * echo "\r" 26 | elseif a:n == 2 27 | autocmd User MUcompletePmenu call s:show_current_method(0) 28 | autocmd CompleteDone * echo "\r" 29 | else " Status line 30 | autocmd User MUcompletePmenu let &ro=&ro 31 | autocmd CompleteDone * let g:mucomplete_current_method = '' | let &ro=&ro 32 | endif 33 | augroup END 34 | endf 35 | 36 | fun! s:shut_off_notifications() 37 | if exists('#MUcompleteNotifications') 38 | autocmd! MUcompleteNotifications 39 | augroup! MUcompleteNotifications 40 | endif 41 | endf 42 | 43 | fun! mucomplete#msg#set_notifications(n) 44 | if a:n > 0 && a:n < 4 45 | call s:notify_at_level(a:n) 46 | else 47 | call s:shut_off_notifications() 48 | endif 49 | endf 50 | 51 | let g:mucomplete#msg#methods = extend({ 52 | \ "c-n" : "Keywords in 'complete' (search forwards)", 53 | \ "c-p" : "Keywords in 'complete' (search backwards)", 54 | \ "cmd" : "Vim commands", 55 | \ "defs": "Definitions or macros", 56 | \ "dict": "Keywords in 'dictionary'", 57 | \ "file": "File completion", 58 | \ "incl": "Keywords in the current and included files", 59 | \ "keyn": "Keywords in the current file (search forwards)", 60 | \ "keyp": "Keywords in the current file (search backwards)", 61 | \ "line": "Whole lines", 62 | \ "list": "Custom list of words", 63 | \ "nsnp": "Neosnippet snippets", 64 | \ "omni": "Omni completion ('omnifunc')", 65 | \ "path": "Path completion", 66 | \ "snip": "SnipMate snippets", 67 | \ "spel": "Spelling suggestions", 68 | \ "tags": "Tags completion", 69 | \ "thes": "Keywords in 'thesaurus'", 70 | \ "user": "User defined completion ('completefunc')", 71 | \ "ulti": "Ultisnips snippets", 72 | \ "uspl": "Improved spelling suggestions", 73 | \ }, get(g:, 'mucomplete#msg#methods', {})) 74 | 75 | let g:mucomplete#msg#short_methods = extend({ 76 | \ "c-n" : "keywords", 77 | \ "c-p" : "keywords", 78 | \ "cmd" : "vim", 79 | \ "defs": "definitions", 80 | \ "dict": "dictionary", 81 | \ "file": "files", 82 | \ "incl": "included files", 83 | \ "keyn": "buffer keywords", 84 | \ "keyp": "buffer keywords", 85 | \ "line": "whole lines", 86 | \ "list": "word list", 87 | \ "nsnp": "neosnippet", 88 | \ "omni": "omnifunc", 89 | \ "path": "paths", 90 | \ "snip": "snipmate", 91 | \ "spel": "spelling", 92 | \ "tags": "tags", 93 | \ "thes": "thesaurus", 94 | \ "user": "completefunc", 95 | \ "ulti": "ultisnips", 96 | \ "uspl": "spelling", 97 | \ }, get(g:, 'mucomplete#msg#short_methods', {})) 98 | 99 | let &cpo = s:save_cpo 100 | unlet s:save_cpo 101 | 102 | -------------------------------------------------------------------------------- /autoload/mucomplete/neosnippet.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | fun! mucomplete#neosnippet#complete() abort 9 | let l:snippets = filter(neosnippet#helpers#get_snippets(), 10 | \ "!get(v:val.options, 'oneshot', 0)") 11 | if empty(l:snippets) 12 | return '' 13 | endif 14 | let l:pat = matchstr(getline('.'), '\S\+\%'.col('.').'c') 15 | let l:candidates = map(filter(keys(l:snippets), 'stridx(v:val, l:pat) == 0'), 16 | \ '{ 17 | \ "word": l:snippets[v:val]["word"], 18 | \ "menu": "[neosnippet] ". get(l:snippets[v:val], "menu_abbr", ""), 19 | \ "dup" : 1 20 | \ }') 21 | if !empty(l:candidates) 22 | call complete(col('.') - len(l:pat), l:candidates) 23 | endif 24 | return '' 25 | endf 26 | 27 | 28 | " Automatic expansion of snippets 29 | 30 | fun! mucomplete#neosnippet#do_expand(keys) 31 | if get(v:completed_item, 'menu', '') =~# '[neosnippet]' 32 | return neosnippet#expand(v:completed_item['word']) 33 | endif 34 | return a:keys 35 | endf 36 | 37 | fun! mucomplete#neosnippet#expand_snippet(keys) 38 | return pumvisible() 39 | \ ? "\\=mucomplete#neosnippet#do_expand('')\" 40 | \ : a:keys 41 | endf 42 | 43 | let &cpo = s:save_cpo 44 | unlet s:save_cpo 45 | 46 | -------------------------------------------------------------------------------- /autoload/mucomplete/path.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | if has('patch-7.4.654') || (v:version == 704 && has("patch654")) 9 | 10 | fun! s:glob(expr, nosuf, list, alllinks) 11 | return glob(a:expr, a:nosuf, a:list, a:alllinks) 12 | endf 13 | 14 | elseif v:version > 703 || (v:version == 703 && has("patch465")) 15 | 16 | fun! s:glob(expr, nosuf, list, alllinks) 17 | return glob(a:expr, a:nosuf, a:list) 18 | endf 19 | 20 | else 21 | 22 | fun! s:glob(expr, nosuf, list, alllinks) 23 | return split(glob(a:expr, a:nosuf), "\n") 24 | endf 25 | 26 | endif 27 | 28 | let s:pathstart = exists('+shellslash') && !&shellslash 29 | \ ? (get(g:, 'mucomplete#use_only_windows_paths', 0) ? '[\\~]' : '[/\\~]') 30 | \ : '[/~]' 31 | 32 | if exists('&fileignorecase') 33 | 34 | fun! s:case_insensitive() 35 | return &fileignorecase || &wildignorecase 36 | endf 37 | 38 | elseif exists('&wildignorecase') 39 | 40 | fun! s:case_insensitive() 41 | return &wildignorecase 42 | endf 43 | 44 | else 45 | 46 | fun! s:case_insensitive() 47 | return 1 48 | endf 49 | 50 | endif 51 | 52 | if has('win32') 53 | 54 | " In Windows, fnamescape() escapes { only if { is not in isfname, but glob() 55 | " won't like even an escaped { as long as { is in isfname. Using 56 | " fnameescape() may not be a good idea anyway, but for now we keep it (see 57 | " https://github.com/vim/vim/issues/541). The best we can do for now is 58 | " replacing { and } with [\{] and [\}] respectively. They won't match (!) if 59 | " braces are in isfname, but at least won't give errors either. 60 | fun! s:fnameescape(p) 61 | return substitute( 62 | \ (stridx(&isfname, '{') == -1 63 | \ ? fnameescape(a:p) 64 | \ : substitute(fnameescape(a:p), '{', '[\\{]', 'g')), 65 | \ '}', '[\\}]', 'g') 66 | endf 67 | 68 | else 69 | 70 | " fnamescape() always escapes { (tried macOS and Linux). 71 | " fnamescape() does not escape }, but glob() needs it to be escaped. 72 | fun! s:fnameescape(p) 73 | return escape(fnameescape(a:p), '}') 74 | endf 75 | 76 | endif 77 | 78 | fun! mucomplete#path#complete() abort 79 | let l:prefix = matchstr(getline('.'), '\f\%(\f\|\s\)*\%'.col('.').'c') 80 | let l:case_insensitive = s:case_insensitive() 81 | while strlen(l:prefix) > 0 " Try to find an existing path (consider paths with spaces, too) 82 | if l:prefix ==# '~' 83 | let l:files = s:glob('~', 0, 1, 1) 84 | if !empty(l:files) 85 | call complete(col('.') - 1, map(l:files, '{ "word": v:val, "menu": "[dir]", "icase": l:case_insensitive }')) 86 | endif 87 | return '' 88 | else 89 | let l:files = s:glob( 90 | \ (get(g:, 'mucomplete#buffer_relative_paths', 0) && l:prefix !~# '^'.s:pathstart 91 | \ ? s:fnameescape(expand('%:p:h')) . '/' 92 | \ : '') 93 | \ . s:fnameescape(l:prefix) . '*', 0, 1, 1) 94 | if !empty(l:files) 95 | call complete(col('.') - len(fnamemodify(l:prefix, ":t")), map(l:files, 96 | \ '{ 97 | \ "word": fnamemodify(v:val, ":t"), 98 | \ "menu": (isdirectory(v:val) ? "[dir]" : "[file]"), 99 | \ "icase": l:case_insensitive 100 | \ }' 101 | \ )) 102 | return '' 103 | endif 104 | endif 105 | let l:prefix = matchstr(l:prefix, '\%(\s\|=\)\zs.*'.s:pathstart.'.*$', 1) " Next potential path 106 | endwhile 107 | return '' 108 | endf 109 | 110 | let &cpo = s:save_cpo 111 | unlet s:save_cpo 112 | 113 | -------------------------------------------------------------------------------- /autoload/mucomplete/spel.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | if exists('*matchstrpos') 9 | fun! s:getword() 10 | return matchstrpos(getline('.'), g:mucomplete#spel#regex.'\+\%'.col('.').'c') 11 | endf 12 | else 13 | fun! s:getword() 14 | return [matchstr(getline('.'), g:mucomplete#spel#regex.'\+\%'.col('.').'c'), match(getline('.'), g:mucomplete#spel#regex.'\+\%'.col('.').'c'), 0] 15 | endf 16 | endif 17 | 18 | fun! mucomplete#spel#complete() abort 19 | let [l:word, l:col, l:_] = s:getword() 20 | let l:suggestions = spellsuggest( 21 | \ get(g:, 'mucomplete#spel#good_words', 0) 22 | \ ? l:word 23 | \ : spellbadword(l:word)[0] 24 | \ , get(g:, 'mucomplete#spel#max', 25)) 25 | if !empty(l:suggestions) 26 | call complete(1 + l:col, l:suggestions) 27 | endif 28 | return '' 29 | endf 30 | 31 | let &cpo = s:save_cpo 32 | unlet s:save_cpo 33 | 34 | -------------------------------------------------------------------------------- /autoload/mucomplete/timer.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | if !has('timers') 9 | fun! mucomplete#timer#stop() 10 | endf 11 | let &cpo = s:save_cpo 12 | unlet s:save_cpo 13 | finish 14 | endif 15 | 16 | fun! mucomplete#timer#enable() 17 | augroup MUcompleteAuto 18 | autocmd! 19 | autocmd InsertCharPre * noautocmd call mucomplete#timer#restart() 20 | autocmd TextChangedI * noautocmd call mucomplete#auto#ic_auto_complete() 21 | autocmd InsertLeave * noautocmd call mucomplete#timer#stop() 22 | augroup END 23 | endf 24 | 25 | fun! mucomplete#timer#restart() 26 | call mucomplete#auto#insertcharpre() 27 | if exists('s:completion_timer') 28 | call timer_stop(s:completion_timer) 29 | endif 30 | let s:completion_timer = timer_start(get(g:, 'mucomplete#completion_delay', 150), 'mucomplete#timer#complete') 31 | endf 32 | 33 | fun! mucomplete#timer#stop() 34 | if exists('s:completion_timer') 35 | call timer_stop(s:completion_timer) 36 | unlet s:completion_timer 37 | endif 38 | endf 39 | 40 | fun! mucomplete#timer#complete(tid) 41 | unlet s:completion_timer 42 | if !pumvisible() 43 | call mucomplete#auto#auto_complete() 44 | endif 45 | endf 46 | 47 | let &cpo = s:save_cpo 48 | unlet s:save_cpo 49 | 50 | -------------------------------------------------------------------------------- /autoload/mucomplete/ultisnips.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | let s:save_cpo = &cpo 6 | set cpo&vim 7 | 8 | let s:cmp = 'stridx(v:val, l:pat)' . (get(g:, 'mucomplete#ultisnips#match_at_start', 1) ? '==0' : '>=0') 9 | 10 | fun! mucomplete#ultisnips#complete() abort 11 | if empty(UltiSnips#SnippetsInCurrentScope(1)) 12 | return '' 13 | endif 14 | let l:pat = matchstr(getline('.'), '\S\+\%'.col('.').'c') 15 | let l:candidates = map(filter(keys(g:current_ulti_dict_info), s:cmp), 16 | \ '{ 17 | \ "word": v:val, 18 | \ "menu": "[snip] ". get(g:current_ulti_dict_info[v:val], "description", ""), 19 | \ "dup" : 1 20 | \ }') 21 | if !empty(l:candidates) 22 | call complete(col('.') - len(l:pat), l:candidates) 23 | endif 24 | return '' 25 | endf 26 | 27 | 28 | " Automatic expansion of snippets 29 | 30 | fun! mucomplete#ultisnips#do_expand(keys) 31 | if get(v:completed_item, 'menu', '') =~# '[snip]' 32 | return UltiSnips#ExpandSnippet() 33 | endif 34 | return a:keys 35 | endf 36 | 37 | fun! mucomplete#ultisnips#expand_snippet(keys) 38 | return pumvisible() 39 | \ ? "\\=mucomplete#ultisnips#do_expand('')\" 40 | \ : a:keys 41 | endf 42 | 43 | let &cpo = s:save_cpo 44 | unlet s:save_cpo 45 | 46 | -------------------------------------------------------------------------------- /doc/mucomplete.txt: -------------------------------------------------------------------------------- 1 | *mucomplete.txt* For Vim version 7.2 Last change: 2020 Nov 15 2 | 3 | |\/|| | _ _ ._ _ ._ | __|_ _ ~ 4 | | ||_|(_(_)| | ||_)|(/_|_(/_ ~ 5 | | ~ 6 | 7 | Welcome to the world of fallback completion! 8 | 9 | Author: Lifepillar 10 | License: MIT 11 | 12 | ============================================================================== 13 | CONTENTS *mucomplete-contents* 14 | 15 | 1. Introduction .............. |mucomplete-introduction| 16 | 2. Requirements .............. |mucomplete-requirements| 17 | 3. Getting started ........... |mucomplete-howto| 18 | 4. Completion methods ........ |mucomplete-methods| 19 | 5. Completion chains ......... |mucomplete-chains| 20 | 6. Path completion ........... |mucomplete-path-complete| 21 | 7. Spelling suggestions ...... |mucomplete-spel-complete| 22 | 8. Extending completions ..... |mucomplete-extend-compl| 23 | 9. Commands .................. |mucomplete-commands| 24 | 10. Mappings .................. |mucomplete-mappings| 25 | 11. Plugs ..................... |mucomplete-plugs| 26 | 12. Customization ............. |mucomplete-customization| 27 | 13. Tips & tricks ............. |mucomplete-tips| 28 | 14. Compatibility ............. |mucomplete-compatibility| 29 | 15. Troubleshooting ........... |mucomplete-troubleshooting| 30 | 16. Providing feedback ........ |mucomplete-feedback| 31 | 17. Implementation details .... |mucomplete-internals| 32 | 33 | ============================================================================== 34 | 1. Introduction *mucomplete-introduction* 35 | 36 | MUcomplete is a minimalist autocompletion plugin. 37 | 38 | MUcomplete does nothing more than typing some completion mappings for you, 39 | either when you press / or automatically while you are typing. You 40 | choose which completion methods to use and in which order, and MUcomplete does 41 | the rest. It does no caching, no asynchronous computation, no intelligent 42 | guessing. It just makes use of built-in Vim features. 43 | 44 | ============================================================================== 45 | 2. Requirements *mucomplete-requirements* 46 | 47 | MUcomplete requires Vim 7.2 compiled with |+insert_expand| and |+menu|. 48 | Automatic completion is available in Vim 7.4.143 or later, although Vim 49 | 8.0.0283 or later is recommended. 50 | 51 | MUcomplete is developed and tested on Vim 8. 52 | 53 | ============================================================================== 54 | 3. Getting started *mucomplete-howto* 55 | 56 | Mandatory Vim settings: 57 | > 58 | set completeopt+=menuone 59 | < 60 | For automatic completion, if you use Vim 7.4.775 or later you also need one of 61 | the following: 62 | > 63 | set completeopt+=noselect 64 | < 65 | or 66 | > 67 | set completeopt+=noinsert 68 | < 69 | Other recommended settings: 70 | > 71 | set shortmess+=c " Shut off completion messages 72 | set belloff+=ctrlg " If Vim beeps during completion 73 | < 74 | Press in Insert mode to complete a word. This will sequentially trigger 75 | the methods specified in |g:mucomplete#chains| until some results are found 76 | (if any). You may use to try the same list of methods in reverse 77 | order. For example, if the current completion chain is ["omni", "keyn"] (see 78 | |mucomplete-methods| and |mucomplete-chains|), then pressing will cause 79 | omni completion to be attempted first, provided that 'omnifunc' is defined. If 80 | 'omnifunc' is not defined or the omni completion function returns no results 81 | then MUcomplete will fallback to local keyword completion ("keyn"). Pressing 82 | will trigger keyword completion first and fallback to omni completion 83 | if necessary. You may define arbitrarily long completion chains, and even 84 | filetype-specific or buffer-specific completion chains. 85 | 86 | Sometimes, the first method returning results is not the one you want. With 87 | the pop-up menu visible, you may type and to cycle back and forth, 88 | respectively, through the current completion chain. In other words, and 89 | mean: "cancel the current menu and try completing the text I originally 90 | typed in a different way". 91 | 92 | If you want completion to be triggered automatically, set 93 | |g:mucomplete#enable_auto_at_startup|. 94 | 95 | Note: completion is disabled when 'paste' is on. 96 | 97 | In detail, this is the algorithm used by MUcomplete: 98 | 99 | 1. Retrieve the current completion chain from |b:mucomplete_chain|, if 100 | defined, otherwise from |g:mucomplete#chains|. 101 | 102 | 2. For each method listed in the given completion chain: 103 | 104 | 2(a). Check whether the method can be applied by invoking the 105 | corresponding function in |g:mucomplete#can_complete|. 106 | 107 | 2(b). If the method can be applied, invoke the corresponding mapping 108 | and go to 2(c); otherwise, try the next method. 109 | 110 | 2(c). If some results are returned, show them in a pop-up menu and 111 | stop; otherwise, try the next method. 112 | 113 | ============================================================================== 114 | 4. Completion methods *mucomplete-methods* 115 | 116 | MUcomplete supports all the completion methods described in |ins-completion| 117 | (but not all of them are enabled by default; see |g:mucomplete#chains|). Each 118 | method is identified by a string: 119 | 120 | "c-n" : keywords in 'complete' (search forwards); |i_CTRL-N| 121 | "c-p" : keywords in 'complete' (search backwards); |i_CTRL-P| 122 | "cmd" : Vim command line; |i_CTRL-X_CTRL-V| 123 | "defs": definitions or macros; |i_CTRL-X_CTRL-D| 124 | "dict": keywords in 'dictionary'; |i_CTRL-X_CTRL-K| 125 | "file": file names; |i_CTRL-X_CTRL-F| 126 | "incl": keywords in the current and included files; |i_CTRL-X_CTRL-I| 127 | "keyn": keywords in the current file (search forwards); |i_CTRL-X_CTRL-N| 128 | "keyp": keywords in the current file (search backwards); |i_CTRL-X_CTRL-P| 129 | "line": whole lines; |i_CTRL-X_CTRL-L| 130 | "omni": omni completion ('omnifunc'); |i_CTRL-X_CTRL-O| 131 | "spel": spelling suggestions; |i_CTRL-X_s| 132 | "tags": tags; |i_CTRL-X_CTRL-]| 133 | "thes": keywords in 'thesaurus'; |i_CTRL-X_CTRL-T| 134 | "user": user defined completion ('completefunc'). |i_CTRL-X_CTRL-U| 135 | 136 | Besides, MUcomplete implements its own alternative file completion and 137 | spelling suggestions: 138 | 139 | "path": file names (MUcomplete's implementation). 140 | "uspl": spelling suggestions (MUcomplete's implementation). 141 | 142 | You may also use your own list of words: 143 | 144 | "list": complete words from |b:mucomplete_wordlist| or |g:mucomplete#wordlist|. 145 | 146 | MUcomplete also supports Neosnippet, SnipMate and UltiSnips: 147 | 148 | "nsnp": Neosnippet snippets. 149 | "snip": SnipMate snippets. 150 | "ulti": UltiSnips snippets. 151 | 152 | If you use snippets, please refer to |mucomplete-compatibility| for the 153 | recommended configuration. 154 | 155 | Finally, arbitrary additional completion methods may be defined by the user 156 | with |g:mucomplete#user_mappings|. 157 | 158 | ============================================================================== 159 | 5. Completion chains *mucomplete-chains* 160 | 161 | A (standard) "completion chain" is a List of completion methods. MUcomplete 162 | allows you to define a global completion chain and filetype-specific 163 | completion chains using |g:mucomplete#chains|. For example: 164 | > 165 | let g:mucomplete#chains = { 166 | \ 'default' : ['path', 'omni', 'keyn', 'dict', 'uspl'], 167 | \ 'vim' : ['path', 'cmd', 'keyn'] 168 | \ } 169 | < 170 | The definition above sets the default completion chain to a List of five 171 | completion methods. Such completion chain is used in all buffers except Vim 172 | buffers, because in Vim buffers the default chain is overridden by 173 | a filetype-specific chain consisting of path completion, Vim commands 174 | completion and keyword completion. 175 | 176 | A completion chain may also be a Dictionary defining the chains that must be 177 | active inside certain syntax items in specified filetypes. These are called 178 | "scoped (completion) chains" and are used in the same places where standard 179 | chains may be used. For example: 180 | > 181 | let g:mucomplete#chains = { 182 | \ 'vim' : { 'vimString': [], 183 | \ 'vimLineComment': ['uspl'], 184 | \ 'default': ['path', 'cmd', 'keyn'] }, 185 | \ 'rust' : { 186 | \ 'default' : ['omni', 'nsnp'], 187 | \ 'rustString.*' : [], 188 | \ 'rustComment.*' : ['spel'] } 189 | \ } 190 | < 191 | The assignment above defines the following behaviour in Vim buffers: no 192 | completion inside strings; only spelling suggestions inside comments; path 193 | completion, Vim commands completion and keyword completion in all other 194 | places. It also define the following in rust buffers: a default chain using 195 | omni completion and neosnippets, no completion inside strings, and spelling 196 | completion inside comments (either line or block). For all other filetypes, 197 | the global default chain is used (a global default chain is automatically 198 | defined by MUcomplete if it is not provided by the user). 199 | 200 | The global default chain may also be "scoped". This allows you to tweak your 201 | completion strategy in some nice ways. For instance: 202 | > 203 | let g:mucomplete#chains = { 204 | \ 'default': { 'default': ['keyn'], 205 | \ '.*string.*': [], 206 | \ '.*comment.*': ['uspl'] 207 | \ } 208 | \ } 209 | < 210 | The above setting will suppress completion inside any region matching a string 211 | highlight group and will enable only spell checking inside comments. Note that 212 | the `default` key in the `default` dictionary is mandatory! 213 | 214 | The keys of a scoped chain can be: 215 | 216 | - names of filetype-specific highlight groups, 217 | - regular expressions matching highlight groups, 218 | - the `'default'` key. 219 | 220 | The associated values are standard completion chains (i.e., Lists of 221 | completion methods). If the `'default'` key is not present in a scoped chain, 222 | MUcomplete falls back to using the global completion chain if necessary. 223 | 224 | Note: if a highlight group is matched by multiple keys, one is chosen 225 | non-deterministically. If you use regular expressions as keys for scoped 226 | chains, make sure that they match disjoint sets of strings! 227 | 228 | ============================================================================== 229 | 6. Path completion *mucomplete-path-complete* 230 | 231 | MUcomplete provides two different methods to complete file paths: "file" and 232 | "path". The "file" completion method is based on Vim's built-in file 233 | completion and works exactly as |i_CTRL-X_CTRL-F|. A limitation of the 234 | "file" method is that it does not expand paths containing spaces (in 235 | principle, one could add a space to 'isfname', but that is not recommended: 236 | see 'isfname' for the details). Another limitation is that relative paths are 237 | always completed with respect to the current working directory. 238 | 239 | MUcomplete also implements its own path completion method, called "path", 240 | which is enabled by default. It differs from "file" because no slash (or 241 | backslash in Windows) is appended when completing a path, and paths with 242 | spaces are expanded correctly. Apart from that, the "path" method still uses 243 | 'isfname' to decide which characters define path names. Besides, with the 244 | "path" method it is possible to complete paths relative to the directory of 245 | the current buffer (see |g:mucomplete#buffer_relative_paths|). The "path" 246 | method also honours 'suffixes' and 'wildignore'. 247 | 248 | To adjust the case sensitivity of path matching, see 'fileignorecase' and 249 | 'wildignorecase'. 250 | 251 | See also |mucomplete-tips|. 252 | 253 | ============================================================================== 254 | 7. Spelling suggestions *mucomplete-spel-complete* 255 | 256 | The "spel" method invokes |i_CTRL-X_s| to perform the completion. Such 257 | mapping causes Vim to search for a badly spelled word in the current line 258 | anywhere before the cursor. This is especially puzzling when automatic 259 | completion is on, because Vim's behaviour may make the cursor jump to 260 | a previous, possibly distant, column. 261 | 262 | For this reason, MUcomplete implements an alternative completion method, 263 | called "uspl". This still uses Vim's built-in spelling features (see 264 | |spellbadword()| and |spellsuggest()|), but it looks only at the word in front 265 | of the cursor. It also has a couple of options (see 266 | |mucomplete-customization|). This is the recommended spelling method to use, 267 | especially if you enable automatic completion. It is in the default completion 268 | chain, although it is actively used only when 'spell' is on and 'spelllang' is 269 | defined. 270 | 271 | ============================================================================== 272 | 8. Extending completions *mucomplete-extend-compl* 273 | 274 | Vim has a very nice, though possibly not very well known, feature allowing you 275 | to extend the current completion by copying the words following the previous 276 | expansion in other contexts using the current completion method. This works 277 | for |i_CTRL-X_CTRL-N|, |i_CTRL-X_CTRL-P|, |i_CTRL-X_CTRL-D|, |i_CTRL-X_CTRL-I| 278 | and |i_CTRL-X_CTRL-L| (for line completion, whole lines are copied). 279 | 280 | MUcomplete streamlines such feature with the help of two functions: 281 | > 282 | mucomplete#extend_fwd(keys) 283 | mucomplete#extend_bwd(keys) 284 | < 285 | MUcomplete does not provide mappings by default, though, so you will have to 286 | map those functions in your `vimrc` to enable this feature. The `keys` 287 | argument is the key sequence to use when expanding the mapping in a context 288 | different from completion. 289 | 290 | All this is more easily understood with examples rather than words. Try this: 291 | > 292 | :imap mucomplete#extend_fwd("\") 293 | :set completeopt=menuone,noselect 294 | < 295 | Now type: 296 | > 297 | Shall I compare thee to a summer’s day? 298 | S 299 | < 300 | Another example: 301 | > 302 | New Zealand 303 | New York Times 304 | Ne 305 | < 306 | ============================================================================== 307 | 9. Commands *mucomplete-commands* 308 | 309 | *:MUcompleteAutoOn* 310 | Enable automatic completion. 311 | 312 | *:MUcompleteAutoOff* 313 | Disable automatic completion. 314 | 315 | *:MUcompleteAutoToggle* 316 | Toggle automatic completion. 317 | 318 | *:MUcompleteNotify* 319 | Set the notification level. When set to 0 (which is the default): 320 | > 321 | :MUcompleteNotify 0 322 | < 323 | no notifications are enabled. When set to 1 or 2, a short (1) or long (2) 324 | description of the current completion method is displayed in the command line. 325 | This works best when |showmode| is off (or |cmdheight| is greater than 1) and 326 | |shortmess| contains the `c` flag. 327 | 328 | When set to 3, support for notifications in the status line is activated: in 329 | this case, |g:mucomplete_current_method| can be used in the definition of the 330 | status line, typically to print the current completion method. See 331 | |mucomplete-tips| for an example. 332 | 333 | The default notification messages can be customized via 334 | |g:mucomplete#msg#methods| and |g:mucomplete#msg#short_methods|. 335 | 336 | ============================================================================== 337 | 10. Mappings *mucomplete-mappings* 338 | 339 | By default, MUcomplete maps the keys below in Insert mode. If you do not want 340 | MUcomplete to define any mapping, set |g:mucomplete#no_mappings| or 341 | |no_plugin_maps|. For the definition of each mapping, see |mucomplete-plugs|. 342 | 343 | 344 | Trigger forward chained completion. When the pop-up menu is visible, 345 | select the next menu entry or try the next completion method depending 346 | on the value of |g:mucomplete#cycle_with_trigger|. 347 | 348 | 349 | Trigger backward chained completion. When the pop-up menu is visible, 350 | select the previous menu entry or try the previous completion method 351 | depending on the value of |g:mucomplete#cycle_with_trigger|. 352 | 353 | 354 | When the pop-up menu is visible, try the next completion method that 355 | can be applied. 356 | 357 | 358 | When the pop-up menu is visible, try the previous completion method 359 | that can be applied. 360 | 361 | The mappings above may be overridden in your |vimrc|. For example, to use 362 | and instead of and , use: 363 | > 364 | imap (MUcompleteFwd) 365 | imap (MUcompleteBwd) 366 | < 367 | To use and as cycling keys, use: 368 | > 369 | inoremap (MUcompleteFwdKey) 370 | imap (MUcompleteCycFwd) 371 | inoremap (MUcompleteBwdKey) 372 | imap (MUcompleteCycBwd) 373 | < 374 | Note: if you decide to use your own cycling keys, please be aware that the 375 | keys that are valid in CTRL-X mode are not mapped (see |ins-completion|). This 376 | means, for example, that if you use as a cycling key, such mapping will 377 | be shadowed when the pop-up menu is offering dictionary suggestions, because 378 | CTRL-K is already used by Vim during dictionary completion to search for the 379 | next matching keyword (see |i_CTRL-X_CTRL-K|). 380 | 381 | The following mappings are defined only in Vim 8.0.0282 or older. 382 | 383 | 384 | 385 | 386 | MUcomplete defines a thin wrapper around these keys in Vim 8.0.0282 or 387 | older, without changing their function. If you want to prevent 388 | MUcomplete from defining these three mappings, set 389 | |g:mucomplete#no_popup_mappings|. See also |mucomplete-compatibility| 390 | for suggestions on fixing conflicts with some popular plugins. 391 | 392 | ============================================================================== 393 | 11. Plugs *mucomplete-plugs* 394 | 395 | (MUcompleteFwd) 396 | (MUcompleteBwd) 397 | These are the plugs that trigger manual forward and backward 398 | completion, respectively. They are ultimately mapped to the (possibly 399 | empty) text that completes the current word. 400 | > 401 | imap (MUcompleteFwd) 402 | imap (MUcompleteBwd) 403 | < 404 | (MUcompleteCycFwd) 405 | (MUcompleteCycBwd) 406 | These are the plugs that trigger forward and backward cycling through 407 | the completion chain. They are ultimately mapped to the (possibly 408 | empty) text that completes the current word. 409 | > 410 | imap (MUcompleteCycFwd) 411 | imap (MUcompleteCycBwd) 412 | < 413 | (MUcompleteFwdKey) 414 | (MUcompleteBwdKey) 415 | These are used to preserve the functionality of the cycling keys in 416 | contexts different from completion. They must be redefined when 417 | (MUcompleteCycFwd) and (MUcompleteCycBwd) are remapped by 418 | the user. See |mucomplete-mappings| for an example. 419 | 420 | The following plugs are defined only in Vim 8.0.0282 or older. 421 | 422 | (MUcompletePopupCancel) 423 | (MUcompletePopupAccept) 424 | (MUcompleteCR) 425 | These are used to detect when the pop-up menu is closed with , 426 | or , respectively. They are ultimately mapped to the 427 | corresponding key (, and , respectively). 428 | > 429 | imap (MUcompletePopupCancel) 430 | imap (MUcompletePopupAccept) 431 | imap (MUcompleteCR) 432 | < 433 | ============================================================================== 434 | 12. Customization *mucomplete-customization* 435 | 436 | *'mucomplete#add_user_mapping()'* 437 | Use this function to add a new user-defined completion method. For example: 438 | > 439 | call mucomplete#add_user_mapping("sqla", "\a") 440 | < 441 | The first argument of the function is the name of the completion method and 442 | the second argument is the mapping to be invoked. 443 | 444 | See also |g:mucomplete#user_mappings|. 445 | 446 | Note: you cannot override existing methods. Calling this function with an 447 | existing key is a no-op. 448 | 449 | *'g:mucomplete#always_use_completeopt'* 450 | By default, 'completeopt' does not affect manual completion (when pressing 451 | to complete a word, the first match is always automatically selected and 452 | inserted). Set this to 1 if you want manual completion to behave as specified 453 | by the value of 'completeopt'. 454 | > 455 | let g:mucomplete#always_use_completeopt = 0 456 | < 457 | With this set to 1, you may want to use different values of 'completeopt' for 458 | manual and automatic completion. See |mucomplete-tips| for a possible way to 459 | achieve that. 460 | 461 | *'g:mucomplete#buffer_relative_paths'* 462 | Set to 1 if you want MUcomplete to interpret relative paths as being relative 463 | to the directory of the current buffer. By default, paths are interpreted as 464 | relative to the current working directory (see `:pwd`). 465 | > 466 | let g:mucomplete#buffer_relative_paths = 0 467 | < 468 | Note: this setting affects only the "path" method, not the "file" method. 469 | 470 | *'g:mucomplete#can_complete'* 471 | A Dictionary defining the conditions that must be satisfied for a given method 472 | to be tried. Each condition is a |lambda|, |function()| or |funcref()| with 473 | one argument (the text to be completed), which returns either 1 or 0, 474 | according to whether the corresponding method should be tried or not. The 475 | argument of such functions consists of |g:mucomplete#look_behind| 476 | characters before the cursor. 477 | 478 | When auto-completion is on, by default most completion methods are enabled 479 | when there are at least two keyword characters in front of the cursor (see 480 | 'iskeyword'). The exceptions are file and path completions, which look at 481 | a longer portion of the text (whose length is determined by 482 | |g:mucomplete#look_behind|) and "linguistic" methods (dictionary, spelling, 483 | synonyms), which require two (for dictionary) or three (for spelling and 484 | synonyms) alphabetic characters in front of the cursor. By default, 485 | autocompletion is never triggered after white space, no matter how this option 486 | is set. If you want to allow autocompletion after any printable character (as 487 | defined by |isprint|), set |g:mucomplete#empty_text_auto| to 1. The enabling 488 | patterns defined inside |g:mucomplete#can_complete| should also be adjusted 489 | accordingly (e.g., they should be changed to match white space). 490 | 491 | Note: If you only want to adjust the number of characters before the cursor 492 | needed to trigger auto-completion, see |g:mucomplete#minimum_prefix_length|. 493 | 494 | When completion is triggered manually, one non-whitespace character in front 495 | of the cursor is enough to enable all the methods in the current completion 496 | chain, except for spelling and synonyms, which still require three characters. 497 | When |g:mucomplete#empty_text| is set, completion can be triggered with 498 | even when the cursor is preceded by a space or is located at the start of the 499 | line (this is useful in very limited circumstances). 500 | 501 | If no key is found in |g:mucomplete#can_complete| for the current completion 502 | method, such method is tried unconditionally. 503 | 504 | The default behaviour described above may be changed for each completion 505 | method or overridden based on the filetype. For example, if you put this in 506 | your |vimrc|: 507 | > 508 | let s:spl_cond = { t -> &l:spelllang == 'en' && t =~# '\a\{4}$' } 509 | let s:cpp_cond = { t -> t =~# '\%(->\|::\)$' } 510 | let g:mucomplete#can_complete = {} 511 | let g:mucomplete#can_complete.default = { 'uspl': s:spl_cond } 512 | let g:mucomplete#can_complete.cpp = { 'omni': s:cpp_cond } 513 | < 514 | then MUcomplete will perform a custom check for "uspl" completion in all 515 | buffers (enabling spelling completion only when the language is English and 516 | there are at least four alphabetic characters in front of the cursor), and 517 | a custom check for "omni" completion in cpp buffers (enabling omni-completion 518 | only after -> and ::). In all the other cases, the default conditions will be 519 | checked. 520 | 521 | *'b:mucomplete_chain'* 522 | A List specifying a completion chain, or a Dictionary specifying a scoped 523 | chain, for the current buffer only. When this variable is defined, the value 524 | of |g:mucomplete#chains| is ignored (with one exception: if a scoped chain 525 | without a `'default'` key is used as the value of this variable, then 526 | MUcomplete may fall back to using |g:mucomplete#chains|`['default']`). 527 | 528 | *'g:mucomplete#chains'* 529 | A Dictionary defining the global default chain and filetype-specific 530 | completion chains. Each completion chain may be a standard chain or a scoped 531 | chain. See |mucomplete-chains| for more details. 532 | > 533 | let g:mucomplete#chains = { 534 | \ 'default' : ['path', 'omni', 'keyn', 'dict', 'uspl'], 535 | \ 'vim' : ['path', 'cmd', 'keyn'] 536 | \ } 537 | < 538 | In your |vimrc|, you may override the default or add filetype-specific 539 | completion chains. For example: 540 | > 541 | let g:mucomplete#chains = {} 542 | let g:mucomplete#chains.default = ['omni', 'c-p'] 543 | let g:mucomplete#chains.markdown = ['keyn', 'dict', 'uspl'] 544 | < 545 | *'g:mucomplete#completion_delay'* 546 | Set to a positive value if you want autocompletion to be triggered only when 547 | you pause typing (autocompletion must be on for this to work). When set to 0, 548 | no delay occurs. If this is set to 1, or it is set to a positive integer value 549 | but Vim does not have the |+timers| feature, then |'updatetime'| is used for 550 | the delay (see also |CursorHoldI|). If Vim is built with |+timers| and this is 551 | set to an integer value greater than 1 then the value is interpreted as the 552 | number of milliseconds to wait before triggering auto-completion. 553 | > 554 | let g:mucomplete#completion_delay = 0 555 | < 556 | See also |g:mucomplete#reopen_immediately|. 557 | 558 | Note: auto-completion must be turned off and on again for this setting to take 559 | effect. 560 | 561 | *'g:mucomplete_current_method'* 562 | The name of the last successful completion method. This variable is typically 563 | used in functions invoked after a |MUcompletePmenu| event is triggered. See 564 | |mucomplete-tips| for some examples. 565 | 566 | *'g:mucomplete#cycle_all'* 567 | MUcomplete allows you to use specific completion methods only when the trigger 568 | keys are pressed (/ by default), even when auto-completion is on. 569 | This is achieved by testing |g:mucomplete_with_key| in the enabling conditions 570 | of such methods (see |mucomplete-tips| for an example). 571 | 572 | When the pop-up menu appears automatically, cycling through the completion 573 | methods with and ignores manually activated methods by default. 574 | Set this option to 1 to cycle through all the methods in the current 575 | completion chain regardless of whether they are defined to be activated only 576 | manually or not. 577 | > 578 | let g:mucomplete#cycle_all = 0 579 | < 580 | *'g:mucomplete#cycle_with_trigger'* 581 | Set to 1 to use and to move back and forth, respectively, 582 | through the current completion chain when the pop-up menu is visible. 583 | > 584 | let g:mucomplete#cycle_with_trigger = 0 585 | < 586 | Note: if you set this to 1, you have to use the standard CTRL-N and CTRL-P to 587 | select the entries in the pop-up menu. 588 | 589 | *'b:mucomplete_empty_text'* 590 | *'g:mucomplete#empty_text'* 591 | By default, when you press to complete a word, MUcomplete inserts 592 | a literal Tab character if there is no non-space character before the cursor. 593 | Set this to 1 if you want manual completion to be triggered no matter what the 594 | character in front of the cursor is (|g:mucomplete#can_complete| will still be 595 | applied): 596 | > 597 | let g:mucomplete#empty_text = 0 598 | < 599 | Setting this variable to 1 is useful in very limited circumstances, e.g., to 600 | trigger omni-completion at the start of a line in some buffer types. 601 | 602 | *'b:mucomplete_empty_text_auto'* 603 | *'g:mucomplete#empty_text_auto'* 604 | By default, autocompletion is never activated if the character in front of the 605 | cursor is a space, no matter how |g:mucomplete#can_complete| is defined. Set 606 | this to 1 if you want autocompletion to be triggered no matter what the 607 | character in front of the cursor is (|g:mucomplete#can_complete| will still be 608 | applied): 609 | > 610 | let g:mucomplete#empty_text_auto = 0 611 | < 612 | Setting this variable to 1 is useful in very limited circumstances, e.g., to 613 | trigger omni-completion for tag attributes in HTML buffers. For instance, with 614 | this option set, typing ` 620 | let g:mucomplete#enable_auto_at_startup = 0 621 | < 622 | *'g:mucomplete#force_manual'* 623 | When set to 1, force each completion method in your completion chain to be 624 | tried only when completion is triggered manually (e.g., by pressing ) 625 | even if auto-completion is on. This is useful only if you override 626 | |g:mucomplete#can_complete| for at least one completion method. See 627 | |mucomplete-tips| for an example. 628 | > 629 | let g:mucomplete#force_manual = 0 630 | < 631 | *'g:mucomplete#look_behind'* 632 | This is the maximum number of characters before the cursor that are considered 633 | when deciding which completion methods can be applied. 634 | > 635 | let g:mucomplete#look_behind = 30 636 | < 637 | Most completion methods require a look-behind no greater than three. The 638 | exception is path completion: to determine whether the text before the cursor 639 | may be a path, MUcomplete needs to find a path separator (or a tilde), which 640 | may occur anywhere before the cursor. This option sets a bound on the time 641 | required for the search, but it also means that, if a path component is very 642 | long, MUcomplete may not trigger path completion. If you are dealing with 643 | paths having path components longer than 30 characters, you may need to 644 | increase the value of this option. 645 | 646 | *'g:mucomplete#minimum_prefix_length'* 647 | The minimum number of (keyword) characters that must be present before the 648 | cursor for automatic completion to be triggered. 649 | > 650 | let g:mucomplete#minimum_prefix_length = 2 651 | < 652 | Note: this setting does not affect all completion methods. In particular, it 653 | does not change the behaviour of `'dict'`, `'file'`, `'path'`, `'spel'`, 654 | `'thes'`, and `'uspl'`. 655 | 656 | Note: this setting is ignored for completion method whose activation condition 657 | (see |g:mucomplete#can_complete|) has been overridden by the user. 658 | 659 | *'g:mucomplete#msg#methods'* 660 | A Dictionary mapping each completion method's string to a description. 661 | Descriptions can be overridden and additional entries can be added by the 662 | user. For example: 663 | > 664 | let g:mucomplete#msg#methods = { 665 | \ 'keyn': 'Mots-clés dans le fichier courant', 666 | \ 'xywz: 'Description of my custom xywz method' 667 | \ } 668 | < 669 | Such descriptions are used in notifications (see |MUcompleteNotify|). 670 | 671 | *'g:mucomplete#msg#short_methods'* 672 | Similar to |g:mucomplete#msg#methods|, but contains shorter descriptions, 673 | suitable for small screens or for displaying messages in the status line. 674 | 675 | *'g:mucomplete#no_mappings'* 676 | When set to 1, MUcomplete does not define any mapping. 677 | > 678 | let g:mucomplete#no_mappings = 0 679 | < 680 | Note: MUcomplete also honours |no_plugin_maps|. 681 | 682 | *'g:mucomplete#no_popup_mappings'* 683 | Set to 1 to prevent MUcomplete from mapping , and . 684 | 685 | > 686 | let g:mucomplete#no_popup_mappings = 0 687 | < 688 | You may safely set this variable to 1 if you use manual completion 689 | exclusively. These mappings, however, are necessary for automatic completion 690 | in Vim versions older than v8.0.0283, so if you disable them (likely because 691 | they conflict with some other plugin or with your own mappings), you will need 692 | to provide alternative definitions in your |vimrc|. This is how they are 693 | defined by MUcomplete: 694 | > 695 | imap (MUcompletePopupCancel) 696 | imap (MUcompletePopupAccept) 697 | imap (MUcompleteCR) 698 | < 699 | Note: Only for Vim 8.0.0282 or older. MUcomplete does not map , and 700 | in recent Vim versions, so this option does nothing in Vim 8.0.0283 or 701 | later. 702 | 703 | *'g:mucomplete#popup_direction'* 704 | > 705 | let g:mucomplete#popup_direction = {'c-p': -1, 'keyp': -1, 'line': -1} 706 | < 707 | MUcomplete by default follows the "natural" direction of each completion 708 | method. Except for |i_CTRL-X_CTRL-L|, |i_CTRL-P| and |i_CTRL-X_CTRL-P|, Vim 709 | always starts by selecting the first (topmost) entry in the pop-up menu; for 710 | |i_CTRL-X_CTRL-L|, |i_CTRL-P| and |i_CTRL-X_CTRL-P|, though, Vim highlights 711 | the last (bottomost) entry instead. Therefore, when you press to select 712 | the "next" entry in the pop-up menu, MUcomplete moves downwards in most cases; 713 | for the exceptions mentioned above, though, moves from bottom to top. In 714 | all cases, you may use to move in the opposite direction. 715 | 716 | The default behaviour may be overridden for each completion type by setting 717 | |g:mucomplete#popup_direction| in your |vimrc|. The value of this variable is 718 | a Dictionary mapping completion methods to 1 or -1, where 1 means "select from 719 | top to bottom" and -1 means "select from bottom to top". For instance, if you 720 | want "path" completion to be bottom-to-top, you need to put this in your 721 | |vimrc|: 722 | > 723 | let g:mucomplete#popup_direction = { 'path' : -1 } 724 | < 725 | If you also want to invert the direction of "c-p" completion, you may write: 726 | > 727 | let g:mucomplete#popup_direction = { 'path' : -1, 'c-p': 1 } 728 | < 729 | For the completion methods not explicitly mentioned in the value of 730 | |g:mucomplete#popup_direction|, the natural value is assumed, i.e., -1 for 731 | "c-p", "keyp" and "line", and 1 for all the other methods. 732 | 733 | *'g:mucomplete#reopen_immediately'* 734 | With autocompletion on and the pop-up menu open, if the user keeps typing 735 | until the pop-up menu eventually closes, MUcomplete immediately attemps to 736 | complete the current text again. Set this to 0 if you want MUcomplete to wait 737 | for the time specified by |g:mucomplete#completion_delay|. 738 | > 739 | let g:mucomplete#reopen_immediately = 1 740 | < 741 | To appreciate the effect of this option, open a new buffer and set: 742 | > 743 | set spell spelllang=en 744 | let g:mucomplete#completion_delay=1000 745 | < 746 | Now type: 747 | > 748 | sure 749 | su 750 | < 751 | and wait one second. If you are using the default completion chain, Vim will 752 | offer you to complete with `sure`. With the pop-up menu open, keep typing: 753 | > 754 | sure 755 | surel 756 | < 757 | As soon as you type `l` the pop-up menu closes and reopens again, offering 758 | spelling suggestions. Now set this options to 0: 759 | > 760 | let g:mucomplete#reopen_immediately = 0 761 | < 762 | and repeat the experiment. You should see that after typing `l` the pop-up 763 | menu is reopened with a delay. 764 | 765 | Note: this option affects the behaviour of delayed completion only when timers 766 | are used. It has no effect if Vim is compiled without |+timers| or if 767 | |g:mucomplete#completion_delay| is set to 0. Do NOT set this option to 0 if 768 | |g:mucomplete#completion_delay| is set to 1. 769 | 770 | Note: This option requires Vim 8.0.0283 or later. 771 | 772 | *'g:mucomplete#spel#good_words'* 773 | Set to 1 if you want spelling suggestions (similar words) even for words that 774 | are spelled correctly. By default, no suggestions are returned for good words 775 | by the "uspl" method. 776 | > 777 | let g:mucomplete#spel#good_words = 0 778 | < 779 | Note: this setting does not affect the "spel" method. 780 | 781 | *'g:mucomplete#spel#max'* 782 | The maximum number of spelling suggestions offered by the "uspl" method. 783 | > 784 | let g:mucomplete#spel#max = 25 785 | < 786 | Note: this setting does not affect the "spel" method. 787 | 788 | *'g:mucomplete#spel#regex'* 789 | The regular expression used to search for matches during spell checking. The 790 | default matches the Latin alphabetic characters plus a wide range of UTF 791 | symbols with diacriticals. 792 | > 793 | let g:mucomplete#spel#regex = 794 | \ '[A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]' 795 | < 796 | *'g:mucomplete#tab_when_no_results'* 797 | Set to 1 if you want a literal Tab character to be inserted when manually 798 | triggered completion does not produce any completion. 799 | > 800 | let g:mucomplete#tab_when_no_results = 0 801 | < 802 | *'g:mucomplete#ultisnips#match_at_start'* 803 | By default, the "ulti" method returns the snippets whose name starts with 804 | the word in front of the cursor. Set this to 0 to return all the snippets that 805 | contain the word in front of the cursor. 806 | > 807 | let g:mucomplete#ultisnips#match_at_start = 1 808 | < 809 | *'g:mucomplete#use_only_windows_paths'* 810 | When this option is set, path completion in Windows uses only backslashes. 811 | By default, paths with forward slashes are completed as well. 812 | > 813 | let g:mucomplete#use_only_windows_paths = 0 814 | < 815 | Note: if 'shellslash' is set, only paths with forward slashes are used, no 816 | matter what the value of this option is. 817 | 818 | Note: this option is relevant only for Windows users. 819 | 820 | *'g:mucomplete#user_mappings'* 821 | A Dictionary of user-defined completion methods. For example: 822 | > 823 | let g:mucomplete#user_mappings = { 824 | \ 'sqla' : "\a", 825 | \ 'xyz' : "\=MyCustomComplete()\" 826 | \ } 827 | < 828 | Each key in the dictionary is an arbitrary string providing the name of the 829 | completion method (but you cannot override the predefined names) and the 830 | corresponding value is the mapping that triggers the desired completion. 831 | 832 | User-defined completion methods are used exactly as predefined methods. For 833 | example: 834 | > 835 | let g:mucomplete#chains = {} 836 | let g:mucomplete#chains.default = ['keyp', 'xyz'] 837 | let g:mucomplete#chains.sql = ['sqla', 'keyp', 'tags'] 838 | < 839 | Note: this variable is read only once when MUcomplete is loaded. If you want 840 | to define completion methods later (for example, in some ftplugin file), use 841 | |mucomplete#add_user_mapping()| instead. 842 | 843 | *'g:mucomplete_with_key'* 844 | Read-only flag that tells whether completion was initiated manually by the 845 | user or it was triggered automatically. See |mucomplete-tips| for an example. 846 | 847 | Note: do not change the value of this variable! 848 | 849 | *'b:mucomplete_wordlist'* 850 | A sorted List of words to be used with the "list" method. When this variable 851 | is defined, |g:mucomplete#wordlist| is ignored. 852 | 853 | *'g:mucomplete#wordlist'* 854 | A Dictionary of sorted lists of words to be used with the "list" method. The 855 | keys of the dictionary are filetypes or the `'default'` keyword. A list keyed 856 | on a filetype is used if the buffer is set to that filetype; otherwise, the 857 | `'default'` list is used, if defined. For instance: 858 | > 859 | let g:mucomplete#wordlist = { 860 | \ 'default': ['January', 'July', 'June'], 861 | \ 'js': ['console.log()', 'console.trace()'] 862 | \ } 863 | let g:mucomplete#chains = { 'default': ['list', 'keyp'] } 864 | < 865 | Note: You may also use these lists in a user completion function by setting: 866 | > 867 | set completefunc=mucomplete#list#completefunc 868 | let g:mucomplete#chains = { 'default': ['user'] } 869 | < 870 | *MUcompletePmenu* 871 | A |User| |autocmd| that is fired when the pop-up menu becomes visible. The 872 | user can hook to this to perform arbitrary operations upon successful 873 | completion. For example: 874 | > 875 | autocmd User MUcompletePmenu call MyFunction() 876 | 877 | The name of the currently used completion method is available inside 878 | `MyFunction()` through |g:mucomplete_current_method|. See |mucomplete-tips| 879 | for an example. 880 | 881 | ============================================================================== 882 | 13. Tips & tricks *mucomplete-tips* 883 | 884 | How to insert a literal tab character when is used by MUcomplete? ~ 885 | Use CTRL-V (or CTRL-Q if CTRL-V is mapped). See |i_|. 886 | Another possibility is to set |g:mucomplete#tab_when_no_results| to 1 to have 887 | a tab character inserted when there are no completions. 888 | 889 | I want to do something special with in some circumstances, ~ 890 | but I also want to keep using it with MUcomplete. How may I achieve ~ 891 | that? ~ 892 | You may adapt the following snippet: 893 | > 894 | fun! MyTabAction() 895 | if some_condition_is_verified 896 | " Do something 897 | return "" 898 | else 899 | return "\(MyFwd)" 900 | endif 901 | endf 902 | 903 | imap (MyFwd) (MUcompleteFwd) 904 | imap MyTabAction() 905 | < 906 | MUcomplete does not always insert a new line when I press Enter… ~ 907 | When the pop-up menu is closed by pressing , sometimes Vim does not 908 | insert a new line. If you always want a new line to be inserted, proceed as 909 | follows. If you use Vim 8.0.0283 or later, put this in your `vimrc`: 910 | > 911 | inoremap pumvisible() ? "" : "" 912 | < 913 | If you use a Vim version older than 8.0.0283, put this in your `vimrc` 914 | instead: 915 | > 916 | imap pumvisible() ? "(MUcompleteCR)" 917 | : "(MUcompleteCR)" 918 | < 919 | How to simulate ZSH behaviour for "file" completion? ~ 920 | Some people like ZSH behaviour, whereby typing a slash enters the current 921 | directory. This can be easily achieved by defining the following mapping in 922 | your |vimrc|: 923 | > 924 | function! IsBehindDir() 925 | return strpart(getline('.'), 0, col('.') - 1) =~# '\f\+/$' 926 | endfunction 927 | 928 | imap / pumvisible() && IsBehindDir() 929 | \ ? "\\(MUcompleteFwd)" 930 | \ : '/' 931 | < 932 | Use different values of completeopt ~ 933 | If you want to use different values of 'completeopt' (or other settings) for 934 | manual and automatic completion, you may adapt the following snippet: 935 | > 936 | fun! ToggleCompleteopt() 937 | MUcompleteAutoToggle 938 | if exists('#MUcompleteAuto') 939 | " Settings for automatic completion 940 | set completeopt+=noinsert,noselect 941 | else 942 | " Settings for manual completion 943 | set completeopt-=noinsert,noselect 944 | endif 945 | endf 946 | 947 | command! MyMUcompleteToggle call ToggleCompleteopt() 948 | < 949 | Put the code above in your |vimrc|. Please keep in mind that the value of 950 | 'completeopt' is ignored for manual completion (except for spelling 951 | suggestions), unless |'g:mucomplete#always_use_completeopt'| is set to 1. 952 | 953 | Enable a completion method only when typing ~ 954 | Some completion methods are inherently slow, and it doesn't make much sense to 955 | trigger them automatically, because they would be called too frequently. Yet, 956 | you might want to trigger them manually by pressing . This can be 957 | achieved by testing the value of |g:mucomplete_with_key| in a custom check. 958 | 959 | For instance, suppose that you are using automatic completion and you want to 960 | use thesaurus completion. Searching for synonyms after each key press would be 961 | too slow (and pointless). To work around this problem, in your |vimrc| you may 962 | define: 963 | > 964 | let g:mucomplete#can_complete = {} 965 | let g:mucomplete#can_complete.default = { 966 | \ 'thes': { 967 | \ t -> g:mucomplete_with_key && strlen(&l:thesaurus) > 0 968 | \ } 969 | \ } 970 | " Add "thes" to your completion chains, e.g.: 971 | let g:mucomplete#chains = { 'default': ['keyn', 'thes'] } 972 | < 973 | Then, searching for synonyms will happen only when you press and keyword 974 | completion returns no results, or when you press . During normal 975 | typing, only keyword completion will be active. 976 | 977 | If you find yourself adding checks of the form `g:mucomplete_with_key && ...` 978 | to all your completion methods except one or two, you may find it more 979 | convenient to set |g:mucomplete#force_manual| to 1 and redefine only the 980 | methods that should be enabled for automatic completion. In other words, the 981 | configuration above might be rewritten as follows: 982 | > 983 | let g:mucomplete#force_manual = 1 " All methods enabled only manually 984 | let g:mucomplete#can_complete = {} 985 | let g:mucomplete#can_complete.default = { 986 | \ 'keyn': { t -> { t -> t =~# '\m\k\k$' } } 987 | \ } 988 | let g:mucomplete#chains = { 'default': ['keyn', 'thes'] } 989 | < 990 | With these settings, all the methods in your completion chain, except for 991 | `'keyn'`, will be tried only with manual completion: but keyword completion 992 | will be triggered automatically. 993 | 994 | Optimize your completion chains ~ 995 | The "c-n", "c-p" and "line" methods allow you to aggregate completion 996 | suggestions from several sources (see 'complete'), including dictionaries and 997 | tags. While this is handy, it may have a couple of drawbacks: first, you may 998 | get too many suggestions, making completion less useful; second, you may incur 999 | an efficiency penalty, especially if you have big tag files or dictionaries or 1000 | many included files. This may slows you down noticeably, in particular when 1001 | automatic completion is on. 1002 | 1003 | You may then optimize your work flow by using longer completion chains and 1004 | reducing the options in 'complete' accordingly. For example, instead of: 1005 | > 1006 | set complete+=i 1007 | set complete+=t 1008 | let g:mucomplete#chains = { 'default' : ['c-p'] } 1009 | < 1010 | which would always scan tags and included files, you might use: 1011 | > 1012 | set complete-=i 1013 | set complete-=t 1014 | let g:mucomplete#chains = { 'default' : ['c-p', 'incl', 'tags'] } 1015 | < 1016 | so that searching included files and/or tags will happen only when 1017 | completion cannot be performed otherwise. 1018 | 1019 | If you use 'dictionary' completion and want to ensure that common words are 1020 | suggested first when completing, then install 1021 | https://github.com/Konfekt/complete-common-words.vim 1022 | 1023 | How to show the currently active completion method in the status line? ~ 1024 | Activate level 3 notifications: 1025 | > 1026 | :MUcompleteNotify 3 1027 | < 1028 | Then use |g:mucomplete_current_method| inside the definition of your status 1029 | line. A minimal example: 1030 | > 1031 | set statusline=%{get(g:,'mucomplete_current_method','')} 1032 | < 1033 | A more realistic example: 1034 | > 1035 | fun! MU() 1036 | return get(g:mucomplete#msg#short_methods, 1037 | \ get(g:, 'mucomplete_current_method', ''), '') 1038 | endf 1039 | 1040 | set statusline=%<%f\ %h%m%r%=\%{MU()}\ %-14.(%l,%c%V%)\ %P 1041 | < 1042 | I want to customize/colorize/foofoofy the notification messages! ~ 1043 | You can hook to |MUcompletePmenu| directly instead of using 1044 | |MUcompleteNotify|. For example, to display colorized messages: 1045 | > 1046 | fun! ColorfulMessages() 1047 | echohl Label 1048 | unsilent echo "[MUcomplete] " 1049 | echohl Special 1050 | unsilent echon get(g:mucomplete#msg#methods, 1051 | \ get(g:, 'mucomplete_current_method', '')) 1052 | echohl None 1053 | let &ro=&ro " Force updating the cursor 1054 | endfun 1055 | 1056 | autocmd User MUcompletePmenu call ColorfulMessages() 1057 | " Clear the command line when the menu is dismissed 1058 | autocmd CompleteDone * echo "\r" 1059 | < 1060 | ============================================================================== 1061 | 14. Compatibility *mucomplete-compatibility* 1062 | 1063 | MUcomplete tries to be a responsible citizen in Vimland. This section 1064 | describes how to make it peacefully coexist with other Vim citizens. 1065 | 1066 | Auto Pairs ~ 1067 | This plugin maps in Insert mode in ways that conflict with 1068 | MUcomplete's operation. To resolve the conflict, put this in your |vimrc|: 1069 | > 1070 | let g:AutoPairsMapSpace = 0 1071 | imap pumvisible() 1072 | \ ? "" 1073 | \ : "=AutoPairsSpace()" 1074 | < 1075 | If you use Vim 8.0.0282 or older, you must also remap : 1076 | > 1077 | let g:AutoPairsMapCR = 0 1078 | imap MyCR (MUcompleteCR)AutoPairsReturn 1079 | imap MyCR 1080 | < 1081 | Mapping things this way will also make MUcomplete and auto-pairs work well 1082 | together with endwise.vim (see below). 1083 | 1084 | Auto Pairs + SnipMate ~ 1085 | See SnipMate + Auto Pairs configuration below. 1086 | 1087 | Auto Pairs + UltiSnips ~ 1088 | See UltiSnips + Auto Pairs configuration below. 1089 | 1090 | endwise.vim ~ 1091 | If you use Vim 8.0.0283 or later, MUcomplete works just fine with endwise. 1092 | 1093 | With older versions of Vim, both MUcomplete and endwise map in Insert 1094 | mode, so you must resolve the conflict. The simplest way is to override 1095 | MUcomplete's definition of in your |vimrc|, as follows: 1096 | > 1097 | imap MyCR (MUcompleteCR) 1098 | imap MyCR 1099 | < 1100 | If you use endwise.vim together with auto-pairs, see the section above 1101 | instead. 1102 | 1103 | LanguageClient-neovim ~ 1104 | MUcomplete works fine with this plugin and its satellite server plugins, but 1105 | for the best results you should enable a short delay (this requires Vim 1106 | 8.0.0283 or later compiled with |+timers|): 1107 | > 1108 | let g:mucomplete#completion_delay = 50 1109 | let g:mucomplete#reopen_immediately = 0 1110 | < 1111 | You might need or want to adjust the delay. You need to increase the delay if 1112 | you notice that MUcomplete triggers completion "too early", as if the last 1113 | typed character is ignored. 1114 | 1115 | If you have other issues with LanguageClient-neovim, first of all make sure 1116 | that omni-completion works without MUcomplete (i.e., by typing CTRL-X CTRL-O). 1117 | See also |mucomplete-troubleshooting|. If that works, but MUcomplete does not 1118 | offers the same completions, consider providing some |mucomplete-feedback|. 1119 | 1120 | Neosnippet ~ 1121 | MUcomplete works out of the box with Neosnippet. Just add the `'nsnp'` method 1122 | to your completion chain. For example: 1123 | > 1124 | let g:mucomplete#chains = {} 1125 | let g:mucomplete#chains.default = ['path', 'nsnp', 'keyn'] 1126 | < 1127 | If you want snippets to be expanded automatically when you accept a menu entry 1128 | with Enter, add the following code to your `vimrc`: 1129 | > 1130 | inoremap 1131 | \ mucomplete#neosnippet#expand_snippet("\") 1132 | imap 1133 | < 1134 | The argument of the function is the expansion to be used when is typed in 1135 | a context different from completion (typically, it's itself). Using 1136 | a plug improves compatibility with some plugins that map in Insert mode 1137 | (e.g., endwise.vim). 1138 | 1139 | If you need more flexibility and you know what you are doing, you may call 1140 | `mucomplete#neosnippet#do_expand()` directly. 1141 | 1142 | Neovim ~ 1143 | Starting with version 0.11, Neovim maps Tab and Shift-Tab by default. 1144 | MUcomplete will not remap those keys. If you want to use manual completion, 1145 | you have to map (MUcompleteFwd) and (MUcompleteBwd) as explained 1146 | in |mucomplete-mappings|. 1147 | 1148 | SnipMate ~ 1149 | In your |vimrc|, set: 1150 | > 1151 | let g:snipMate = {} 1152 | let g:snipMate['no_match_completion_feedkeys_chars'] = '' 1153 | < 1154 | Then, add the `'snip'` method to your completion chain(s). For example: 1155 | > 1156 | let g:mucomplete#chains = { 'default': ['snip', 'keyn'] } 1157 | < 1158 | If you want snippets to be expanded automatically when you accept a menu entry 1159 | with Enter, also add the following code to your `vimrc`: 1160 | > 1161 | inoremap MyEnter 1162 | imap MyCR (pumvisible() 1163 | \ ? "\\snipMateTrigger" 1164 | \ : "\MyEnter") 1165 | imap MyCR 1166 | < 1167 | Using a plug improves compatibility with some plugins that map in Insert 1168 | mode (e.g., endwise.vim). 1169 | 1170 | SnipMate + Auto Pairs ~ 1171 | If you want snippets to be expanded automatically when you accept a menu entry 1172 | with Enter and you are also using Auto Pairs, use the following snippet 1173 | instead of the snippet above: 1174 | > 1175 | let g:AutoPairsMapCR = 0 1176 | 1177 | inoremap MyEnter 1178 | imap MyCR (pumvisible() 1179 | \ ? "\\snipMateTrigger" 1180 | \ : "\MyEnterAutoPairsReturn") 1181 | imap MyCR 1182 | 1183 | UltiSnips ~ 1184 | UltiSnips maps and in a way that conflicts with MUcomplete. The 1185 | recommended way to resolve the conflict is to redefine UltiSnips's mappings. 1186 | For example: 1187 | > 1188 | let g:UltiSnipsExpandTrigger = "" " Do not use 1189 | let g:UltiSnipsJumpForwardTrigger = "" " Do not use 1190 | < 1191 | If you want snippets to be expanded automatically when you accept a menu entry 1192 | with Enter, also add the following code to your `vimrc`: 1193 | > 1194 | inoremap MyCR 1195 | \ mucomplete#ultisnips#expand_snippet("\") 1196 | imap MyCR 1197 | < 1198 | Using a plug improves compatibility with some plugins that map in Insert 1199 | mode (e.g., endwise.vim). 1200 | 1201 | The argument of the function is the expansion to be used when is typed in 1202 | a context different from completion (typically, it's itself). 1203 | 1204 | If you need more flexibility and you know what you are doing, you may call 1205 | `mucomplete#ultisnips#do_expand()` directly. 1206 | 1207 | It is also possible to expand snippets or complete text using only . That 1208 | is, when you press , if there is a snippet keyword before the cursor then 1209 | the snippet is expanded (and you may use also to jump between the 1210 | snippet triggers), otherwise MUcomplete kicks in. The following configuration 1211 | achieves this kind of behaviour: 1212 | > 1213 | let g:ulti_expand_or_jump_res = 0 1214 | 1215 | fun! TryUltiSnips() 1216 | if !pumvisible() " With the pop-up menu open, let Tab move down 1217 | call UltiSnips#ExpandSnippetOrJump() 1218 | endif 1219 | return '' 1220 | endf 1221 | 1222 | fun! TryMUcomplete() 1223 | return g:ulti_expand_or_jump_res ? "" : "\(MUcompleteFwd)" 1224 | endf 1225 | 1226 | inoremap (TryUlti) =TryUltiSnips() 1227 | imap (TryMU) TryMUcomplete() 1228 | imap "\(TryUlti)\(TryMU)" 1229 | < 1230 | You still need to redefine UltiSnips's mappings as explained above. 1231 | 1232 | UltiSnips + Auto Pairs ~ 1233 | If you want snippets to be expanded as explained above and you are using Auto 1234 | Pairs, you need to disable Auto Pairs's mappings and invoke them in custom 1235 | mappings, as follows: 1236 | > 1237 | let g:AutoPairsMapCR = 0 1238 | let g:AutoPairsMapSpace = 0 1239 | imap pumvisible() 1240 | \ ? "" 1241 | \ : "=AutoPairsSpace()" 1242 | 1243 | inoremap UltiExpand 1244 | \ mucomplete#ultisnips#expand_snippet("\") 1245 | imap MyCR UltiExpandAutoPairsReturn 1246 | imap MyCR 1247 | < 1248 | UltiSnips + PHP ~ 1249 | In some versions of Vim, there is a (now solved) compatibility issue between 1250 | PHP's 'omnifunc' function and UltiSnips. This bug is hit by MUcomplete when: 1251 | 1252 | - automatic completion is on; 1253 | - the "omni" method is in your completion chain; 1254 | - you try to move between the different parts of a snippet while expanding 1255 | a snippet (and you discover that you can't). 1256 | 1257 | There are two workarounds if you still want to use UltiSnips with PHP: 1258 | 1259 | - remove "omni" from PHP's completion chain; 1260 | - disable automatic completion (and do not trigger completion during snippet 1261 | expansion). 1262 | 1263 | Note: this is not a bug in MUcomplete. 1264 | 1265 | vim-peekabo ~ 1266 | By default, vim-peekabo remaps in Insert mode. Since MUcomplete relies 1267 | on |i_CTRL-R| in an essential way, you have to change vim-peekabo's mapping: 1268 | > 1269 | let g:peekaboo_ins_prefix = '' 1270 | < 1271 | Note: now you need to press to view the registers. 1272 | 1273 | ============================================================================== 1274 | 15. Troubleshooting *mucomplete-troubleshooting* 1275 | 1276 | Why am I getting the error: "E227: mapping already exists for..."? ~ 1277 | MUcomplete takes great care not to override an existing mapping defined in 1278 | your |vimrc| or by another plugin. If you get this error, it means that 1279 | MUcomplete cannot define one of its own mappings, because it is already 1280 | defined elsewhere. For example, UltiSnips and Matchem map CTRL-J in Insert 1281 | mode, which causes this error as soon as MUcomplete kicks in: 1282 | > 1283 | E227: mapping already exists for ^@ 1284 | < 1285 | (^@ is CTRL-J). To discover where the mapping was last defined, use: 1286 | > 1287 | :verbose imap 1288 | < 1289 | To fix the conflict, redefine one of the conflicting mappings. See 1290 | |mucomplete-mappings| if you decide to override one of MUcomplete's mappings. 1291 | 1292 | I think I have found a bug. What should I do? ~ 1293 | Before reporting a bug, please do the following: 1294 | 1295 | - In order to rule out conflicts with other settings, please copy 1296 | troubleshooting_vimrc.vim from MUcomplete's directory into your .vim 1297 | directory, edit it, and run Vim with: 1298 | > 1299 | vim -u troubleshooting_vimrc.vim 1300 | < 1301 | Can you still reproduce your problem? If not, a conflict with another plugin 1302 | or a setting in your |vimrc| may be the culprit. 1303 | 1304 | - Double-check your completion chains: > 1305 | 1306 | echo g:mucomplete#chains 1307 | < 1308 | Also, check whether |b:mucomplete_chain| is defined, because its value 1309 | shadows the global dictionary. Are the methods you expect to be used defined 1310 | and in the correct order? 1311 | 1312 | - Some completion methods are enabled conditionally. For example, dictionary 1313 | completion may be triggered only if 'dictionary' is set in the current 1314 | buffer. If you have trouble with a conditionally enabled completion method, 1315 | please check whether the corresponding condition is satisfied (see 1316 | |g:mucomplete#can_complete|). 1317 | 1318 | - Make sure that is not mapped in Insert mode. The following command 1319 | should return "No mapping found": > 1320 | 1321 | :imap 1322 | < 1323 | - Turn off automatic completion: > 1324 | 1325 | :MUcompleteAutoOff 1326 | < 1327 | and try to complete a word using the corresponding mapping (see 1328 | |ins-completion| for a list of available mappings). For example, for omni 1329 | completion, use |i_CTRL-X_CTRL-O|. Do you get a different output compared to 1330 | what MUcomplete provides? If not, then the problem is not MUcomplete. 1331 | 1332 | If triggering completion manually results in the expected behaviour, but 1333 | MUcomplete behaves differently, please report the bug. 1334 | 1335 | ============================================================================== 1336 | 16. Providing feedback *mucomplete-feedback* 1337 | 1338 | For bug reports and feature requests please use: 1339 | 1340 | https://github.com/lifepillar/vim-mucomplete/issues 1341 | 1342 | Pull requests are welcome, too! 1343 | 1344 | ============================================================================== 1345 | 17. Implementation details *mucomplete-internals* 1346 | 1347 | This section describes some technicalities of MUcomplete's implementation, and 1348 | is not intended for the regular user: it is mostly a memo for myself and 1349 | a reading for those interested in a few subtleties of the source code. 1350 | 1351 | What the hell is (MUcompleteOut) for? Why is it defined to be ~ 1352 | ? ~ 1353 | To be able to sequentially try different completion methods, MUcomplete needs 1354 | to make sure that Vim is not in |i_CTRL-X| sub-mode before trying a completion 1355 | mapping. Since recently, there was no way in Vim to check that. So, the idea 1356 | was to use a key sequence that (1) exits CTRL-X sub-mode when Vim is in CTRL-X 1357 | submode, and (2) does nothing when typed out of CTRL-X mode. There are a few 1358 | such key sequences, and eventually MUcomplete settled to use , as it 1359 | is one of the simplest. A possible side effect of that sequence is that it may 1360 | trigger a beep, but that can be suppressed by adding `ctrlg` to |belloff|. 1361 | 1362 | As of Vim 8.2.3389, Vim provides to stop insert mode completion 1363 | without side effects. MUcomplete uses if possible. 1364 | 1365 | What's the purpose of computing an empty string in the value returned by ~ 1366 | s:next_method()? ~ 1367 | Well, if you remove that expression (=''), the completion 1368 | mechanism messes up. Honestly, I do not know why :) I suspect it has to do 1369 | with type ahead or buffering, but if you can enlighten me, I'd appreciate that 1370 | :) 1371 | 1372 | Why is there a double in the expression returned by s:next_method()? ~ 1373 | In principle, one should be enough. But using two makes MUcomplete more 1374 | robust against interruptions. 1375 | 1376 | A completion mapping may start a long computation (e.g., thesaurus 1377 | completion), which the user may want to interrupt by pressing CTRL-C. For some 1378 | reason, pressing CTRL-C causes the next character fed to Vim to be eaten 1379 | (, in this case). I don't know exactly why that happens, but a workaround 1380 | is to use instead of just . The first is then eaten, but 1381 | the second one allows the following expression to be evaluated correctly. 1382 | 1383 | Fortunately, although |i_CTRL-R_CTRL-R| and |i_CTRL-R| are not functionally 1384 | equivalent, their differences do not matter in the context in which they are 1385 | used by MUcomplete. 1386 | 1387 | See also https://github.com/vim/vim/issues/1260. 1388 | 1389 | Why is "cmd" treated specially by s:verify_completion()? ~ 1390 | Because of a Vim bug. See https://github.com/vim/vim/issues/1319. 1391 | 1392 | Does MUcomplete's implementation have any limitations? ~ 1393 | Of course! But very few :) 1394 | Fuzzy completion is not supported and will likely never be. This doesn't 1395 | bother me much, but it might be a showstopper for you. 1396 | 1397 | There is no room for asynchronous computation, given the way MUcomplete is 1398 | implemented (how could the fallback mechanism work then?). If you think that 1399 | auto-completion should be asynchronous, fortunately there is no lack of 1400 | plugins. Do not take it for granted, though, that "asynchronous" means 1401 | "faster": in general, the time Vim spends in MUcomplete's code is negligible 1402 | compared to the time it takes to populate the pop-up menu. Asynchronous 1403 | plugins typically minimize the impact of the latter task (by delegating it to 1404 | an async job), but unless they are carefully implemented, Vim may spend 1405 | a significant amount of time running their code. Profile your plugins! 1406 | 1407 | Finally, one thing that does bother me is that MUcomplete cannot exploit the 1408 | optimization provided by |complete_add()| and |complete_check()| in user 1409 | completion functions (see |E840| for an example). The reason is that 1410 | MUcomplete sends a immediately after each completion mapping, 1411 | effectively preventing further keys to be passed along to the buffer. So, 1412 | a user completion function cannot be interrupted by further key presses. 1413 | Unfortunately, as discussed above, sending is required for 1414 | synchronization purposes: without , s:verify_completion() may be called 1415 | too early, i.e., when the pop-up menu has not appeared yet (but it is going to 1416 | appear, because completion was successful). 1417 | 1418 | vim:tw=78:ts=8:noet:ft=help:norl: 1419 | 1420 | -------------------------------------------------------------------------------- /doc/tags: -------------------------------------------------------------------------------- 1 | 'b:mucomplete_chain' mucomplete.txt /*'b:mucomplete_chain'* 2 | 'b:mucomplete_empty_text' mucomplete.txt /*'b:mucomplete_empty_text'* 3 | 'b:mucomplete_empty_text_auto' mucomplete.txt /*'b:mucomplete_empty_text_auto'* 4 | 'b:mucomplete_wordlist' mucomplete.txt /*'b:mucomplete_wordlist'* 5 | 'g:mucomplete#always_use_completeopt' mucomplete.txt /*'g:mucomplete#always_use_completeopt'* 6 | 'g:mucomplete#buffer_relative_paths' mucomplete.txt /*'g:mucomplete#buffer_relative_paths'* 7 | 'g:mucomplete#can_complete' mucomplete.txt /*'g:mucomplete#can_complete'* 8 | 'g:mucomplete#chains' mucomplete.txt /*'g:mucomplete#chains'* 9 | 'g:mucomplete#completion_delay' mucomplete.txt /*'g:mucomplete#completion_delay'* 10 | 'g:mucomplete#cycle_all' mucomplete.txt /*'g:mucomplete#cycle_all'* 11 | 'g:mucomplete#cycle_with_trigger' mucomplete.txt /*'g:mucomplete#cycle_with_trigger'* 12 | 'g:mucomplete#empty_text' mucomplete.txt /*'g:mucomplete#empty_text'* 13 | 'g:mucomplete#empty_text_auto' mucomplete.txt /*'g:mucomplete#empty_text_auto'* 14 | 'g:mucomplete#enable_auto_at_startup' mucomplete.txt /*'g:mucomplete#enable_auto_at_startup'* 15 | 'g:mucomplete#force_manual' mucomplete.txt /*'g:mucomplete#force_manual'* 16 | 'g:mucomplete#look_behind' mucomplete.txt /*'g:mucomplete#look_behind'* 17 | 'g:mucomplete#minimum_prefix_length' mucomplete.txt /*'g:mucomplete#minimum_prefix_length'* 18 | 'g:mucomplete#msg#methods' mucomplete.txt /*'g:mucomplete#msg#methods'* 19 | 'g:mucomplete#msg#short_methods' mucomplete.txt /*'g:mucomplete#msg#short_methods'* 20 | 'g:mucomplete#no_mappings' mucomplete.txt /*'g:mucomplete#no_mappings'* 21 | 'g:mucomplete#no_popup_mappings' mucomplete.txt /*'g:mucomplete#no_popup_mappings'* 22 | 'g:mucomplete#popup_direction' mucomplete.txt /*'g:mucomplete#popup_direction'* 23 | 'g:mucomplete#reopen_immediately' mucomplete.txt /*'g:mucomplete#reopen_immediately'* 24 | 'g:mucomplete#spel#good_words' mucomplete.txt /*'g:mucomplete#spel#good_words'* 25 | 'g:mucomplete#spel#max' mucomplete.txt /*'g:mucomplete#spel#max'* 26 | 'g:mucomplete#spel#regex' mucomplete.txt /*'g:mucomplete#spel#regex'* 27 | 'g:mucomplete#tab_when_no_results' mucomplete.txt /*'g:mucomplete#tab_when_no_results'* 28 | 'g:mucomplete#ultisnips#match_at_start' mucomplete.txt /*'g:mucomplete#ultisnips#match_at_start'* 29 | 'g:mucomplete#use_only_windows_paths' mucomplete.txt /*'g:mucomplete#use_only_windows_paths'* 30 | 'g:mucomplete#user_mappings' mucomplete.txt /*'g:mucomplete#user_mappings'* 31 | 'g:mucomplete#wordlist' mucomplete.txt /*'g:mucomplete#wordlist'* 32 | 'g:mucomplete_current_method' mucomplete.txt /*'g:mucomplete_current_method'* 33 | 'g:mucomplete_with_key' mucomplete.txt /*'g:mucomplete_with_key'* 34 | 'mucomplete#add_user_mapping()' mucomplete.txt /*'mucomplete#add_user_mapping()'* 35 | :MUcompleteAutoOff mucomplete.txt /*:MUcompleteAutoOff* 36 | :MUcompleteAutoOn mucomplete.txt /*:MUcompleteAutoOn* 37 | :MUcompleteAutoToggle mucomplete.txt /*:MUcompleteAutoToggle* 38 | :MUcompleteNotify mucomplete.txt /*:MUcompleteNotify* 39 | MUcompletePmenu mucomplete.txt /*MUcompletePmenu* 40 | mucomplete-chains mucomplete.txt /*mucomplete-chains* 41 | mucomplete-commands mucomplete.txt /*mucomplete-commands* 42 | mucomplete-compatibility mucomplete.txt /*mucomplete-compatibility* 43 | mucomplete-contents mucomplete.txt /*mucomplete-contents* 44 | mucomplete-customization mucomplete.txt /*mucomplete-customization* 45 | mucomplete-extend-compl mucomplete.txt /*mucomplete-extend-compl* 46 | mucomplete-feedback mucomplete.txt /*mucomplete-feedback* 47 | mucomplete-howto mucomplete.txt /*mucomplete-howto* 48 | mucomplete-internals mucomplete.txt /*mucomplete-internals* 49 | mucomplete-introduction mucomplete.txt /*mucomplete-introduction* 50 | mucomplete-mappings mucomplete.txt /*mucomplete-mappings* 51 | mucomplete-methods mucomplete.txt /*mucomplete-methods* 52 | mucomplete-path-complete mucomplete.txt /*mucomplete-path-complete* 53 | mucomplete-plugs mucomplete.txt /*mucomplete-plugs* 54 | mucomplete-requirements mucomplete.txt /*mucomplete-requirements* 55 | mucomplete-spel-complete mucomplete.txt /*mucomplete-spel-complete* 56 | mucomplete-tips mucomplete.txt /*mucomplete-tips* 57 | mucomplete-troubleshooting mucomplete.txt /*mucomplete-troubleshooting* 58 | mucomplete.txt mucomplete.txt /*mucomplete.txt* 59 | -------------------------------------------------------------------------------- /plugin/mucomplete.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | if exists("g:loaded_mucomplete") 6 | finish 7 | endif 8 | let g:loaded_mucomplete = 1 9 | 10 | let s:save_cpo = &cpo 11 | set cpo&vim 12 | 13 | imap (MUcompleteFwd) mucomplete#tab_complete( 1) 14 | imap (MUcompleteBwd) mucomplete#tab_complete(-1) 15 | imap (MUcompleteCycFwd) mucomplete#cycle( 1) 16 | imap (MUcompleteCycBwd) mucomplete#cycle(-1) 17 | 18 | if !has('patch-8.0.0283') 19 | inoremap (MUcompletePopupCancel) mucomplete#auto#popup_exit("\") 20 | inoremap (MUcompletePopupAccept) mucomplete#auto#popup_exit("\") 21 | inoremap (MUcompleteCR) mucomplete#auto#popup_exit("\") 22 | endif 23 | 24 | if !get(g:, 'mucomplete#no_mappings', get(g:, 'no_plugin_maps', 0)) 25 | if !hasmapto('(MUcompleteFwd)', 'i') && !has('nvim') 26 | imap (MUcompleteFwd) 27 | endif 28 | if !hasmapto('(MUcompleteBwd)', 'i') && !has('nvim') 29 | imap (MUcompleteBwd) 30 | endif 31 | endif 32 | 33 | command -bar -nargs=1 MUcompleteNotify call mucomplete#msg#set_notifications() 34 | 35 | if has('patch-7.4.143') || (v:version == 704 && has("patch143")) " TextChangedI started to work there 36 | command -bar -nargs=0 MUcompleteAutoOn call mucomplete#auto#enable() 37 | command -bar -nargs=0 MUcompleteAutoOff call mucomplete#auto#disable() 38 | command -bar -nargs=0 MUcompleteAutoToggle call mucomplete#auto#toggle() 39 | 40 | if get(g:, 'mucomplete#enable_auto_at_startup', 0) 41 | call mucomplete#auto#enable() 42 | endif 43 | endif 44 | 45 | let &cpo = s:save_cpo 46 | unlet s:save_cpo 47 | 48 | -------------------------------------------------------------------------------- /test/Readme.md: -------------------------------------------------------------------------------- 1 | # MUcomplete test folder 2 | 3 | This folder contains: 4 | 5 | - a Vim script to test the behaviour of MUcomplete; 6 | - a Vim script to profile MUcomplete's performance. 7 | 8 | To run the test suite, execute: 9 | 10 | ``` 11 | vim -u ../troubleshooting_vimrc.vim ./test_mucomplete.vim 12 | ``` 13 | 14 | then source the script with `:source %`. 15 | 16 | To measure MUcomplete's performance, source `profile_mucomplete.vim`. The 17 | profile is written into a `*.profile` file inside the `test` folder. 18 | 19 | -------------------------------------------------------------------------------- /test/profile_mucomplete.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | " Source this script to start profiling MUcomplete 6 | let s:testdir = fnamemodify(resolve(expand(':p')), ':h') 7 | let s:mudir = fnamemodify(s:testdir, ':h') 8 | execute 'lcd' s:testdir 9 | 10 | fun! s:term_sendkeys(buf, what) 11 | call term_sendkeys(a:buf, a:what) 12 | call term_wait(a:buf) 13 | redraw 14 | endf 15 | 16 | fun! s:prepare_buffer(buf, commands) 17 | call s:term_sendkeys(a:buf, ":enew!\r") " Edit a new buffer 18 | for l:cmd in a:commands " Execute setup commands 19 | call s:term_sendkeys(a:buf, ":".l:cmd."\r") 20 | endfor 21 | call s:term_sendkeys(a:buf, "i") " Enter Insert mode 22 | endf 23 | 24 | fun! s:type(buf, text, wpm) 25 | let l:d = string(60000 / (5 * a:wpm)) 26 | let l:M = len(a:text) 27 | let l:i = 0 28 | while l:i < l:M 29 | let l:j = 0 30 | let l:N = len(a:text[l:i]) 31 | while l:j < l:N 32 | call s:term_sendkeys(a:buf, a:text[l:i][l:j]) 33 | execute "sleep" l:d."m" 34 | let l:j += 1 35 | endwhile 36 | call s:term_sendkeys(a:buf, "\r") 37 | let l:i += 1 38 | endwhile 39 | call s:term_sendkeys(a:buf, "\") " End in Normal mode 40 | endf 41 | 42 | " Launch a Vim instance 43 | let s:termbuf = term_start([v:progpath, 44 | \ "-u", s:mudir."/troubleshooting_vimrc.vim", 45 | \ "--cmd", "profile start mucomplete-".strftime("%Y%m%d-%H%M").".profile", 46 | \ "--cmd", "profile! file */autoload/mucomplete.vim", 47 | \ "-c", "MUcompleteAutoOn", 48 | \ "-c", 'inoremap pumvisible() ? "" : ""', 49 | \ "-c", "set noshowmode shortmess+=c"], { 50 | \ "curwin": 0, 51 | \ "hidden": 0, 52 | \ "stoponexit": "kill", 53 | \ "term_name": "MUcomplete profiling", 54 | \ "term_cols": 80, 55 | \ "term_kill": "kill" 56 | \ } 57 | \ ) 58 | call term_wait(s:termbuf, 1000) 59 | redraw! 60 | 61 | " Test 0 - Warm up! 62 | let s:text = ["jump jump jump jump!"] 63 | call s:prepare_buffer(s:termbuf, []) 64 | call s:type(s:termbuf, s:text, 60) 65 | 66 | " Test 1 67 | let s:text = readfile(s:mudir."/plugin/mucomplete.vim") 68 | call map(s:text, { i,v -> substitute(v, '^\s*', '', '') }) " Remove leading space (for correct indentation) 69 | call s:prepare_buffer(s:termbuf, ["set ft=vim", "setl nospell et formatoptions="]) 70 | call s:type(s:termbuf, s:text, 200) 71 | 72 | " Test 2 73 | let s:text = readfile(s:mudir."/Readme.md") 74 | call s:prepare_buffer(s:termbuf, ["set ft=text", "setl spell spelllang=en"]) 75 | call s:type(s:termbuf, s:text, 400) 76 | 77 | " Quit Vim 78 | call s:term_sendkeys(s:termbuf, "ZQ") 79 | 80 | -------------------------------------------------------------------------------- /test/test.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | let s:messages = [] 6 | let s:errors = [] 7 | let s:done = 0 8 | let s:fail = 0 9 | let s:time_passed = 0.0 10 | 11 | fun! RunTheTest(test) 12 | let s:done += 1 13 | 14 | let l:message = a:test 15 | let l:start_time = reltime() 16 | 17 | try 18 | exe 'call ' . a:test 19 | catch 20 | call add(v:errors, 'Caught exception in ' . a:test . ': ' . v:exception . ' @ ' . v:throwpoint) 21 | endtry 22 | 23 | let l:message .= ' (' . printf('%.01f', 1000.0 * reltimefloat(reltime(l:start_time))) . 'ms) ' 24 | 25 | if len(v:errors) > 0 26 | let s:fail += 1 27 | let l:message .= 'FAILED' 28 | call add(s:errors, '') 29 | call add(s:errors, a:test) 30 | for l:err in v:errors 31 | if l:err =~# '^Caught exception' 32 | call add(s:errors, substitute(l:err, '^Caught exception\zs.*: Vim[^:]*\ze:', '', '')) 33 | else 34 | call add(s:errors, substitute(l:err, '^.*\zeline \d\+', '', '')) 35 | endif 36 | endfor 37 | let v:errors = [] 38 | else 39 | let l:message .= '✔︎' 40 | endif 41 | call add(s:messages, l:message) 42 | endfunc 43 | 44 | fun! FinishTesting() 45 | call add(s:messages, '') 46 | call add(s:messages, 'Run ' . s:done . (s:done > 1 ? ' tests' : ' test') . ' in ' . printf('%.03f', s:time_passed) . 's') 47 | if s:fail == 0 48 | call add(s:messages, 'ALL TESTS PASSED! ✔︎') 49 | else 50 | call add(s:messages, s:fail . (s:fail > 1 ? ' tests' : ' test') . ' failed') 51 | endif 52 | 53 | botright new +setlocal\ buftype=nofile\ bufhidden=wipe\ nobuflisted\ noswapfile\ wrap 54 | call append(line('$'), s:messages) 55 | call append(line('$'), '') 56 | call append(line('$'), s:errors) 57 | call matchadd('Identifier', '✔︎') 58 | call matchadd('WarningMsg', '\') 59 | call matchadd('WarningMsg', '^\d\+ tests\? failed') 60 | call matchadd('Keyword', '^\') 62 | call matchadd('Constant', '\') 63 | call matchadd('ErrorMsg', 'Caught exception') 64 | endf 65 | 66 | fun! RunBabyRun(...) 67 | " Locate Test_ functions and execute them. 68 | redir @t 69 | execute 'silent function /^Test_'.(a:0 > 0 ? a:1 : '') 70 | redir END 71 | let s:tests = split(substitute(@t, 'function \(\k*()\)', '\1', 'g')) 72 | 73 | let l:start_time = reltime() 74 | 75 | for s:test in sort(s:tests) 76 | call RunTheTest(s:test) 77 | endfor 78 | 79 | let s:time_passed = reltimefloat(reltime(l:start_time)) 80 | 81 | call FinishTesting() 82 | endf 83 | 84 | -------------------------------------------------------------------------------- /test/test_mucomplete.vim: -------------------------------------------------------------------------------- 1 | " Chained completion that works as I want! 2 | " Maintainer: Lifepillar 3 | " License: MIT 4 | 5 | " To run the tests: 6 | " 7 | " 1. vim -u ../troubleshooting_vimrc.vim test_mucomplete.vim 8 | " 2. :source % 9 | " 10 | " NOTE: some tests pass only in Vim 8.0.1806 or later. 11 | " 12 | " TODO: use option_save() and option_restore() when implemented 13 | 14 | if !has('patch-8.2.2638') 15 | echohl WarningMsg 16 | echomsg "[MUcomplete Test] Vim 8.2.2638 or later is needed to run the tests successfully" 17 | echohl None 18 | endif 19 | 20 | let s:testdir = fnamemodify(resolve(expand(':p')), ':h') 21 | let s:mudir = fnamemodify(s:testdir, ':h') 22 | 23 | execute 'lcd' s:testdir 24 | execute 'source' s:testdir.'/test.vim' 25 | 26 | " Runs a Vim instance in an environment in which only MUcomplete is loaded. 27 | " Returns the exit status of the Vim instance. 28 | " 29 | " vimrc: a List of commands to add to the vimrc 30 | " cmd: a List of commands to execute after loading the vimrc. 31 | " ...: zero or more commands to execute before loading the vimrc. 32 | " 33 | " NOTE: In the list of commands, single quotes, if present, must be escaped. 34 | " 35 | fun! s:vim(vimrc, cmd, ...) 36 | let l:vimrc_name = 'Xvimrc' 37 | let l:vimrc = [ 38 | \ 'set nocompatible', 39 | \ 'set nobackup noswapfile', 40 | \ 'if has("persistent_undo") | set noundofile | endif', 41 | \ 'if has("writebackup") | set nowritebackup | endif', 42 | \ 'if has("packages") | set packpath= | endif', 43 | \ 'set runtimepath='.fnameescape(s:mudir), 44 | \ 'setl completeopt=menuone' 45 | \ ] 46 | let l:vimrc += a:vimrc 47 | call writefile(l:vimrc, l:vimrc_name) 48 | let l:opt = ' -u ' . l:vimrc_name . ' -i NONE --not-a-term ' 49 | let l:status = system(v:progpath 50 | \ . l:opt 51 | \ . join(map(a:000, { i,v -> "--cmd '" . v . "'"})) 52 | \ . ' ' 53 | \ . join(map(a:cmd, { i,v -> "-c '" . v . "'"})) 54 | \ ) 55 | call delete(l:vimrc_name) 56 | return l:status 57 | endf 58 | 59 | fun! Test_MU_buffer_keyword_completion() 60 | new 61 | let b:mucomplete_chain = ['keyn'] 62 | MUcompleteAutoOff 63 | setl completeopt=menuone,noselect 64 | call feedkeys("ajump ju", "tx") 65 | call feedkeys("a", "t!") 66 | call feedkeys("\\", "tx") 67 | call assert_equal("jump jump", getline(1)) 68 | bwipe! 69 | setl completeopt& 70 | endf 71 | 72 | fun! Test_MU_buffer_keyword_completion_plug() 73 | new 74 | let b:mucomplete_chain = ['keyn'] 75 | MUcompleteAutoOff 76 | setl completeopt=menuone,noselect 77 | call feedkeys("ajump ju", "tx") 78 | call feedkeys("a", "t!") 79 | " Check that invoking the plug directly has the same effect as 80 | call feedkeys("\(MUcompleteFwd)\", "tx") 81 | call assert_equal("jump jump", getline(1)) 82 | bwipe! 83 | setl completeopt& 84 | endf 85 | 86 | " Extending completion should work the same no matter how completeopt is set. 87 | " It should not depend on the value on g:mucomplete#popup_direction either. 88 | fun! Test_MU_buffer_extend_keyword_completion() 89 | new 90 | imap mucomplete#extend_bwd("\") 91 | imap mucomplete#extend_fwd("\") 92 | MUcompleteAutoOff 93 | 94 | for l:opt in ['menuone', 'menuone,noselect', 'menuone,noinsert', 'menuone,noinsert,noselect'] 95 | for l:method in ['keyn', 'keyp'] 96 | let b:mucomplete_chain = [l:method] 97 | for l:popup_dir in [1,-1] 98 | let g:mucomplete#popup_direction = { l:method: l:popup_dir } 99 | let &l:completeopt = l:opt 100 | norm ggdG 101 | call feedkeys("aIn Xanadu did Kubla Khan", "tx") 102 | call feedkeys("oIn", "tx") 103 | call feedkeys("a", "t!") 104 | call feedkeys("\\\\\", "tx") 105 | call assert_equal("In Xanadu did Kubla Khan", getline(1)) 106 | call assert_equal("In Xanadu did Kubla Khan", getline(2)) 107 | call feedkeys("oIn", "tx") 108 | call feedkeys("a", "t!") 109 | call feedkeys("\\\\\", "tx") 110 | call assert_equal("In Xanadu did Kubla Khan", getline(3)) 111 | endfor 112 | endfor 113 | endfor 114 | 115 | unlet g:mucomplete#popup_direction 116 | setl completeopt& 117 | bwipe! 118 | endf 119 | 120 | fun! Test_MU_extend_line_completion() 121 | new 122 | imap mucomplete#extend_bwd("\") 123 | imap mucomplete#extend_fwd("\") 124 | let b:mucomplete_chain = ['line'] 125 | MUcompleteAutoOff 126 | 127 | for l:opt in ['menuone', 'menuone,noselect', 'menuone,noinsert', 'menuone,noinsert,noselect'] 128 | let &l:completeopt = l:opt 129 | norm ggdG 130 | call setline(1, ['abc def', 'abc def ghi', 'abc def ghi jkl']) 131 | let l:expected = ['abc def', 'abc def ghi', 'abc def ghi jkl', 132 | \ 'abc def', 'abc def ghi', 'abc def ghi jkl', 133 | \ 'abc def', 'abc def ghi', 'abc def ghi jkl'] 134 | call cursor(3,1) 135 | call feedkeys("oabc", "tx") 136 | call feedkeys("a", "t!") 137 | " Select the first line, then extend with the remaining lines 138 | call feedkeys("\\\\\\\", "tx") 139 | call feedkeys("oabc", "tx") 140 | call feedkeys("a", "t!") 141 | " Ditto 142 | call feedkeys("\\\\\\\", "tx") 143 | call assert_equal(l:expected, getline(1, '$')) 144 | endfor 145 | 146 | setl completeopt& 147 | bwipe! 148 | endf 149 | 150 | fun! Test_MU_cmd_completion() 151 | new 152 | set ft=vim 153 | let b:mucomplete_chain = ['cmd'] 154 | MUcompleteAutoOff 155 | setl completeopt=menuone,noselect 156 | call feedkeys("aech", "tx") 157 | call feedkeys("a", "t!") 158 | call feedkeys("\\\", "tx") 159 | call assert_equal("echoconsole", getline(1)) 160 | bwipe! 161 | setl completeopt& 162 | endf 163 | 164 | fun! Test_MU_line_completion() 165 | new 166 | let b:mucomplete_chain = ['line'] 167 | MUcompleteAutoOff 168 | setl completeopt=menuone,noselect 169 | call feedkeys("aVim is awesome\", "tx") 170 | call feedkeys("aVi", "tx") 171 | call feedkeys("a", "t!") 172 | call feedkeys("\\", "tx") 173 | call assert_equal("Vim is awesome", getline(1)) 174 | call assert_equal("Vim is awesome", getline(2)) 175 | bwipe! 176 | setl completeopt& 177 | endf 178 | 179 | fun! Test_MU_path_completion_basic() 180 | new 181 | execute 'lcd' s:testdir 182 | let b:mucomplete_chain = ['path'] 183 | MUcompleteAutoOff 184 | setl completeopt=menuone,noselect 185 | call feedkeys("a./test_m", "tx") 186 | call feedkeys("a", "t!") 187 | call feedkeys("\\", "tx") 188 | call assert_equal("./test_mucomplete.vim", getline(1)) 189 | bwipe! 190 | setl completeopt& 191 | endf 192 | 193 | fun! Test_MU_path_completion_with_non_default_isfname() 194 | new 195 | let b:mucomplete_chain = ['path'] 196 | MUcompleteAutoOff 197 | try 198 | setl completeopt=menuone,noselect 199 | set isfname+=@-@,#,{,},* 200 | execute 'lcd' s:testdir 201 | call mkdir('tempdir/I * mucomplete/@ @/###/{ok}/}ok{/', "p") 202 | call feedkeys("a./tempdir/I", "tx") 203 | call feedkeys("a", "t!") 204 | call feedkeys("\\", "tx") 205 | call assert_equal("./tempdir/I * mucomplete", getline(1)) 206 | call feedkeys("a/", "t!") 207 | call feedkeys("\\", "tx") 208 | call assert_equal("./tempdir/I * mucomplete/@ @", getline(1)) 209 | call feedkeys("a/", "t!") 210 | call feedkeys("\\", "tx") 211 | call assert_equal("./tempdir/I * mucomplete/@ @/###", getline(1)) 212 | call feedkeys("a/{", "t!") 213 | call feedkeys("\\", "tx") 214 | call assert_equal("./tempdir/I * mucomplete/@ @/###/{ok}", getline(1)) 215 | call feedkeys("a/}", "t!") 216 | call feedkeys("\\", "tx") 217 | call assert_equal("./tempdir/I * mucomplete/@ @/###/{ok}/}ok{", getline(1)) 218 | bwipe! 219 | finally 220 | call delete("tempdir", "rf") 221 | setl completeopt& 222 | set isfname& 223 | endtry 224 | endf 225 | 226 | fun! Test_MU_double_slash_comment_is_not_path() 227 | new 228 | execute 'lcd' s:testdir 229 | let b:mucomplete_chain = ['path'] 230 | MUcompleteAutoOff 231 | setl completeopt=menuone,noselect 232 | call feedkeys("a// t", "tx") 233 | call feedkeys("a", "t!") 234 | call feedkeys("\\", "tx") 235 | call assert_equal("// t", getline(1)) 236 | bwipe! 237 | setl completeopt& 238 | endf 239 | 240 | fun! Test_MU_slash_is_not_path_in_autocompletion() 241 | new 242 | setl completeopt=menuone,noselect 243 | let b:mucomplete_chain = ['path'] 244 | call assert_equal('(MUcompleteFwd)', maparg('', 'i')) 245 | call assert_equal('(MUcompleteBwd)', maparg('', 'i')) 246 | MUcompleteAutoOn 247 | call cursor(3,1) 248 | call test_override("char_avail", 1) 249 | call feedkeys("A/\\\", 'tx') 250 | call assert_equal('/', getline(1)) 251 | call feedkeys("o//\\\", 'tx') 252 | call assert_equal('//', getline(2)) 253 | call test_override("char_avail", 0) 254 | MUcompleteAutoOff 255 | setl completeopt& 256 | bwipe! 257 | endf 258 | 259 | fun! Test_MU_complete_path_after_equal_sign() 260 | new 261 | execute 'lcd' s:testdir 262 | let b:mucomplete_chain = ['path'] 263 | MUcompleteAutoOff 264 | setl completeopt=menuone,noselect 265 | call feedkeys("Alet path=./R", "tx") 266 | call feedkeys("a", "t!") 267 | call feedkeys("\\", "tx") 268 | call assert_equal("let path=./Readme.md", getline(1)) 269 | bwipe! 270 | setl completeopt& 271 | endf 272 | 273 | fun! Test_MU_uspl_completion() 274 | new 275 | setlocal spell 276 | setlocal spelllang=en 277 | let b:mucomplete_chain = ['uspl'] 278 | MUcompleteAutoOff 279 | setl completeopt=menuone,noselect 280 | call feedkeys("aspelin", "tx") 281 | call feedkeys("a", "t!") 282 | call feedkeys("\\\", "tx") 283 | call assert_equal("spleen", getline(1)) 284 | call feedkeys("a spelin", "tx") 285 | call feedkeys("a", "t!") 286 | call feedkeys("\\\\", "tx") 287 | call assert_equal("spleen spelling", getline(1)) 288 | bwipe! 289 | setl completeopt& 290 | endf 291 | 292 | fun! Test_MU_uspl_umlauts_completion() 293 | new 294 | setlocal spell 295 | setlocal spelllang=en 296 | let b:mucomplete_chain = ['uspl'] 297 | MUcompleteAutoOff 298 | setl completeopt=menuone,noselect 299 | call feedkeys("anaïv", "tx") 300 | call feedkeys("a", "t!") 301 | call feedkeys("\\\", "tx") 302 | call assert_equal("naïve", getline(1)) 303 | call feedkeys("a naiv", "tx") 304 | call feedkeys("a", "t!") 305 | call feedkeys("\\\\\\", "tx") 306 | call assert_equal("naïve naïve", getline(1)) 307 | bwipe! 308 | setl completeopt& 309 | endf 310 | 311 | fun! Test_MU_ctrl_e_ends_completion() 312 | new 313 | let b:mucomplete_chain = ['keyn'] 314 | MUcompleteAutoOff 315 | setl completeopt=menuone,noselect 316 | call feedkeys("aabsinthe ab", "tx") 317 | call feedkeys("a", "t!") 318 | call feedkeys("\\", "tx") 319 | call assert_equal("absinthe ab", getline(1)) 320 | bwipe! 321 | setl completeopt& 322 | endf 323 | 324 | fun! Test_MU_ctrl_y_accepts_completion() 325 | new 326 | let b:mucomplete_chain = ['keyn'] 327 | MUcompleteAutoOff 328 | setl completeopt=menuone,noselect 329 | call feedkeys("aabsinthe ab", "tx") 330 | call feedkeys("a", "t!") 331 | call feedkeys("\\ ok", "tx") 332 | call assert_equal("absinthe absinthe ok", getline(1)) 333 | bwipe! 334 | setl completeopt& 335 | endf 336 | 337 | fun! Test_MU_issue_87() 338 | new 339 | set ft=tex 340 | let b:mucomplete_chain = ['path', 'omni', 'keyn'] 341 | MUcompleteAutoOff 342 | setl completeopt=menuone,noselect 343 | call feedkeys('a\emph{', "tx") 344 | call feedkeys("a", "t!") 345 | call feedkeys("\\", "tx") 346 | call assert_equal('\emph{', getline(1)) 347 | call assert_equal([], v:errors) 348 | bwipe! 349 | setl completeopt& 350 | endf 351 | 352 | fun! Test_MU_issue_89() 353 | " Make sure that cyclic plugs are defined before the autoload file is loaded. 354 | let l:vimrc = [ 355 | \ 'inoremap (MUcompleteFwdKey) ', 356 | \ 'imap (MUcompleteCycFwd)', 357 | \ 'let g:mucomplete#enable_auto_at_startup = 1' 358 | \ ] 359 | let l:cmd = ['edit Xout', 'call feedkeys("i\ok", "tx")', 'norm! ZZ'] 360 | call s:vim(l:vimrc, l:cmd) 361 | let l:output = join(readfile('Xout')) 362 | call assert_equal('ok', l:output) 363 | call delete('Xout') 364 | endf 365 | 366 | fun! Test_MU_smart_enter() 367 | " Before v9.1.1121, Vim does not always insert a new line after pressing 368 | " Enter with the pop-up menu visible. This function tests a situation is 369 | " which Vim would not normally insert a new line (so "ok" would end on the 370 | " same line as "hawkfish"), but MUcomplete does, after remapping . 371 | new 372 | let b:mucomplete_chain = ['keyn'] 373 | setl completeopt=menuone 374 | MUcompleteAutoOff 375 | " Default behaviour: Enter does not start a new line 376 | call feedkeys("ahawkfish\hawk", "tx") 377 | call feedkeys("a", "t!") 378 | call feedkeys("\\fish\ok", "tx") 379 | 380 | if has('patch-9.1.1121') 381 | call assert_equal("hawkfish", getline(1)) 382 | call assert_equal("hawkfish", getline(2)) 383 | call assert_equal("ok", getline(3)) 384 | call assert_equal(3, line('$')) 385 | else 386 | call assert_equal("hawkfish", getline(1)) 387 | call assert_equal("hawkfishok", getline(2)) 388 | call assert_equal(2, line('$')) 389 | endif 390 | 391 | " Remap to always Insert a new line when the pop up menu is dismissed 392 | imap pumvisible() ? "\\" : "\" 393 | call feedkeys("ohawk", "tx") 394 | call feedkeys("a", "t!") 395 | call feedkeys("\\fish\ok", "tx") 396 | 397 | if has('patch-9.1.1121') 398 | call assert_equal("hawkfish", getline(4)) 399 | call assert_equal("ok", getline(5)) 400 | call assert_equal(5, line('$')) 401 | else 402 | call assert_equal("hawkfish", getline(3)) 403 | call assert_equal("ok", getline(4)) 404 | call assert_equal(4, line('$')) 405 | endif 406 | bwipe! 407 | endf 408 | 409 | if has('python') || has('python3') 410 | 411 | fun! Test_MU_issue_85_python_dot() 412 | " Allow omni-completion to be triggered after a dot. 413 | new 414 | set filetype=python 415 | let b:mucomplete_chain = ['omni'] 416 | MUcompleteAutoOff 417 | setl completeopt=menuone,noselect 418 | call feedkeys("aimport sys.", "tx") 419 | call feedkeys("a", "t!") 420 | " Trigger omni-completion and select the first entry 421 | call feedkeys("\\", "tx") 422 | call assert_match('import sys.\w\+', getline(1)) 423 | bwipe! 424 | setl completeopt& 425 | endf 426 | 427 | endif 428 | 429 | fun! Test_MU_popup_complete_backwards_issues_61_and_95() 430 | " This test fails before Vim 8.0.1731 because of a Vim bug. 431 | " See https://github.com/vim/vim/issues/1645 432 | new 433 | setlocal completeopt=menuone,noinsert 434 | call setline(1, ['Post', 'Port', 'Po']) 435 | 436 | if has('patch-9.1.1121') " Insert newline when pressing Enter if no menu item is selected 437 | let l:expected = ['Post', 'Port', 'Port', ''] 438 | else 439 | let l:expected = ['Post', 'Port', 'Port'] 440 | endif 441 | 442 | call cursor(3,2) 443 | " Check that Vim does not have bugs 444 | call feedkeys("A\". repeat("\", 3). "rt\", 'tx') 445 | call assert_equal(l:expected, getline(1, '$')) 446 | norm ggdG 447 | call setline(1, ['Post', 'Port', 'Po']) 448 | call cursor(3,2) 449 | call feedkeys("A\\rt\", 'tx') 450 | call assert_equal(l:expected, getline(1, '$')) 451 | " Check that MUcomplete behaves the same 452 | norm ggdG 453 | call setline(1, ['Post', 'Port', 'Po']) 454 | let b:mucomplete_chain = ['keyp'] 455 | call cursor(3,2) 456 | call feedkeys("A\\\rt\", 'tx') 457 | call assert_equal(l:expected, getline(1, '$')) 458 | norm ggdG 459 | call setline(1, ['Post', 'Port', 'Po']) 460 | let b:mucomplete_chain = ['c-p'] 461 | call cursor(3,2) 462 | call feedkeys("A\\rt\", 'tx') 463 | call assert_equal(l:expected, getline(1, '$')) 464 | bwipe! 465 | endfunc 466 | 467 | fun! Test_MU_popup_direction() 468 | new 469 | let b:mucomplete_chain = ['keyp'] 470 | let g:mucomplete#always_use_completeopt = 0 471 | MUcompleteAutoOff 472 | 473 | " Manual completion must be independent of completeopt when 474 | " always_use_completeopt is off. 475 | for l:opt in ['menuone', 'menuone,noselect', 'menuone,noinsert', 'menuone,noinsert,noselect'] 476 | let g:mucomplete#popup_direction = { 'keyp': -1 } 477 | norm ggdG 478 | let &l:completeopt = l:opt 479 | call setline(1, ['bowl', 'bowling', 'bowtie', 'bo']) 480 | let l:expected = ['bowl', 'bowling', 'bowtie', 'bowtie', 'bowling'] 481 | call cursor(4,2) 482 | call feedkeys("A\", 'tx') 483 | call feedkeys("obo", 'tx') 484 | call feedkeys("a", 't!') 485 | call feedkeys("\\", 'tx') 486 | call assert_equal(l:expected, getline(1, '$')) 487 | norm ggdG 488 | let g:mucomplete#popup_direction = { 'keyp': 1 } 489 | call setline(1, ['bowl', 'bowling', 'bowtie', 'bo']) 490 | let l:expected = ['bowl', 'bowling', 'bowtie', 'bowl', 'bowtie'] 491 | call cursor(4,2) 492 | call feedkeys("A\", 'tx') 493 | call feedkeys("obo", 'tx') 494 | call feedkeys("a", 't!') 495 | call feedkeys("\\", 'tx') 496 | call assert_equal(l:expected, getline(1, '$')) 497 | endfor 498 | 499 | unlet g:mucomplete#always_use_completeopt 500 | unlet g:mucomplete#popup_direction 501 | setl completeopt& 502 | bwipe! 503 | endf 504 | 505 | fun! Test_MU_basic_autocompletion() 506 | new 507 | setl completeopt=menuone,noselect 508 | let b:mucomplete_chain = ['keyn'] 509 | call assert_equal('(MUcompleteFwd)', maparg('', 'i')) 510 | call assert_equal('(MUcompleteBwd)', maparg('', 'i')) 511 | MUcompleteAutoOn 512 | call setline(1, ['topolino', 'topomoto', '']) 513 | let l:expected = ['topolino', 'topomoto', 'topomoto', 'topomoto'] 514 | call cursor(3,1) 515 | call test_override("char_avail", 1) 516 | call feedkeys("Ato\\\\", 'tx') 517 | call feedkeys("Ato\\\", 'tx') 518 | call assert_equal(l:expected, getline(1,'$')) 519 | call test_override("char_avail", 0) 520 | MUcompleteAutoOff 521 | setl completeopt& 522 | bwipe! 523 | endf 524 | 525 | fun! Test_MU_autocompletion_tab_shifttab() 526 | new 527 | let b:mucomplete_chain = ['keyn'] 528 | setl completeopt=menuone,noselect 529 | MUcompleteAutoOn 530 | 531 | " Test that we are able to select menu entries with TAB and SHIFT-TAB 532 | call setline(1, ['monadelphous', 'monadism', 'monazite', 'mondegreen']) 533 | let l:expected = ['monadelphous', 'monadism', 'monazite', 'mondegreen', 534 | \ 'monadelphous', 'monadism', 'monazite', 'mondegreen', 535 | \ 'mondegreen', 'monazite', 'monadism', 'monadelphous'] 536 | call cursor(4,1) 537 | call test_override("char_avail", 1) 538 | call feedkeys("omo\\\", 'tx') 539 | call feedkeys("omo", 't!') 540 | call feedkeys("\\\\", 'tx') 541 | call feedkeys("omo", 't!') 542 | call feedkeys("\\\\\", 'tx') 543 | call feedkeys("omo", 't!') 544 | call feedkeys("\\\\\\", 'tx') 545 | call feedkeys("omo", 't!') 546 | call feedkeys("\\\", 'tx') 547 | call feedkeys("omo", 't!') 548 | call feedkeys("\\\\", 'tx') 549 | call feedkeys("omo", 't!') 550 | call feedkeys("\\\\\", 'tx') 551 | call feedkeys("omo", 't!') 552 | call feedkeys("\\\\\\", 'tx') 553 | call assert_equal(l:expected, getline(1, '$')) 554 | call test_override("char_avail", 0) 555 | 556 | MUcompleteAutoOff 557 | setl completeopt& 558 | bwipe! 559 | endf 560 | 561 | fun! Test_MU_natural_popup_direction_auto_on_noselect() 562 | new 563 | setl completeopt=menuone,noselect 564 | MUcompleteAutoOn 565 | let g:mucomplete#popup_direction = { 'keyp': -1 } 566 | let b:mucomplete_chain = ['keyp'] 567 | 568 | call test_override("char_avail", 1) 569 | call setline(1, ['bowl', 'bowling', 'bowtie']) 570 | let expected = ['bowl', 'bowling', 'bowtie', 'bowtie', 'bowling', 'bowl'] 571 | call cursor(3,1) 572 | call feedkeys("obo\", 'tx') 573 | call feedkeys("obo\\", 'tx') 574 | call feedkeys("obo\\\", 'tx') 575 | call assert_equal(expected, getline(1, '$')) 576 | call test_override("char_avail", 0) 577 | 578 | MUcompleteAutoOff 579 | unlet g:mucomplete#popup_direction 580 | setl completeopt& 581 | bwipe! 582 | endf 583 | 584 | fun! Test_MU_reverse_popup_direction_auto_on_noselect() 585 | new 586 | setl completeopt=menuone,noselect 587 | MUcompleteAutoOn 588 | let g:mucomplete#popup_direction = { 'keyp': 1 } 589 | let b:mucomplete_chain = ['keyp'] 590 | 591 | call test_override("char_avail", 1) 592 | call setline(1, ['bowl', 'bowling', 'bowtie']) 593 | let expected = ['bowl', 'bowling', 'bowtie', 'bowl', 'bowtie', 'bowtie'] 594 | call cursor(3,1) 595 | call feedkeys("obo\", 'tx') 596 | call feedkeys("obo\\", 'tx') 597 | call feedkeys("obo\\\", 'tx') 598 | call assert_equal(expected, getline(1, '$')) 599 | call test_override("char_avail", 0) 600 | 601 | unlet g:mucomplete#popup_direction 602 | MUcompleteAutoOff 603 | setl completeopt& 604 | bwipe! 605 | endf 606 | 607 | fun! Test_MU_natural_popup_direction_auto_on_noinsert() 608 | new 609 | setl completeopt=menuone,noinsert 610 | MUcompleteAutoOn 611 | let g:mucomplete#popup_direction = { 'keyp': -1 } 612 | let b:mucomplete_chain = ['keyp'] 613 | 614 | call test_override("char_avail", 1) 615 | call setline(1, ['bowl', 'bowling', 'bowtie']) 616 | let expected = ['bowl', 'bowling', 'bowtie', 'bowtie', 'bowling', 'bowl'] 617 | call cursor(3,1) 618 | call feedkeys("obo\", 'tx') 619 | call feedkeys("obo\", 'tx') 620 | call feedkeys("obo\\", 'tx') 621 | call assert_equal(expected, getline(1, '$')) 622 | call test_override("char_avail", 0) 623 | 624 | unlet g:mucomplete#popup_direction 625 | MUcompleteAutoOff 626 | setl completeopt& 627 | bwipe! 628 | endf 629 | 630 | fun! Test_MU_reverse_popup_direction_auto_on_noinsert() 631 | new 632 | setl completeopt=menuone,noinsert 633 | MUcompleteAutoOn 634 | let g:mucomplete#popup_direction = { 'keyp': 1 } 635 | let b:mucomplete_chain = ['keyp'] 636 | 637 | call test_override("char_avail", 1) 638 | call setline(1, ['bowl', 'bowling', 'bowtie']) 639 | let expected = ['bowl', 'bowling', 'bowtie', 'bowl', 'bowtie', 'bowtie'] 640 | call cursor(3,1) 641 | call feedkeys("obo\", 'tx') 642 | call feedkeys("obo\", 'tx') 643 | call feedkeys("obo\\", 'tx') 644 | call assert_equal(expected, getline(1, '$')) 645 | call test_override("char_avail", 0) 646 | 647 | unlet g:mucomplete#popup_direction 648 | MUcompleteAutoOff 649 | setl completeopt& 650 | bwipe! 651 | endf 652 | 653 | fun! Test_MU_natural_popup_direction_auto_on_noinsert_noselect() 654 | new 655 | setl completeopt=menuone,noselect,noinsert 656 | MUcompleteAutoOn 657 | let g:mucomplete#popup_direction = { 'keyp': -1 } 658 | let b:mucomplete_chain = ['keyp'] 659 | 660 | call test_override("char_avail", 1) 661 | call setline(1, ['bowl', 'bowling', 'bowtie']) 662 | let expected = ['bowl', 'bowling', 'bowtie', 'bowtie', 'bowling'] 663 | call cursor(3,1) 664 | call feedkeys("obo\", 'tx') 665 | call feedkeys("obo\\", 'tx') 666 | call assert_equal(expected, getline(1, '$')) 667 | call test_override("char_avail", 0) 668 | 669 | unlet g:mucomplete#popup_direction 670 | MUcompleteAutoOff 671 | setl completeopt& 672 | bwipe! 673 | endf 674 | 675 | fun! Test_MU_reverse_popup_direction_auto_on_noselect_noinsert() 676 | new 677 | setl completeopt=menuone,noselect,noinsert 678 | MUcompleteAutoOn 679 | let g:mucomplete#popup_direction = { 'keyp': 1 } 680 | let b:mucomplete_chain = ['keyp'] 681 | 682 | call test_override("char_avail", 1) 683 | call setline(1, ['bowl', 'bowling', 'bowtie']) 684 | let expected = ['bowl', 'bowling', 'bowtie', 'bowl', 'bowtie'] 685 | call cursor(3,1) 686 | call feedkeys("obo\", 'tx') 687 | call feedkeys("obo\\", 'tx') 688 | call assert_equal(expected, getline(1, '$')) 689 | call test_override("char_avail", 0) 690 | 691 | unlet g:mucomplete#popup_direction 692 | MUcompleteAutoOff 693 | setl completeopt& 694 | bwipe! 695 | endf 696 | 697 | " MUcomplete must be immune to remappings of CTRL-N and CTRL-P in Insert mode 698 | fun! Test_MU_ctrl_p_and_ctrl_n_remapped() 699 | new 700 | inoremap P 701 | inoremap N 702 | setl completeopt=menu,noselect 703 | call feedkeys("Ajust jump ju", 'tx') 704 | call feedkeys("a", "t!") 705 | call feedkeys("\\\\", 'tx') 706 | call assert_equal('just jump jump', getline(1)) 707 | call feedkeys("oju", 'tx') 708 | call feedkeys("a", "t!") 709 | call feedkeys("\\\\\", 'tx') 710 | call assert_equal('jump', getline(2)) 711 | 712 | setl completeopt& 713 | bwipe! 714 | endf 715 | 716 | " MUcomplete must be immune to remappings of Up and Down arrows 717 | fun! Test_MU_up_and_down_arrow_remapped() 718 | new 719 | inoremap UP 720 | inoremap DOWN 721 | setl completeopt=menu,noinsert 722 | call feedkeys("Ajust jump ju", 'tx') 723 | call feedkeys("a", "t!") 724 | call feedkeys("\\\\", 'tx') 725 | call assert_equal('just jump jump', getline(1)) 726 | call feedkeys("oju", 'tx') 727 | call feedkeys("a", "t!") 728 | call feedkeys("\\\\\", 'tx') 729 | call assert_equal('jump', getline(2)) 730 | 731 | setl completeopt& 732 | bwipe! 733 | endf 734 | 735 | fun! Test_MU_cycling_uses_correct_compl_text() 736 | new 737 | setl completeopt=menuone,noselect 738 | set filetype=c 739 | setlocal omnifunc=ccomplete#Complete 740 | setlocal tags=./testtags 741 | let b:mucomplete_chain = ['omni', 'keyn'] 742 | call writefile(['incCount path/to/somefile.c /^void incCount(int n) {$/;" f'], 'testtags') 743 | 744 | call feedkeys("Aint incredible;", 'tx') 745 | call feedkeys("oin", 'tx') 746 | call feedkeys("a", "t!") 747 | call feedkeys("\\c\\\", 'tx') 748 | call assert_equal('incredible', getline(2)) 749 | call feedkeys("oin", 'tx') 750 | call feedkeys("a", "t!") 751 | call feedkeys("\\c\\\\\", 'tx') 752 | call assert_equal('incredible', getline(3)) 753 | call feedkeys("oin", 'tx') 754 | call feedkeys("a", "t!") 755 | call feedkeys("\\c\\\", 'tx') 756 | call assert_equal('incredible', getline(3)) 757 | call feedkeys("oin", 'tx') 758 | call feedkeys("a", "t!") 759 | call feedkeys("\\c\\\\\", 'tx') 760 | call assert_equal('incredible', getline(4)) 761 | 762 | call delete('testtags') 763 | setl completeopt& 764 | bwipe! 765 | endf 766 | 767 | fun! Test_MU_ccomplete_and_cycling() 768 | new 769 | setl completeopt=menuone,noselect 770 | set filetype=c 771 | setlocal omnifunc=ccomplete#Complete 772 | setlocal tags=./testtags 773 | let b:mucomplete_chain = ['omni', 'keyn'] 774 | call writefile(['incCount path/to/somefile.c /^void incCount(int n) {$/;" f'], 'testtags') 775 | 776 | call feedkeys("Aint in", 'tx') 777 | call feedkeys("a", "t!") 778 | call feedkeys("\\\\", 'tx') 779 | call assert_equal('int int', getline(1)) 780 | call feedkeys("oin", 'tx') 781 | call feedkeys("a", "t!") 782 | call feedkeys("\\\\\\", 'tx') 783 | call assert_equal('int', getline(2)) 784 | call feedkeys("oin", 'tx') 785 | call feedkeys("a", "t!") 786 | call feedkeys("\\\\", 'tx') 787 | call assert_equal('int', getline(3)) 788 | call feedkeys("oin", 'tx') 789 | call feedkeys("a", "t!") 790 | call feedkeys("\\\\\\", 'tx') 791 | call assert_equal('int', getline(4)) 792 | 793 | call delete('testtags') 794 | setl completeopt& 795 | bwipe! 796 | endf 797 | 798 | fun! Test_MU_scoped_completion() 799 | new 800 | setl completeopt=menuone,noselect 801 | set filetype=vim 802 | set spell spelllang=en 803 | let b:mucomplete_chain = { 'vimLineComment': ['uspl'], 'vimString': [], 'default': ['cmd', 'keyp'] } 804 | call setline(1, ['" Vim rulez', 'let x = "rocks roc"', 'wh']) 805 | let l:expected = ['" Vim rules', 'let x = "rocks roc"', 'while'] 806 | call cursor(1,1) 807 | call feedkeys("A\\\\", 'tx') 808 | call feedkeys("+2fca\\\", 'tx') " No completion here 809 | call feedkeys("+A\\\", 'tx') 810 | call assert_equal(l:expected, getline(1, '$')) 811 | 812 | setl completeopt& 813 | bwipe! 814 | endf 815 | 816 | fun! Test_MU_scoped_completion_with_regexp() 817 | new 818 | setl completeopt=menuone,noselect 819 | set filetype=vim 820 | set spell spelllang=en 821 | let b:mucomplete_chain = { '^.*Comment$': ['uspl'], 'vimStr.*': [], 'default': ['cmd', 'keyp'] } 822 | call setline(1, ['" Vim rulez', 'let x = "rocks roc"', 'wh']) 823 | let l:expected = ['" Vim rules', 'let x = "rocks roc"', 'while'] 824 | call cursor(1,1) 825 | call feedkeys("A\\\\", 'tx') 826 | call feedkeys("+2fca\\\", 'tx') " No completion here 827 | call feedkeys("+A\\\", 'tx') 828 | call assert_equal(l:expected, getline(1, '$')) 829 | 830 | setl completeopt& 831 | bwipe! 832 | endf 833 | 834 | fun! Test_MU_test_set_dictionary_spell() 835 | new 836 | set dictionary=spell " Set global option 837 | set spell spelllang=en 838 | let b:mucomplete_chain = ['dict'] 839 | " Setting 'dictionary' globally leaves the local option empty: 840 | call assert_equal('', &l:dictionary) 841 | call setline(1, 'zu') 842 | call cursor(1,1) 843 | call feedkeys("A\\\", 'tx') 844 | call assert_equal('zucchini', getline(1)) 845 | 846 | setl completeopt& 847 | set dictionary& 848 | bwipe! 849 | endf 850 | 851 | fun! Test_MU_setlocal_dictionary_spell() 852 | new 853 | setlocal dictionary=spell " Set local option 854 | setlocal spell spelllang=en 855 | let b:mucomplete_chain = ['dict'] 856 | " Setting 'dictionary' locally also sets it globally: 857 | call assert_equal('spell', &l:dictionary) 858 | call assert_equal('spell', &dictionary) 859 | call setline(1, 'zu') 860 | call cursor(1,1) 861 | call feedkeys("A\\\", 'tx') 862 | call assert_equal('zucchini', getline(1)) 863 | 864 | setl completeopt& 865 | set dictionary& 866 | bwipe! 867 | endf 868 | 869 | fun! Test_MU_test_set_thesaurus_globally() 870 | new 871 | call writefile(['abundantly'], 'testthes') 872 | set thesaurus=./testthes " Set global option 873 | let b:mucomplete_chain = ['thes'] 874 | " Setting 'thesaurus' globally leaves the local option empty: 875 | call assert_equal('', &l:thesaurus) 876 | call setline(1, 'abu') 877 | call cursor(1,1) 878 | call feedkeys("A\\\", 'tx') 879 | call assert_equal('abundantly', getline(1)) 880 | 881 | call delete('testthes') 882 | setl completeopt& 883 | set thesaurus& 884 | bwipe! 885 | endf 886 | 887 | fun! Test_MU_test_set_thesaurus_locally() 888 | new 889 | call writefile(['abundantly'], 'testthes') 890 | setlocal thesaurus=./testthes 891 | let b:mucomplete_chain = ['thes'] 892 | " Setting 'thesaurus' locally also sets the global option: 893 | call assert_equal('./testthes', &l:thesaurus) 894 | call assert_equal('./testthes', &thesaurus) 895 | call setline(1, 'abu') 896 | call cursor(1,1) 897 | call feedkeys("A\\\", 'tx') 898 | call assert_equal('abundantly', getline(1)) 899 | 900 | call delete('testthes') 901 | setl completeopt& 902 | set thesaurus& 903 | bwipe! 904 | endf 905 | 906 | " See https://github.com/lifepillar/vim-mucomplete/issues/160 907 | fun! Test_MU_completion_mode_is_exited_when_no_results() 908 | new 909 | setlocal completeopt=menuone,noselect 910 | setlocal tags=./testtags 911 | setlocal complete=t 912 | setlocal filetype=c 913 | let b:mucomplete_chain = ['keyn'] 914 | call writefile(['incCount path/to/somefile.c /^void incCount(int n) {$/;" f'], 'testtags') 915 | 916 | call feedkeys("iin", 'tx') 917 | call feedkeys("a", "t!") 918 | " When pressing Tab, no result is returned and the completion mode should be 919 | " reset. So, if the user next types CTRL-P, Vim should complete keywords from 920 | " different sources (tags, in this case). If, for some reason, Vim were still 921 | " in completion mode, then CTRL-P would have no effect. 922 | call feedkeys("\\\\\", 'tx') 923 | call assert_equal('incCount', getline(1)) 924 | 925 | call delete('testtags') 926 | setl completeopt& 927 | bwipe! 928 | endf 929 | 930 | fun! Test_MU_tab_when_no_result() 931 | new 932 | let g:mucomplete#tab_when_no_results = 1 933 | let b:mucomplete_chain = ['keyn'] 934 | call feedkeys("ieorigh", 'tx') 935 | call feedkeys("a", "t!") 936 | call feedkeys("\\", "tx") 937 | call assert_equal("eorigh\t", getline(1)) 938 | 939 | unlet g:mucomplete#tab_when_no_results 940 | bwipe! 941 | endf 942 | 943 | call RunBabyRun('MU') 944 | 945 | -------------------------------------------------------------------------------- /troubleshooting_vimrc.vim: -------------------------------------------------------------------------------- 1 | " vim: foldmethod=marker foldenable 2 | " Do not change this section {{{ 3 | set nocompatible 4 | set nobackup noswapfile 5 | if has('persistent_undo') 6 | set noundofile 7 | endif 8 | if has('writebackup') 9 | set nowritebackup 10 | endif 11 | if has('viminfo') 12 | set viminfo="" 13 | endif 14 | if has('packages') 15 | set packpath=$VIMRUNTIME 16 | endif 17 | set runtimepath=$VIMRUNTIME 18 | set completeopt=menuone 19 | if has('patch-7.4.775') 20 | if !has('patch-7.4.784') 21 | echomsg "WARNING: noinsert and noselect may not work properly with this version of Vim." 22 | endif 23 | set completeopt+=noinsert 24 | else 25 | echomsg "Automatic completion is not available in this version of Vim." 26 | endif 27 | set showmode 28 | if has('patch-7.4.314') 29 | set shortmess-=c 30 | endif 31 | syntax enable 32 | filetype plugin indent on 33 | " }}} 34 | 35 | set runtimepath+=~/.vim/pack/my/start/mucomplete " CHANGE THIS 36 | 37 | " Optionally add additional configuration below this line 38 | --------------------------------------------------------------------------------