Commits

Takeshi NISHIDA committed a80b4bf

Fixed a bug that keyword completion was never attempted when no candidate for snipMate's trigger completion was found.

Comments (0)

Files changed (4)

 endfunction
 
 "
+function acp#requireForSnipmate(context)
+  if g:acp_behaviorSnipmateLength < 0
+    return 0
+  endif
+  let matches = matchlist(a:context, '\(^\|\s\|\<\)\(\u\{' .
+        \                            g:acp_behaviorSnipmateLength . ',}\)$')
+  return !empty(matches) && !empty(s:getMatchingSnipItems(matches[2]))
+endfunction
+
+"
+function acp#requireForKeyword(context)
+  return g:acp_behaviorKeywordLength >= 0 &&
+        \ a:context =~ '\k\{' . g:acp_behaviorKeywordLength . ',}$'
+endfunction
+
+"
+function acp#requireForFile(context)
+  if g:acp_behaviorFileLength < 0
+    return 0
+  endif
+  if has('win32') || has('win64')
+    let separator = '[/\\]'
+  else
+    let separator = '\/'
+  endif
+  if a:context !~ '\f' . separator . '\f\{' . g:acp_behaviorFileLength . ',}$'
+    return 0
+  endif
+  return a:context !~ '[*/\\][/\\]\f*$\|[^[:print:]]\f*$'
+endfunction
+
+"
+function acp#requireForRubyOmni(context)
+  if !has('ruby')
+    return 0
+  endif
+  if g:acp_behaviorRubyOmniMethodLength >= 0 &&
+        \ a:context =~ '[^. \t]\(\.\|::\)\k\{' .
+        \              g:acp_behaviorRubyOmniMethodLength . ',}$'
+    return 1
+  endif
+  if g:acp_behaviorRubyOmniSymbolLength >= 0 &&
+        \ a:context =~ '\(^\|[^:]\):\k\{' .
+        \              g:acp_behaviorRubyOmniSymbolLength . ',}$'
+    return 1
+  endif
+  return 0
+endfunction
+
+"
+function acp#requireForPythonOmni(context)
+  return has('python') &&
+        \ a:context =~ '\k\.\k\{' . g:acp_behaviorPythonOmniLength . ',}$'
+endfunction
+
+"
+function acp#requireForXmlOmni(context)
+  return a:context =~ '\(<\|<\/\|<[^>]\+ \|<[^>]\+=\"\)\k\{' .
+        \             g:acp_behaviorXmlOmniLength . ',}$'
+endfunction
+
+"
+function acp#requireForCssOmni(context)
+  if g:acp_behaviorCssOmniPropertyLength >= 0 &&
+        \ a:context =~ '\(^\s\|[;{]\)\s*\k\{' .
+        \              g:acp_behaviorCssOmniPropertyLength . ',}$'
+    return 1
+  endif
+  if g:acp_behaviorCssOmniValueLength >= 0 &&
+        \ a:context =~ '[:@!]\s*\k\{' .
+        \              g:acp_behaviorCssOmniValueLength . ',}$'
+    return 1
+  endif
+  return 0
+endfunction
+
+"
 function acp#completeSnipmate(findstart, base)
   if a:findstart
     return len(matchstr(s:getCurrentText(), '.*\U'))
   for trigger in keys(GetSnipsInCurrentScope())
     let lenTrigger = len(trigger)
     if lenText >= lenTrigger && strridx(text, trigger) + lenTrigger == lenText
-      let g:i = text . '|' . trigger
       call feedkeys("\<C-r>=TriggerSnippet()\<CR>", "n")
       return 0
     endif
 
 "
 function s:matchesBehavior(text, behav)
-  return a:text =~ a:behav.pattern &&
-        \ (!exists('a:behav.exclude') || a:text !~ a:behav.exclude)
+  return call(a:behav.require, [a:text])
 endfunction
 
 "
     return ''
   endif
   if exists('s:behavsCurrent[0].onPopupClose')
-    if !function(s:behavsCurrent[0].onPopupClose)()
+    if !call(s:behavsCurrent[0].onPopupClose, [])
       call s:finishPopup(1)
       return ''
     endif
 "
 function s:makeSnipmateItem(key, snip)
   if type(a:snip) == type([])
-    let snipFormatted = '[multi snip]'
+    let descriptions = map(copy(a:snip), 'v:val[0]')
+    let snipFormatted = '[MULTI] ' . join(descriptions, ', ')
   else
-    let snipFormatted = strpart(substitute(a:snip, '\(\n\|\s\)\+', ' ', 'g'), 0, 80)
+    let snipFormatted = substitute(a:snip, '\(\n\|\s\)\+', ' ', 'g')
   endif
   return  {
         \   'word': a:key,
-        \   'menu': snipFormatted,
+        \   'menu': strpart(snipFormatted, 0, 80),
         \ }
 endfunction
 
+"
+function s:getMatchingSnipItems(base)
+  let key = a:base . "\n"
+  if !exists('s:snipItems[key]')
+    let s:snipItems[key] = items(GetSnipsInCurrentScope())
+    call filter(s:snipItems[key], 'strpart(v:val[0], 0, len(a:base)) ==? a:base')
+    call map(s:snipItems[key], 's:makeSnipmateItem(v:val[0], v:val[1])')
+  endif
+  return s:snipItems[key]
+endfunction
+
 " }}}1
 "=============================================================================
 " INITIALIZATION {{{1
 let s:lockCount = 0
 let s:behavsCurrent = []
 let s:tempOptionSet = [{}, {}]
+let s:snipItems = {}
 
 inoremap <silent> <expr> <Plug>AcpOnPopupPost acp#onPopupPost()
 
 <
         ユーザー定義補完の関数。空ならこの補完は行いません。
 
-                                         *g:acp_behaviorUserDefinedPattern*  >
-  let g:acp_behaviorUserDefinedPattern = '\k$'
+        See also:|complete-functions|
+
+                                         *g:acp_behaviorUserDefinedRequire*  >
+  let g:acp_behaviorUserDefinedRequire = ''
 <
-        ユーザー定義補完の自動ポップアップを行うのに必要なカーソルの直前のパタ
-        ーン。
+        TODO
 
                                              *g:acp_behaviorSnipmateLength*  >
   let g:acp_behaviorSnipmateLength = -1
 
         "completefunc":
           'completefunc' に設定する関数。 "command" が "<C-x><C-u>" のときだけ
-          意味があります。
+          意味があります。
 
-        "pattern", "exclude":
-          カーソル直前テキストが "pattern" にマッチし、"exclude" にマッチしな
-          かった場合、補完メニューをポップアップします。
+        "require":
+          TODO
 
         "repeat":
           真なら最後の補完が自動的に繰り返されます。
 
         See also:|complete-functions|
 
-                                         *g:acp_behaviorUserDefinedPattern*  >
-  let g:acp_behaviorUserDefinedPattern = '\k$'
+                                         *g:acp_behaviorUserDefinedRequire*  >
+  let g:acp_behaviorUserDefinedRequire = ''
 <
-        Pattern before a cursor, which are needed to attempt user-defined
-        completion.
+        TODO
 
                                              *g:acp_behaviorSnipmateLength*  >
   let g:acp_behaviorSnipmateLength = -1
           'completefunc' will be set to this user-provided function during the
           completion. Only makes sense when "command" is "<C-x><C-u>".
 
-        "pattern", "exclude":
-          If a text before a cursor matches "pattern" and not "exclude", popup
-          menu is opened.
+        "require":
+          TODO
 
         "repeat":
           If non-zero, the last completion is automatically repeated.
 ==============================================================================
 CHANGELOG                                                      *acp-changelog*
 
+2.11.2
+  - Fixed a bug that keyword completion was never attempted when
+    no candidate for snipMate's trigger completion was found.
+
 2.11.1
   - Fixed a bug that a snipMate's trigger could not be expanded when it was
     completed.
         \   'css'    : [],
         \ }
   "---------------------------------------------------------------------------
