Permalink
Browse files

Version 2.10

- ENH: When no base doesn't match with the beginning of a snippet, fall back to matches either anywhere in the snippet or in the snippet expansion.
- Truncate very long or multi-line snippet expansions in the popup menu. This requires the CompleteHelper plugin. When the entire snippet doesn't fit into the popup menu, offer it for showing in the preview window. *** THIS PLUGIN NOW REQUIRES THE CompleteHelper PLUGIN (vimscript #3914) ***
  • Loading branch information...
1 parent 061b1bf commit 29f60156fbf6519e73c9ed88eb5f1e18cfda36c2 Ingo Karkat committed with Oct 19, 2012
Showing with 122 additions and 19 deletions.
  1. +16 −2 README
  2. +80 −12 autoload/SnippetComplete.vim
  3. +26 −5 doc/SnippetComplete.txt
View
@@ -9,9 +9,23 @@ but switching to command mode for that is cumbersome.
This plugin offers a context-sensitive insert mode completion to quickly list
and complete defined abbreviations directly while typing.
+SEE ALSO
+- The SnippetCompleteSnipMate.vim plugin (vimscript #4276) extends the
+ completion with snippets for the popular snipMate plugin (vimscript #2540).
+
USAGE
-i_CTRL-X_] Find matches for abbreviations that start with the
- text in front of the cursor.
+In insert mode, optionally type part of the snippet shortcut or a fragment
+from its expected expansion, and invoke the snippet completion via CTRL-X ].
+You can then search forward and backward via CTRL-N / CTRL-P, as usual.
+
+CTRL-X ] Find matches for abbreviations that start with the
+ text in front of the cursor. If other snippet types
+ are registered, show those, too.
+ If no matches were found that way, matches anywhere in
+ the snippet or in the snippet's expanded text will be
+ shown. So if you can't remember the shortcut, but a
+ word fragment from the resulting expansion, just try
+ with that.
There are three types of abbreviations (full-id,
end-id and non-id), which can consist of different
@@ -2,13 +2,26 @@
" abbreviations and snippets.
"
" DEPENDENCIES:
+" - CompleteHelper/Abbreviate.vim autoload script
"
" Copyright: (C) 2010-2012 Ingo Karkat
" The VIM LICENSE applies to this script; see ':help copyright'.
"
" Maintainer: Ingo Karkat <ingo@karkat.de>
"
" REVISION DATE REMARKS
+" 2.10.005 18-Oct-2012 Must use the keyword before the cursor for
+" matches in the snippet expansion, not the type's
+" base column.
+" 2.10.004 17-Oct-2012 ENH: When no base doesn't match with the
+" beginning of a snippet, fall back to matches
+" either anywhere in the snippet or in the snippet
+" expansion.
+" Truncate very long or multi-line snippet
+" expansions in the popup menu. This requires the
+" CompleteHelper plugin. When the entire snippet
+" doesn't fit into the popup menu, offer it for
+" showing in the preview window.
" 2.00.003 05-May-2012 Rewrite s:RegistryTypeCompare() so that it
" doesn't need to access
" g:SnippetComplete_Registry.
@@ -109,21 +122,28 @@ endfunction
function! s:GetBase( baseCol, cursorCol )
return strpart(getline('.'), a:baseCol - 1, (a:cursorCol - a:baseCol))
endfunction
-function! s:MatchSnippets( snippets, baseCol )
- let l:base = s:GetBase(a:baseCol, col('.'))
-"****D echomsg '****' a:baseCol l:base
- return (empty(l:base) ?
- \ a:snippets :
- \ filter(copy(a:snippets), 'strpart(v:val.word, 0, ' . len(l:base) . ') ==# ' . string(l:base))
+function! s:MatchSnippetsStrict( snippets, base )
+ return filter(copy(a:snippets), 'strpart(v:val.word, 0, ' . len(a:base) . ') ==# ' . string(a:base))
+endfunction
+function! s:MatchSnippetsRelaxed( snippets, base )
+ return filter(copy(a:snippets), 'stridx(v:val.word, a:base) != -1')
+endfunction
+function! s:MatchSnippetsExpansion( snippets, base )
+ return filter(copy(a:snippets),
+ \ 'stridx(get(v:val, "menu", ""), a:base) != -1 ||' .
+ \ 'stridx(get(v:val, "info", ""), a:base) != -1'
\)
endfunction
-function! s:GetSnippetCompletions( types )
- let l:baseColumns = s:DetermineBaseCol(a:types)
-"****D echomsg '####' string(l:baseColumns)
+function! s:GetSnippetCompletionsWithStrategy( Strategy, types, baseColumns )
let l:completionsByBaseCol = {}
- for [l:type, l:baseCol] in l:baseColumns
+ for [l:type, l:baseCol] in a:baseColumns
let l:snippets = s:GetSnippets(a:types, l:type)
- let l:matches = s:MatchSnippets(l:snippets, l:baseCol)
+ let l:base = s:GetBase(l:baseCol, col('.'))
+"****D echomsg '****' l:baseCol l:base
+ let l:matches = (empty(l:base) ?
+ \ l:snippets :
+ \ call(a:Strategy, [l:snippets, l:base])
+ \)
"****D echomsg '****' l:type string(l:matches)
if ! empty(l:matches)
let l:completions = get(l:completionsByBaseCol, l:baseCol, [])
@@ -134,6 +154,35 @@ function! s:GetSnippetCompletions( types )
"****D echomsg '****' string(l:completionsByBaseCol)
return l:completionsByBaseCol
endfunction
+function! s:GetSnippetCompletions( types )
+ let l:baseColumns = s:DetermineBaseCol(a:types)
+"****D echomsg '####' string(l:baseColumns)
+ let l:completionsByBaseCol = s:GetSnippetCompletionsWithStrategy('s:MatchSnippetsStrict', a:types, l:baseColumns)
+ if empty(l:completionsByBaseCol)
+ " When the base doesn't match with the beginning of a snippet, fall back
+ " to matches either anywhere in the snippet or in the snippet expansion.
+
+ " First do a relaxed match anywhere in the snippet.
+ let l:completionsByBaseCol = s:GetSnippetCompletionsWithStrategy('s:MatchSnippetsRelaxed', a:types, l:baseColumns)
+
+ " Then add any matches in the snippet expansion.
+ " For these, the keyword before the cursor must be used as base, not the
+ " base columns as determined by the snippet type!
+ let l:startCol = searchpos('\k*\%#', 'bn', line('.'))[1]
+ if l:startCol != 0
+ let l:startColumns = map(keys(a:types), '[v:val, l:startCol]') " Transform into the expected structure.
+ let l:completionsByStartCol = s:GetSnippetCompletionsWithStrategy('s:MatchSnippetsExpansion', a:types, l:startColumns)
+
+ " Add the matches to any matches already existing for that base
+ " column. There will be duplicates when the base matches both in the
+ " snippet and its expansion, but Vim's completion will ignore
+ " identical entries.
+ let l:completionsByBaseCol[l:startCol] = get(l:completionsByBaseCol, l:startCol, []) +
+ \ get(l:completionsByStartCol, l:startCol, [])
+ endif
+ endif
+ return l:completionsByBaseCol
+endfunction
function! s:CompletionCompare( c1, c2 )
return (a:c1.word ==# a:c2.word ? 0 : a:c1.word ># a:c2.word ? 1 : -1)
endfunction
@@ -175,6 +224,23 @@ function! s:RecordPosition()
" a window above the current), the position changes.
return getpos('.') + [bufnr(''), winnr(), tabpagenr()]
endfunction
+function! s:FormatMatches( matchObject )
+ " Shorten the snippet expansion if necessary.
+ let l:menu = get(a:matchObject, 'menu', '')
+ let l:text = CompleteHelper#Abbreviate#Text(l:menu)
+ if l:text !=# l:menu
+ let a:matchObject.menu = l:text
+
+ if ! has_key(a:matchObject, 'info')
+ " When the entire snippet doesn't fit into the popup menu, offer it
+ " for showing in the preview window.
+ let a:matchObject.info = l:menu
+ endif
+ endif
+
+ return a:matchObject
+endfunction
+
let s:lastCompletionsByBaseCol = {}
let s:nextBaseIdx = 0
let s:initialCompletePosition = []
@@ -206,7 +272,9 @@ function! SnippetComplete#SnippetComplete( types )
if l:baseNum > 0
" Show the completions for the current base.
- call complete(l:baseColumns[l:baseIdx], sort(s:lastCompletionsByBaseCol[l:baseColumns[l:baseIdx]], 's:CompletionCompare'))
+ let l:matches = sort(s:lastCompletionsByBaseCol[l:baseColumns[l:baseIdx]], 's:CompletionCompare')
+ call map(l:matches, 's:FormatMatches(v:val)')
+ call complete(l:baseColumns[l:baseIdx], l:matches)
let s:lastCompleteEndPosition = s:RecordPosition()
if l:baseNum > 1
@@ -25,10 +25,19 @@ and complete defined abbreviations directly while typing.
==============================================================================
USAGE *SnippetComplete-usage*
+
+In insert mode, optionally type part of the snippet shortcut or a fragment
+from its expected expansion, and invoke the snippet completion via CTRL-X ].
+You can then search forward and backward via CTRL-N / CTRL-P, as usual.
*i_CTRL-X_]*
-i_CTRL-X_] Find matches for abbreviations that start with the
+CTRL-X ] Find matches for abbreviations that start with the
text in front of the cursor. If other snippet types
are registered, show those, too.
+ If no matches were found that way, matches anywhere in
+ the snippet or in the snippet's expanded text will be
+ shown. So if you can't remember the shortcut, but a
+ word fragment from the resulting expansion, just try
+ with that.
There are three types of |abbreviations| (full-id,
end-id and non-id), which can consist of different
@@ -50,22 +59,27 @@ i_CTRL-X_] Find matches for abbreviations that start with the
INSTALLATION *SnippetComplete-installation*
This script is packaged as a |vimball|. If you have the "gunzip" decompressor
-in your PATH, simply edit the *.vba.gz package in Vim; otherwise, decompress
+in your PATH, simply edit the *.vmb.gz package in Vim; otherwise, decompress
the archive first, e.g. using WinZip. Inside Vim, install by sourcing the
vimball or via the |:UseVimball| command. >
- vim SnippetComplete.vba.gz
+ vim SnippetComplete*.vmb.gz
:so %
To uninstall, use the |:RmVimball| command.
DEPENDENCIES *SnippetComplete-dependencies*
- Requires Vim 7.0 or higher.
+- Requires the |CompleteHelper.vim| plugin (vimscript #3914), version 1.10 or
+ higher.
==============================================================================
CONFIGURATION *SnippetComplete-configuration*
+For a permanent configuration, put the following commands into your |vimrc|:
+
+ *SnippetComplete-remap*
If you want to use a different mapping, map your keys to the
-<Plug>(SnippetComplete) mapping target _before_ sourcing this script (e.g. in
+<Plug>(SnippetComplete) mapping target _before_ sourcing the script (e.g. in
your |vimrc|).
For example, to use CTRL-X <Tab>, use this: >
imap <C-x><Tab> <Plug>(SnippetComplete)
@@ -117,13 +131,20 @@ KNOWN PROBLEMS *SnippetComplete-known-problems*
TODO *SnippetComplete-todo*
- Getting and sorting of matches when 'ignorecase' is on.
-- Limiting the length of the snippet expansion shown in the popup menu.
IDEAS *SnippetComplete-ideas*
==============================================================================
HISTORY *SnippetComplete-history*
+2.10 19-Oct-2012
+- ENH: When no base doesn't match with the beginning of a snippet, fall back
+ to matches either anywhere in the snippet or in the snippet expansion.
+- Truncate very long or multi-line snippet expansions in the popup menu. This
+ requires the CompleteHelper plugin. When the entire snippet doesn't fit into
+ the popup menu, offer it for showing in the preview window.
+ *** THIS PLUGIN NOW REQUIRES THE CompleteHelper PLUGIN (vimscript #3914) ***
+
2.01 13-Aug-2012
- FIX: Vim 7.0/1 need preloading of functions referenced in Funcrefs.

0 comments on commit 29f6015

Please sign in to comment.