Skip to content
This repository has been archived by the owner on Jul 27, 2018. It is now read-only.

Commit

Permalink
Rafactor for snippet support. Sketch for neosnippet api. Shougo/neosn…
Browse files Browse the repository at this point in the history
  • Loading branch information
roxma committed Sep 1, 2017
1 parent d940aa1 commit 15020d6
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 91 deletions.
66 changes: 5 additions & 61 deletions autoload/cm.vim
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ endif
let s:init = 1
let s:already_setup = 0

inoremap <silent> <expr> <Plug>(cm_inject_snippet) <SID>check_and_inject_snippet()
inoremap <silent> <expr> <Plug>(cm_inject_snippet) cm#snippet#check_and_inject()
" use silent mapping that doesn't slower the terminal ui
" Note: `:help complete()` says:
Expand Down Expand Up @@ -45,8 +45,9 @@ func! cm#enable_for_buffer(...)
endif

if s:already_setup == 0
doautocmd User CmSetup
let s:already_setup = 1
call cm#snippet#init()
doautocmd User CmSetup
endif

" remove to avoid conflict: #34
Expand Down Expand Up @@ -268,7 +269,6 @@ let s:channel_jobid = -1
let g:_cm_channel_id = -1
let s:channel_started = 0
let g:_cm_start_py_path = globpath(&rtp,'pythonx/cm_start.py',1)
let s:snippets = []
let s:complete_start_timer = 0
let s:old_rtp = &rtp

Expand Down Expand Up @@ -377,7 +377,7 @@ func! cm#_core_complete(context, startcol, matches, not_changed, snippets)
let s:startcol = a:startcol
let l:padcmd = 'extend(v:val,{"abbr":printf("%".strdisplaywidth(v:val["padding"])."s%s","",v:val["abbr"])})'
let s:matches = map(a:matches, l:padcmd)
let s:snippets = a:snippets
let g:cm#snippet#snippets = a:snippets

call feedkeys(g:cm_completekeys, 'i')

Expand Down Expand Up @@ -514,70 +514,14 @@ func! s:check_changes(...)
endif
endif

call s:check_and_inject_snippet()
call cm#snippet#check_and_inject()
endfunc

func! s:complete_start_timer_handler(...)
let s:complete_start_timer = 0
call s:on_changed()
endfunc

func! s:check_and_inject_snippet()

if empty(v:completed_item) || !has_key(v:completed_item,'info') || empty(v:completed_item.info) || has_key(v:completed_item,'snippet')
return ''
endif

let l:last_line = split(v:completed_item.info,'\n')[-1]
if l:last_line[0:len('snippet@')-1]!='snippet@'
return ''
endif

let l:snippet_id = str2nr(l:last_line[len('snippet@'):])
if l:snippet_id>=len(s:snippets) || l:snippet_id<0
return ''
endif

" neosnippet recognize the snippet field of v:completed_item. Also useful
" for checking. Kind of a hack.
let v:completed_item.snippet = s:snippets[l:snippet_id]['snippet']
let v:completed_item.snippet_word = s:snippets[l:snippet_id]['word']

if v:completed_item.snippet == ''
return ''
endif

if g:cm_completed_snippet_engine == 'ultisnips'
if get(b:,'_cm_us_setup',0)==0
" UltiSnips_Manager.add_buffer_filetypes('%s.snips.ncm' % vim.eval('&filetype'))
let b:_cm_us_setup = 1
let b:_cm_us_filetype = 'ncm'
call UltiSnips#AddFiletypes(b:_cm_us_filetype)
autocmd InsertLeave <buffer> exec g:_uspy 'UltiSnips_Manager._added_snippets_source._snippets["ncm"]._snippets = []'
endif
exec g:_uspy 'UltiSnips_Manager._added_snippets_source._snippets["ncm"]._snippets = []'
" TODO cleanup when InsertLeave
call UltiSnips#AddSnippetWithPriority(v:completed_item.snippet_word, v:completed_item.snippet, '', 'i', b:_cm_us_filetype, 1)
elseif g:cm_completed_snippet_engine == 'snipmate'
if !exists('s:completed_item')
let s:completed_item = {}
autocmd InsertLeave * let s:completed_item = {}
" inject ncm's handler into snipmate
let g:snipMateSources['ncm'] = funcref#Function('cm#_snipmate_snippets')
endif
let s:completed_item = v:completed_item
endif

return ''
endfunc

func! cm#_snipmate_snippets(scopes, trigger, result)
if empty(s:completed_item)
return
endif
let a:result[s:completed_item['snippet_word']] = {'default': [s:completed_item.snippet,0] }
endfunc

" on completion context changed
func! s:on_changed()

Expand Down
126 changes: 126 additions & 0 deletions autoload/cm/snippet.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@

let g:cm#snippet#snippets = []

func! cm#snippet#init()
if !exists('g:cm_completed_snippet_enable')
if exists('g:loaded_neosnippet')
let g:cm_completed_snippet_enable = 1
let g:cm_completed_snippet_engine = 'neosnippet'
" Not compatible with neosnippet#enable_completed_snippet. NCM
" choose a different approach
let g:neosnippet#enable_completed_snippet=0
call s:neosnippet_init()
elseif exists('g:did_plugin_ultisnips')
let g:cm_completed_snippet_enable = 1
let g:cm_completed_snippet_engine = 'ultisnips'
elseif exists('g:snipMateSources')
let g:cm_completed_snippet_enable = 1
let g:cm_completed_snippet_engine = 'snipmate'
call s:snipmate_init()
else
let g:cm_completed_snippet_enable = 0
let g:cm_completed_snippet_engine = ''
endif
endif
if !exists('g:cm_completed_snippet_engine')
let g:cm_completed_snippet_engine = ''
endif
endfunc

