"============================================================================= " autocomplpop.vim - Automatically open the popup menu for completion. "============================================================================= " " Author: Takeshi NISHIDA " Version: 2.5, for Vim 7.1 " Licence: MIT Licence " URL: https://www.vim8.org/scripts/script.php?script_id=1879 " " GetLatestVimScripts: 1879 1 :AutoInstall: autocomplpop.vim " "============================================================================= " DOCUMENT: (Japanese: http://vim.g.hatena.ne.jp/keyword/autocomplpop.vim) " " Description: ---------------------------------------------------------- {{{1 " Install this plugin and your vim comes to automatically opens the popup " menu for completion when you enter characters or move the cursor in Insert " mode. " " Installation: --------------------------------------------------------- {{{1 " Drop this file in your plugin directory. " " Usage: ---------------------------------------------------------------- {{{1 " If this plugin has been installed, the auto-popup is enabled at startup by " default. " " Which completion method is used depends on the text before the cursor. The " default behavior is as follows: " " 1. The keyword completion is attempted if the text before the cursor " consists of two keyword character. " 2. The filename completion is attempted if the text before the cursor " consists of a filename character + a path separator + 0 or more " filename characters. " 3. The omni completion is attempted in Ruby file if the text before the " cursor consists of "." or "::". (Ruby interface is required.) " 4. The omni completion is attempted in Python file if the text before " the cursor consists of ".". (Python interface is required.) " 5. The omni completion is attempted in HTML/XHTML file if the text " before the cursor consists of "<" or "'), '\d\+_') endfunction "----------------------------------------------------------------------------- function! s:GetPopupFeeder() return s:PopupFeeder endfunction "----------------------------------------------------------------------------- function! s:Enable() call s:Disable() augroup AutoComplPopGlobalAutoCommand autocmd! autocmd InsertEnter * let s:PopupFeeder.last_pos = [] | unlet s:PopupFeeder.last_pos autocmd InsertLeave * call s:PopupFeeder.finish() augroup END if g:AutoComplPop_MappingDriven call s:FeedMapping.map() else autocmd AutoComplPopGlobalAutoCommand CursorMovedI * call s:PopupFeeder.feed() endif nnoremap i i=GetPopupFeeder().feed() nnoremap a a=GetPopupFeeder().feed() nnoremap R R=GetPopupFeeder().feed() endfunction "----------------------------------------------------------------------------- function! s:Disable() call s:FeedMapping.unmap() augroup AutoComplPopGlobalAutoCommand autocmd! augroup END nnoremap i | nunmap i nnoremap a | nunmap a nnoremap R | nunmap R endfunction " FUNCTION: BEHAVIOR ==================================================== {{{1 "----------------------------------------------------------------------------- function! s:MakeDefaultBehavior() let behavs = { \ '*' : [], \ 'ruby' : [], \ 'python' : [], \ 'html' : [], \ 'xhtml' : [], \ 'css' : [], \ } if g:AutoComplPop_BehaviorKeywordLength >= 0 for key in keys(behavs) call add(behavs[key], { \ 'command' : "\", \ 'pattern' : printf('\k\{%d,}$', g:AutoComplPop_BehaviorKeywordLength), \ 'repeat' : 0, \ }) endfor endif if g:AutoComplPop_BehaviorFileLength >= 0 for key in keys(behavs) call add(behavs[key], { \ 'command' : "\\", \ 'pattern' : printf('\f[%s]\f\{%d,}$', (has('win32') || has('win64') ? '/\\' : '/'), \ g:AutoComplPop_BehaviorFileLength), \ 'excluded' : '[*/\\][/\\]\f*$\|[^[:print:]]\f*$', \ 'repeat' : 1, \ }) endfor endif if has('ruby') && g:AutoComplPop_BehaviorRubyOmniMethodLength >= 0 call add(behavs.ruby, { \ 'command' : "\\", \ 'pattern' : printf('[^. \t]\(\.\|::\)\k\{%d,}$', g:AutoComplPop_BehaviorRubyOmniMethodLength), \ 'repeat' : 0, \ }) endif if has('ruby') && g:AutoComplPop_BehaviorRubyOmniSymbolLength >= 0 call add(behavs.ruby, { \ 'command' : "\\", \ 'pattern' : printf('\(^\|[^:]\):\k\{%d,}$', g:AutoComplPop_BehaviorRubyOmniSymbolLength), \ 'repeat' : 0, \ }) endif if has('python') && g:AutoComplPop_BehaviorPythonOmniLength >= 0 call add(behavs.python, { \ 'command' : "\\", \ 'pattern' : printf('\k\.\k\{%d,}$', g:AutoComplPop_BehaviorPythonOmniLength), \ 'repeat' : 0, \ }) endif if g:AutoComplPop_BehaviorHtmlOmniLength >= 0 let behav_html = { \ 'command' : "\\", \ 'pattern' : printf('\(<\|<\/\|<[^>]* \)\k\{%d,}$', g:AutoComplPop_BehaviorHtmlOmniLength), \ 'repeat' : 1, \ } call add(behavs.html , behav_html) call add(behavs.xhtml, behav_html) endif if g:AutoComplPop_BehaviorCssOmniPropertyLength >= 0 call add(behavs.css, { \ 'command' : "\\", \ 'pattern' : printf('\(^\s\|[;{]\)\s*\k\{%d,}$', g:AutoComplPop_BehaviorCssOmniPropertyLength), \ 'repeat' : 0, \ }) endif if g:AutoComplPop_BehaviorCssOmniValueLength >= 0 call add(behavs.css, { \ 'command' : "\\", \ 'pattern' : printf('[:@!]\s*\k\{%d,}$', g:AutoComplPop_BehaviorCssOmniValueLength), \ 'repeat' : 0, \ }) endif return behavs endfunction " OBJECT: PopupFeeder: ================================================== {{{1 let s:PopupFeeder = { 'behavs' : [], 'lock_count' : 0 } "----------------------------------------------------------------------------- function! s:PopupFeeder.feed() " NOTE: CursorMovedI is not triggered while the pupup menu is visible. And " it will be triggered when pupup menu is disappeared. if self.lock_count > 0 || pumvisible() || &paste return '' endif let cursor_moved = self.check_cursor_and_update() if exists('self.behavs[0]') && self.behavs[0].repeat let self.behavs = (self.behavs[0].repeat ? [ self.behavs[0] ] : []) elseif cursor_moved let self.behavs = copy(exists('g:AutoComplPop_Behavior[&filetype]') ? g:AutoComplPop_Behavior[&filetype] \ : g:AutoComplPop_Behavior['*']) else let self.behavs = [] endif let cur_text = strpart(getline('.'), 0, col('.') - 1) call filter(self.behavs, 'cur_text =~ v:val.pattern && (!exists(''v:val.excluded'') || cur_text !~ v:val.excluded)') if empty(self.behavs) call self.finish() return '' endif " In case of dividing words by symbols while a popup menu is visible, " popup is not available unless input or try popup once. " (E.g. "for(int", "ab==cd") So duplicates first completion. call insert(self.behavs, self.behavs[0]) call s:OptionManager.set('completeopt', 'menuone' . (g:AutoComplPop_CompleteoptPreview ? ',preview' : '')) call s:OptionManager.set('complete', g:AutoComplPop_CompleteOption) call s:OptionManager.set('ignorecase', g:AutoComplPop_IgnoreCaseOption) call s:OptionManager.set('lazyredraw', !g:AutoComplPop_MappingDriven) " NOTE: With CursorMovedI driven, Set 'lazyredraw' to avoid flickering. " With Mapping driven, set 'nolazyredraw' to make a popup menu visible. " use for silence instead of = call feedkeys(self.behavs[0].command . "\AutocomplpopOnPopupPost", 'm') return '' " for = endfunction "----------------------------------------------------------------------------- function! s:PopupFeeder.finish() let self.behavs = [] call s:OptionManager.restore_all() endfunction "----------------------------------------------------------------------------- function! s:PopupFeeder.lock() let self.lock_count += 1 endfunction "----------------------------------------------------------------------------- function! s:PopupFeeder.unlock() let self.lock_count -= 1 if self.lock_count < 0 let self.lock_count = 0 throw "autocomplpop.vim: not locked" endif endfunction "----------------------------------------------------------------------------- function! s:PopupFeeder.check_cursor_and_update() let prev_pos = (exists('self.last_pos') ? self.last_pos : [-1, -1, -1, -1]) let self.last_pos = getpos('.') if has('multi_byte_ime') return (prev_pos[1] != self.last_pos[1] || prev_pos[2] + 1 == self.last_pos[2] || \ prev_pos[2] > self.last_pos[2]) else return (prev_pos != self.last_pos) endif endfunction "----------------------------------------------------------------------------- function! s:PopupFeeder.on_popup_post() if pumvisible() " a command to restore to original text and select the first match return "\\" elseif exists('self.behavs[1]') call remove(self.behavs, 0) return printf("\%s\=%sGetPopupFeeder().on_popup_post()\", \ self.behavs[0].command, s:GetSidPrefix()) else call self.finish() return "\" endif endfunction " OBJECT: OptionManager: sets or restores temporary options ============= {{{1 let s:OptionManager = { 'originals' : {} } "----------------------------------------------------------------------------- function! s:OptionManager.set(name, value) call extend(self.originals, { a:name : eval('&' . a:name) }, 'keep') execute printf('let &%s = a:value', a:name) endfunction "----------------------------------------------------------------------------- function! s:OptionManager.restore_all() for [name, value] in items(self.originals) execute printf('let &%s = value', name) endfor let self.originals = {} endfunction " OBJECT: FeedMapping: manages global mappings ========================== {{{1 let s:FeedMapping = { 'keys' : [] } "----------------------------------------------------------------------------- function! s:FeedMapping.map() call self.unmap() let self.keys = [ \ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', \ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', \ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', \ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', \ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', \ '-', '_', '~', '^', '.', ',', ':', '!', '#', '=', '%', '$', '@', '<', '>', '/', '\', \ '', '', '', ] for key in self.keys execute printf('inoremap %s %s=GetPopupFeeder().feed()', \ key, key) endfor endfunction "----------------------------------------------------------------------------- function! s:FeedMapping.unmap() for key in self.keys execute 'iunmap ' . key endfor let self.keys = [] endfunction " }}}1 " GLOBAL OPTIONS: ======================================================= {{{1 "........................................................................... if !exists('g:AutoComplPop_NotEnableAtStartup') let g:AutoComplPop_NotEnableAtStartup = 0 endif "........................................................................... if !exists('g:AutoComplPop_MappingDriven') let g:AutoComplPop_MappingDriven = 0 endif "......................................................................... if !exists('g:AutoComplPop_IgnoreCaseOption') let g:AutoComplPop_IgnoreCaseOption = 0 endif "......................................................................... if !exists('g:AutoComplPop_CompleteOption') let g:AutoComplPop_CompleteOption = '.,w,b,k' endif "......................................................................... if !exists('g:AutoComplPop_CompleteoptPreview') let g:AutoComplPop_CompleteoptPreview = 0 endif "......................................................................... if !exists('g:AutoComplPop_BehaviorKeywordLength') let g:AutoComplPop_BehaviorKeywordLength = 2 endif "......................................................................... if !exists('g:AutoComplPop_BehaviorFileLength') let g:AutoComplPop_BehaviorFileLength = 0 endif "......................................................................... if !exists('g:AutoComplPop_BehaviorRubyOmniMethodLength') let g:AutoComplPop_BehaviorRubyOmniMethodLength = 0 endif "......................................................................... if !exists('g:AutoComplPop_BehaviorRubyOmniSymbolLength') let g:AutoComplPop_BehaviorRubyOmniSymbolLength = 1 endif "......................................................................... if !exists('g:AutoComplPop_BehaviorPythonOmniLength') let g:AutoComplPop_BehaviorPythonOmniLength = 0 endif "......................................................................... if !exists('g:AutoComplPop_BehaviorHtmlOmniLength') let g:AutoComplPop_BehaviorHtmlOmniLength = 0 endif "......................................................................... if !exists('g:AutoComplPop_BehaviorCssOmniPropertyLength') let g:AutoComplPop_BehaviorCssOmniPropertyLength = 1 endif "......................................................................... if !exists('g:AutoComplPop_BehaviorCssOmniValueLength') let g:AutoComplPop_BehaviorCssOmniValueLength = 0 endif "......................................................................... if !exists('g:AutoComplPop_Behavior') let g:AutoComplPop_Behavior = {} endif call extend(g:AutoComplPop_Behavior, s:MakeDefaultBehavior(), 'keep') " COMMANDS/AUTOCOMMANDS/MAPPINGS/ETC.: ================================== {{{1 command! -bar -narg=0 AutoComplPopEnable call s:Enable() command! -bar -narg=0 AutoComplPopDisable call s:Disable() command! -bar -narg=0 AutoComplPopLock call s:PopupFeeder.lock() command! -bar -narg=0 AutoComplPopUnlock call s:PopupFeeder.unlock() inoremap AutocomplpopOnPopupPost GetPopupFeeder().on_popup_post() if !g:AutoComplPop_NotEnableAtStartup AutoComplPopEnable endif " }}}1 "============================================================================= " vim: set fdm=marker: