Skip to content

Commit

Permalink
Version 2.10
Browse files Browse the repository at this point in the history
- 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
Ingo Karkat authored and vim-scripts committed Oct 22, 2012
1 parent 061b1bf commit 29f6015
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 19 deletions.
18 changes: 16 additions & 2 deletions README
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -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 This plugin offers a context-sensitive insert mode completion to quickly list
and complete defined abbreviations directly while typing. 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 USAGE
i_CTRL-X_] Find matches for abbreviations that start with the In insert mode, optionally type part of the snippet shortcut or a fragment
text in front of the cursor. 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, There are three types of abbreviations (full-id,
end-id and non-id), which can consist of different end-id and non-id), which can consist of different
Expand Down
92 changes: 80 additions & 12 deletions autoload/SnippetComplete.vim
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,13 +2,26 @@
" abbreviations and snippets. " abbreviations and snippets.
" "
" DEPENDENCIES: " DEPENDENCIES:
" - CompleteHelper/Abbreviate.vim autoload script
" "
" Copyright: (C) 2010-2012 Ingo Karkat " Copyright: (C) 2010-2012 Ingo Karkat
" The VIM LICENSE applies to this script; see ':help copyright'. " The VIM LICENSE applies to this script; see ':help copyright'.
" "
" Maintainer: Ingo Karkat <ingo@karkat.de> " Maintainer: Ingo Karkat <ingo@karkat.de>
" "
" REVISION DATE REMARKS " 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 " 2.00.003 05-May-2012 Rewrite s:RegistryTypeCompare() so that it
" doesn't need to access " doesn't need to access
" g:SnippetComplete_Registry. " g:SnippetComplete_Registry.
Expand Down Expand Up @@ -109,21 +122,28 @@ endfunction
function! s:GetBase( baseCol, cursorCol ) function! s:GetBase( baseCol, cursorCol )
return strpart(getline('.'), a:baseCol - 1, (a:cursorCol - a:baseCol)) return strpart(getline('.'), a:baseCol - 1, (a:cursorCol - a:baseCol))
endfunction endfunction
function! s:MatchSnippets( snippets, baseCol ) function! s:MatchSnippetsStrict( snippets, base )
let l:base = s:GetBase(a:baseCol, col('.')) return filter(copy(a:snippets), 'strpart(v:val.word, 0, ' . len(a:base) . ') ==# ' . string(a:base))
"****D echomsg '****' a:baseCol l:base endfunction
return (empty(l:base) ? function! s:MatchSnippetsRelaxed( snippets, base )
\ a:snippets : return filter(copy(a:snippets), 'stridx(v:val.word, a:base) != -1')
\ filter(copy(a:snippets), 'strpart(v:val.word, 0, ' . len(l:base) . ') ==# ' . string(l:base)) 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 endfunction
function! s:GetSnippetCompletions( types ) function! s:GetSnippetCompletionsWithStrategy( Strategy, types, baseColumns )
let l:baseColumns = s:DetermineBaseCol(a:types)
"****D echomsg '####' string(l:baseColumns)
let l:completionsByBaseCol = {} 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: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) "****D echomsg '****' l:type string(l:matches)
if ! empty(l:matches) if ! empty(l:matches)
let l:completions = get(l:completionsByBaseCol, l:baseCol, []) let l:completions = get(l:completionsByBaseCol, l:baseCol, [])
Expand All @@ -134,6 +154,35 @@ function! s:GetSnippetCompletions( types )
"****D echomsg '****' string(l:completionsByBaseCol) "****D echomsg '****' string(l:completionsByBaseCol)
return l:completionsByBaseCol return l:completionsByBaseCol
endfunction 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 ) function! s:CompletionCompare( c1, c2 )
return (a:c1.word ==# a:c2.word ? 0 : a:c1.word ># a:c2.word ? 1 : -1) return (a:c1.word ==# a:c2.word ? 0 : a:c1.word ># a:c2.word ? 1 : -1)
endfunction endfunction
Expand Down Expand Up @@ -175,6 +224,23 @@ function! s:RecordPosition()
" a window above the current), the position changes. " a window above the current), the position changes.
return getpos('.') + [bufnr(''), winnr(), tabpagenr()] return getpos('.') + [bufnr(''), winnr(), tabpagenr()]
endfunction 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:lastCompletionsByBaseCol = {}
let s:nextBaseIdx = 0 let s:nextBaseIdx = 0
let s:initialCompletePosition = [] let s:initialCompletePosition = []
Expand Down Expand Up @@ -206,7 +272,9 @@ function! SnippetComplete#SnippetComplete( types )


if l:baseNum > 0 if l:baseNum > 0
" Show the completions for the current base. " 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() let s:lastCompleteEndPosition = s:RecordPosition()


if l:baseNum > 1 if l:baseNum > 1
Expand Down
31 changes: 26 additions & 5 deletions doc/SnippetComplete.txt
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -25,10 +25,19 @@ and complete defined abbreviations directly while typing.


============================================================================== ==============================================================================
USAGE *SnippetComplete-usage* 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_]*
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 text in front of the cursor. If other snippet types
are registered, show those, too. 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, There are three types of |abbreviations| (full-id,
end-id and non-id), which can consist of different end-id and non-id), which can consist of different
Expand All @@ -50,22 +59,27 @@ i_CTRL-X_] Find matches for abbreviations that start with the
INSTALLATION *SnippetComplete-installation* INSTALLATION *SnippetComplete-installation*


This script is packaged as a |vimball|. If you have the "gunzip" decompressor 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 the archive first, e.g. using WinZip. Inside Vim, install by sourcing the
vimball or via the |:UseVimball| command. > vimball or via the |:UseVimball| command. >
vim SnippetComplete.vba.gz vim SnippetComplete*.vmb.gz
:so % :so %
To uninstall, use the |:RmVimball| command. To uninstall, use the |:RmVimball| command.


DEPENDENCIES *SnippetComplete-dependencies* DEPENDENCIES *SnippetComplete-dependencies*


- Requires Vim 7.0 or higher. - Requires Vim 7.0 or higher.
- Requires the |CompleteHelper.vim| plugin (vimscript #3914), version 1.10 or
higher.


============================================================================== ==============================================================================
CONFIGURATION *SnippetComplete-configuration* 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 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|). your |vimrc|).
For example, to use CTRL-X <Tab>, use this: > For example, to use CTRL-X <Tab>, use this: >
imap <C-x><Tab> <Plug>(SnippetComplete) imap <C-x><Tab> <Plug>(SnippetComplete)
Expand Down Expand Up @@ -117,13 +131,20 @@ KNOWN PROBLEMS *SnippetComplete-known-problems*
TODO *SnippetComplete-todo* TODO *SnippetComplete-todo*


- Getting and sorting of matches when 'ignorecase' is on. - Getting and sorting of matches when 'ignorecase' is on.
- Limiting the length of the snippet expansion shown in the popup menu.


IDEAS *SnippetComplete-ideas* IDEAS *SnippetComplete-ideas*


============================================================================== ==============================================================================
HISTORY *SnippetComplete-history* 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 2.01 13-Aug-2012
- FIX: Vim 7.0/1 need preloading of functions referenced in Funcrefs. - FIX: Vim 7.0/1 need preloading of functions referenced in Funcrefs.


Expand Down

0 comments on commit 29f6015

Please sign in to comment.