func! cm#snippet#check_and_inject()

if empty(v:completed_item) || !has_key(v:completed_item,'info') || empty(v:completed_item.info) || has_key(v:completed_item,'snippet')
return ''
endif

let l:last_line = split(v:completed_item.info,'\n')[-1]
if l:last_line[0:len('snippet@')-1]!='snippet@'
return ''
endif

let l:snippet_id = str2nr(l:last_line[len('snippet@'):])
if l:snippet_id>=len(g:cm#snippet#snippets) || l:snippet_id<0
return ''
endif

" neosnippet recognize the snippet field of v:completed_item. Also useful
" for checking. Kind of a hack.
let v:completed_item.snippet = g:cm#snippet#snippets[l:snippet_id]['snippet']
let v:completed_item.snippet_word = g:cm#snippet#snippets[l:snippet_id]['word']

if v:completed_item.snippet == ''
return ''
endif

if g:cm_completed_snippet_engine == 'ultisnips'

call s:ultisnips_inject()

" elseif g:cm_completed_snippet_engine == 'snipmate'
" nothing needs to be done for snipmate

elseif g:cm_completed_snippet_engine == 'neosnippet'

call s:neosnippet_inject()

endif

return ''
endfunc

func! s:ultisnips_inject()
if get(b:,'_cm_us_setup',0)==0
" UltiSnips_Manager.add_buffer_filetypes('%s.snips.ncm' % vim.eval('&filetype'))
let b:_cm_us_setup = 1
let b:_cm_us_filetype = 'ncm'
call UltiSnips#AddFiletypes(b:_cm_us_filetype)
augroup cm
autocmd InsertLeave <buffer> exec g:_uspy 'UltiSnips_Manager._added_snippets_source._snippets["ncm"]._snippets = []'
augroup END
endif
exec g:_uspy 'UltiSnips_Manager._added_snippets_source._snippets["ncm"]._snippets = []'
call UltiSnips#AddSnippetWithPriority(v:completed_item.snippet_word, v:completed_item.snippet, '', 'i', b:_cm_us_filetype, 1)
endfunc

func! s:neosnippet_init()
augroup cm
autocmd InsertEnter * call s:neosnippet_cleanup()
augroup END
let s:neosnippet_injected = []
endfunc

func! s:neosnippet_inject()
let snippets = neosnippet#variables#current_neosnippet()

let item = {}
let item['options'] = { "word": 1, "oneshot": 0, "indent": 0, "head": 0}
let item['word'] = v:completed_item.snippet_word
let item['snip'] = v:completed_item.snippet
let item['description'] = ''

let snippets.snippets[v:completed_item.snippet_word] = item

" remember for cleanup
let s:neosnippet_injected = add(s:neosnippet_injected, v:completed_item.snippet_word)
endfunc

func! s:neosnippet_cleanup()
let cs = neosnippet#variables#current_neosnippet()
for word in s:neosnippet_injected
unlet cs.snippets[word]
endfor
let s:neosnippet_injected = []
endfunc

func! s:snipmate_init()
" inject ncm's handler into snipmate
let g:snipMateSources.ncm = funcref#Function('cm#snippet#_snipmate_snippets')
endfunc

func! cm#snippet#_snipmate_snippets(scopes, trigger, result)
if empty(v:completed_item)
return
endif
let a:result[v:completed_item.snippet_word] = {'default': [v:completed_item.snippet, 0] }
endfunc

24 changes: 0 additions & 24 deletions plugin/cm.vim
Original file line number Diff line number Diff line change
Expand Up @@ -57,30 +57,6 @@ let g:cm_refresh_length = get(g:, 'cm_refresh_length', get(g:, 'cm_refresh_defau

let g:cm_completeopt=get(g:,'cm_completeopt','menu,menuone,noinsert,noselect')

" runs after snippet plugin is loaded
func! s:snippet_init()
if !exists('g:cm_completed_snippet_enable')
if get(g:,'neosnippet#enable_completed_snippet',0)
let g:cm_completed_snippet_enable = 1
let g:cm_completed_snippet_engine = 'neosnippet'
elseif exists('g:did_plugin_ultisnips')
let g:cm_completed_snippet_enable = 1
let g:cm_completed_snippet_engine = 'ultisnips'
elseif exists('g:snipMateSources')
let g:cm_completed_snippet_enable = 1
let g:cm_completed_snippet_engine = 'snipmate'
else
let g:cm_completed_snippet_enable = 0
let g:cm_completed_snippet_engine = ''
endif
endif
if !exists('g:cm_completed_snippet_engine')
let g:cm_completed_snippet_engine = ''
endif
endfunc

au User CmSetup call s:snippet_init()

" use did_plugin_ultisnips to detect the installation of ultisnips
" https://github.com/SirVer/ultisnips/blob/76ebfec3cf7340a1edd90ea052b16910733c96b0/autoload/UltiSnips.vim#L1
au User CmSetup if exists('g:did_plugin_ultisnips') | call cm#register_source({'name' : 'cm-ultisnips',
Expand Down
6 changes: 0 additions & 6 deletions pythonx/cm_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -648,12 +648,6 @@ def _complete(self, ctx, startcol, matches):

if snippet:

if self._completed_snippet_engine=='neosnippet':
# neosnippet does not remove the completed word
# make them compatible if possible
if snippet[0:len(m['snippet_word'])] == m['snippet_word']:
snippet = snippet[len(m['snippet_word']):]

# snippet word should not contain spaces
rp = m['snippet_word'].split(' ')[0]
m['word'] = m['word'][:-len(m['snippet_word'])] + rp
Expand Down

0 comments on commit 15020d6

Please sign in to comment.