-  if !empty(g:acp_behaviorUserDefinedFunction)
+  if !empty(g:acp_behaviorUserDefinedFunction) &&
+        \ !empty(g:acp_behaviorUserDefinedRequire)
     for key in keys(behavs)
       call add(behavs[key], {
             \   'command'      : "\<C-x>\<C-u>",
             \   'completefunc' : g:acp_behaviorUserDefinedFunction,
-            \   'pattern'      : g:acp_behaviorUserDefinedPattern,
+            \   'require'      : g:acp_behaviorUserDefinedRequire,
             \   'repeat'       : 0,
             \ })
     endfor
   endif
   "---------------------------------------------------------------------------
-  if g:acp_behaviorSnipmateLength >= 0
-    for key in keys(behavs)
-      call add(behavs[key], {
-            \   'command'      : "\<C-x>\<C-u>",
-            \   'completefunc' : 'acp#completeSnipmate',
-            \   'pattern'      : printf('\(^\|\s\|\<\)\u\{%d,}$', g:acp_behaviorSnipmateLength),
-            \   'repeat'       : 0,
-            \   'onPopupClose' : 'acp#onPopupCloseSnipmate'
-            \ })
-    endfor
-  endif
+  for key in keys(behavs)
+    call add(behavs[key], {
+          \   'command'      : "\<C-x>\<C-u>",
+          \   'completefunc' : 'acp#completeSnipmate',
+          \   'require'      : "acp#requireForSnipmate",
+          \   'repeat'       : 0,
+          \   'onPopupClose' : 'acp#onPopupCloseSnipmate'
+          \ })
+  endfor
   "---------------------------------------------------------------------------
-  if g:acp_behaviorKeywordLength >= 0
-    for key in keys(behavs)
-      call add(behavs[key], {
-            \   'command' : g:acp_behaviorKeywordCommand,
-            \   'pattern' : printf('\k\{%d,}$', g:acp_behaviorKeywordLength),
-            \   'repeat'  : 0,
-            \ })
-    endfor
-  endif
-  "---------------------------------------------------------------------------
-  if g:acp_behaviorFileLength >= 0
-    for key in keys(behavs)
-      call add(behavs[key], {
-            \   'command' : "\<C-x>\<C-f>",
-            \   'pattern' : printf('\f[%s]\f\{%d,}$', (has('win32') || has('win64') ? '/\\' : '/'),
-            \                      g:acp_behaviorFileLength),
-            \   'exclude' : '[*/\\][/\\]\f*$\|[^[:print:]]\f*$',
-            \   'repeat'  : 1,
-            \ })
-    endfor
-  endif
-  "---------------------------------------------------------------------------
-  if has('ruby') && g:acp_behaviorRubyOmniMethodLength >= 0
-    call add(behavs.ruby, {
-          \   'command' : "\<C-x>\<C-o>",
-          \   'pattern' : printf('[^. \t]\(\.\|::\)\k\{%d,}$',
-          \                      g:acp_behaviorRubyOmniMethodLength),
+  for key in keys(behavs)
+    call add(behavs[key], {
+          \   'command' : g:acp_behaviorKeywordCommand,
+          \   'require' : "acp#requireForKeyword",
           \   'repeat'  : 0,
           \ })
-  endif
+  endfor
   "---------------------------------------------------------------------------
-  if has('ruby') && g:acp_behaviorRubyOmniSymbolLength >= 0
-    call add(behavs.ruby, {
-          \   'command' : "\<C-x>\<C-o>",
-          \   'pattern' : printf('\(^\|[^:]\):\k\{%d,}$',
-          \                      g:acp_behaviorRubyOmniSymbolLength),
-          \   'repeat'  : 0,
+  for key in keys(behavs)
+    call add(behavs[key], {
+          \   'command' : "\<C-x>\<C-f>",
+          \   'require' : "acp#requireForFile",
+          \   'repeat'  : 1,
           \ })
-  endif
+  endfor
   "---------------------------------------------------------------------------
-  if has('python') && g:acp_behaviorPythonOmniLength >= 0
-    call add(behavs.python, {
-          \   'command' : "\<C-x>\<C-o>",
-          \   'pattern' : printf('\k\.\k\{%d,}$',
-          \                      g:acp_behaviorPythonOmniLength),
-          \   'repeat'  : 0,
-          \ })
-  endif
+  call add(behavs.ruby, {
+        \   'command' : "\<C-x>\<C-o>",
+        \   'require' : "acp#requireForRubyOmni",
+        \   'repeat'  : 0,
+        \ })
   "---------------------------------------------------------------------------
-  if g:acp_behaviorXmlOmniLength >= 0
-    call add(behavs.xml, {
-          \   'command' : "\<C-x>\<C-o>",
-          \   'pattern' : printf('\(<\|<\/\|<[^>]\+ \|<[^>]\+=\"\)\k\{%d,}$',
-          \                      g:acp_behaviorXmlOmniLength),
-          \   'repeat'  : 0,
-          \ })
-  endif
+  call add(behavs.ruby, {
+        \   'command' : "\<C-x>\<C-o>",
+        \   'require' : "acp#requireForRubyOmni",
+        \   'repeat'  : 0,
+        \ })
   "---------------------------------------------------------------------------
-  if g:acp_behaviorHtmlOmniLength >= 0
-    let behavHtml = {
-          \   'command' : "\<C-x>\<C-o>",
-          \   'pattern' : printf('\(<\|<\/\|<[^>]\+ \|<[^>]\+=\"\)\k\{%d,}$',
-          \                      g:acp_behaviorHtmlOmniLength),
-          \   'repeat'  : 1,
-          \ }
-    call add(behavs.html , behavHtml)
-    call add(behavs.xhtml, behavHtml)
-  endif
+  call add(behavs.python, {
+        \   'command' : "\<C-x>\<C-o>",
+        \   'require' : "acp#requireForPythonOmni",
+        \   'repeat'  : 0,
+        \ })
   "---------------------------------------------------------------------------
-  if g:acp_behaviorCssOmniPropertyLength >= 0
-    call add(behavs.css, {
-          \   'command' : "\<C-x>\<C-o>",
-          \   'pattern' : printf('\(^\s\|[;{]\)\s*\k\{%d,}$',
-          \                      g:acp_behaviorCssOmniPropertyLength),
-          \   'repeat'  : 0,
-          \ })
-  endif
+  call add(behavs.xml, {
+        \   'command' : "\<C-x>\<C-o>",
+        \   'require' : "acp#requireForXmlOmni",
+        \   'repeat'  : 1,
+        \ })
   "---------------------------------------------------------------------------
-  if g:acp_behaviorCssOmniValueLength >= 0
-    call add(behavs.css, {
-          \   'command' : "\<C-x>\<C-o>",
-          \   'pattern' : printf('[:@!]\s*\k\{%d,}$',
-          \                      g:acp_behaviorCssOmniValueLength),
-          \   'repeat'  : 0,
-          \ })
-  endif
+  call add(behavs.html, {
+        \   'command' : "\<C-x>\<C-o>",
+        \   'require' : "acp#requireForXmlOmni",
+        \   'repeat'  : 1,
+        \ })
+  "---------------------------------------------------------------------------
+  call add(behavs.xhtml, {
+        \   'command' : "\<C-x>\<C-o>",
+        \   'require' : "acp#requireForXmlOmni",
+        \   'repeat'  : 1,
+        \ })
+  "---------------------------------------------------------------------------
+  call add(behavs.css, {
+        \   'command' : "\<C-x>\<C-o>",
+        \   'require' : "acp#requireForCssOmni",
+        \   'repeat'  : 0,
+        \ })
   "---------------------------------------------------------------------------
   return behavs
 endfunction
 call s:defineOption('g:acp_completeOption', '.,w,b,k')
 call s:defineOption('g:acp_completeoptPreview', 0)
 call s:defineOption('g:acp_behaviorUserDefinedFunction', '')
-call s:defineOption('g:acp_behaviorUserDefinedPattern' , '\k$')
+call s:defineOption('g:acp_behaviorUserDefinedRequire', '')
 call s:defineOption('g:acp_behaviorSnipmateLength', -1)
 call s:defineOption('g:acp_behaviorKeywordCommand', "\<C-n>")
 call s:defineOption('g:acp_behaviorKeywordLength', 2)