diff --git a/autoload/neosnippet.vim b/autoload/neosnippet.vim index 26a4094..3b67b22 100644 --- a/autoload/neosnippet.vim +++ b/autoload/neosnippet.vim @@ -48,490 +48,6 @@ function! neosnippet#jumpable() "{{{ return neosnippet#mappings#jumpable() endfunction"}}} -function! neosnippet#jump(cur_text, col) "{{{ - call s:skip_next_auto_completion() - - let expand_stack = neosnippet#variables#expand_stack() - - " Get patterns and count. - if empty(expand_stack) - return s:search_outof_range(a:col) - endif - - let expand_info = expand_stack[-1] - " Search patterns. - let [begin, end] = neosnippet#_get_snippet_range( - \ expand_info.begin_line, - \ expand_info.begin_patterns, - \ expand_info.end_line, - \ expand_info.end_patterns) - if neosnippet#_search_snippet_range(begin, end, expand_info.holder_cnt) - " Next count. - let expand_info.holder_cnt += 1 - return 1 - endif - - " Search placeholder 0. - if neosnippet#_search_snippet_range(begin, end, 0) - return 1 - endif - - " Not found. - let expand_stack = neosnippet#variables#expand_stack() - let expand_stack = expand_stack[: -2] - - return s:search_outof_range(a:col) -endfunction"}}} -function! neosnippet#expand(cur_text, col, trigger_name) "{{{ - call s:skip_next_auto_completion() - - let snippets = neosnippet#helpers#get_snippets() - - if a:trigger_name == '' || !has_key(snippets, a:trigger_name) - let pos = getpos('.') - let pos[2] = len(a:cur_text)+1 - call setpos('.', pos) - - if pos[2] < col('$') - startinsert - else - startinsert! - endif - - return - endif - - let snippet = snippets[a:trigger_name] - let cur_text = a:cur_text[: -1-len(a:trigger_name)] - - let snip_word = snippet.snip - if snip_word =~ '\\\@', 'g') - let snip_word = substitute(snip_word, - \ '\\\@', 'g') - let snip_word = substitute(snip_word, - \ '\\'.neosnippet#get_mirror_placeholder_marker_substitute_pattern().'\|'. - \ '\\'.neosnippet#get_placeholder_marker_substitute_pattern(), - \ '\=submatch(0)[1:]', 'g') - - " Insert snippets. - let next_line = getline('.')[a:col-1 :] - let snippet_lines = split(snip_word, '\n', 1) - if empty(snippet_lines) - return - endif - - let begin_line = line('.') - let end_line = line('.') + len(snippet_lines) - 1 - - let snippet_lines[0] = cur_text . snippet_lines[0] - let next_col = len(snippet_lines[-1]) + 1 - let snippet_lines[-1] = snippet_lines[-1] . next_line - - if has('folding') - " Note: Change foldmethod to "manual". Because, if you use foldmethod is - " expr, whole snippet is visually selected. - let foldmethod_save = &l:foldmethod - let &l:foldmethod = 'manual' - endif - - let expand_stack = neosnippet#variables#expand_stack() - - try - call setline('.', snippet_lines[0]) - if len(snippet_lines) > 1 - call append('.', snippet_lines[1:]) - endif - - if begin_line != end_line || snippet.options.indent - call s:indent_snippet(begin_line, end_line) - endif - - let begin_patterns = (begin_line > 1) ? - \ [getline(begin_line - 1)] : [] - let end_patterns = (end_line < line('$')) ? - \ [getline(end_line + 1)] : [] - call add(expand_stack, { - \ 'begin_line' : begin_line, - \ 'begin_patterns' : begin_patterns, - \ 'end_line' : end_line, - \ 'end_patterns' : end_patterns, - \ 'holder_cnt' : 1, - \ }) - - if snip_word =~ neosnippet#get_placeholder_marker_pattern() - call neosnippet#jump(a:cur_text, a:col) - endif - finally - if has('folding') - if foldmethod_save !=# &l:foldmethod - let &l:foldmethod = foldmethod_save - endif - - silent! execute begin_line . ',' . end_line . 'foldopen!' - endif - endtry - - let &l:iminsert = 0 - let &l:imsearch = 0 -endfunction"}}} -function! neosnippet#expand_target() "{{{ - let trigger = input('Please input snippet trigger: ', - \ '', 'customlist,neosnippet#commands#_complete_target_snippets') - let neosnippet = neosnippet#variables#current_neosnippet() - if !has_key(neosnippet#helpers#get_snippets(), trigger) || - \ neosnippet#helpers#get_snippets()[trigger].snip !~# - \ neosnippet#get_placeholder_target_marker_pattern() - if trigger != '' - echo 'The trigger is invalid.' - endif - - let neosnippet.target = '' - return - endif - - call neosnippet#expand_target_trigger(trigger) -endfunction"}}} -function! neosnippet#expand_target_trigger(trigger) "{{{ - let neosnippet = neosnippet#variables#current_neosnippet() - let neosnippet.target = substitute( - \ neosnippet#helpers#get_selected_text(visualmode(), 1), '\n$', '', '') - - let line = getpos("'<")[1] - let col = getpos("'<")[2] - - call neosnippet#helpers#delete_selected_text(visualmode()) - - call cursor(line, col) - - call neosnippet#expand(neosnippet#util#get_cur_text(), col, a:trigger) -endfunction"}}} -function! s:indent_snippet(begin, end) "{{{ - if a:begin > a:end - return - endif - - let pos = getpos('.') - - let neosnippet = neosnippet#variables#current_neosnippet() - - let equalprg = &l:equalprg - try - setlocal equalprg= - - " Indent begin line? - let begin = (neosnippet.target == '') ? a:begin : a:begin + 1 - - let base_indent = matchstr(getline(a:begin), '^\s\+') - for line_nr in range(begin, a:end) - call cursor(line_nr, 0) - - if getline('.') =~ '^\t\+' - " Delete head tab character. - let current_line = substitute(getline('.'), '^\t', '', '') - - if &l:expandtab && current_line =~ '^\t\+' - " Expand tab. - cal setline('.', substitute(current_line, - \ '^\t\+', base_indent . repeat(' ', &shiftwidth * - \ len(matchstr(current_line, '^\t\+'))), '')) - elseif line_nr != a:begin - call setline('.', base_indent . current_line) - endif - else - silent normal! == - endif - endfor - finally - let &l:equalprg = equalprg - call setpos('.', pos) - endtry -endfunction"}}} - -function! neosnippet#_get_snippet_range(begin_line, begin_patterns, end_line, end_patterns) "{{{ - let pos = getpos('.') - - call cursor(a:begin_line, 0) - if empty(a:begin_patterns) - let begin = line('.') - 50 - else - let [begin, _] = searchpos('^' . neosnippet#util#escape_pattern( - \ a:begin_patterns[0]) . '$', 'bnW') - if begin <= 0 - let begin = line('.') - 50 - endif - endif - if begin <= 0 - let begin = 1 - endif - - call cursor(a:end_line, 0) - if empty(a:end_patterns) - let end = line('.') + 50 - else - let [end, _] = searchpos('^' . neosnippet#util#escape_pattern( - \ a:end_patterns[0]) . '$', 'nW') - if end <= 0 - let end = line('.') + 50 - endif - endif - if end > line('$') - let end = line('$') - endif - - call setpos('.', pos) - return [begin, end] -endfunction"}}} -function! neosnippet#_search_snippet_range(start, end, cnt, ...) "{{{ - let is_select = get(a:000, 0, 1) - call s:substitute_placeholder_marker(a:start, a:end, a:cnt) - - " Search marker pattern. - let pattern = substitute(neosnippet#get_placeholder_marker_pattern(), - \ '\\d\\+', a:cnt, '') - - for line in filter(range(a:start, a:end), - \ 'getline(v:val) =~ pattern') - call s:expand_placeholder(a:start, a:end, a:cnt, line, is_select) - return 1 - endfor - - return 0 -endfunction"}}} -function! s:search_outof_range(col) "{{{ - call s:substitute_placeholder_marker(1, 0, 0) - - let pattern = neosnippet#get_placeholder_marker_pattern() - if search(pattern, 'w') > 0 - call s:expand_placeholder(line('.'), 0, '\\d\\+', line('.')) - return 1 - endif - - let pos = getpos('.') - if a:col == 1 - let pos[2] = 1 - call setpos('.', pos) - startinsert - elseif a:col >= col('$') - startinsert! - else - let pos[2] = a:col+1 - call setpos('.', pos) - startinsert - endif - - " Not found. - return 0 -endfunction"}}} -function! s:expand_placeholder(start, end, holder_cnt, line, ...) "{{{ - let is_select = get(a:000, 0, 1) - - let pattern = substitute(neosnippet#get_placeholder_marker_pattern(), - \ '\\d\\+', a:holder_cnt, '') - let current_line = getline(a:line) - let match = match(current_line, pattern) - let neosnippet = neosnippet#variables#current_neosnippet() - - let default_pattern = substitute( - \ neosnippet#get_placeholder_marker_default_pattern(), - \ '\\d\\+', a:holder_cnt, '') - let default = substitute( - \ matchstr(current_line, default_pattern), - \ '\\\ze[^\\]', '', 'g') - - if default =~ '^TARGET\>' && neosnippet.target != '' - let default = '' - let is_target = 1 - else - let is_target = 0 - endif - - let default = substitute(default, '^TARGET:\?', '', '') - - let neosnippet.selected_text = default - - " Substitute marker. - let default = substitute(default, - \ neosnippet#get_placeholder_marker_substitute_pattern(), - \ '<`\1`>', 'g') - let default = substitute(default, - \ neosnippet#get_mirror_placeholder_marker_substitute_pattern(), - \ '<|\1|>', 'g') - - " len() cannot use for multibyte. - let default_len = len(substitute(default, '.', 'x', 'g')) - - let pos = getpos('.') - let pos[1] = a:line - let pos[2] = match+1 - - let cnt = s:search_sync_placeholder(a:start, a:end, a:holder_cnt) - if cnt >= 0 - let pattern = substitute(neosnippet#get_placeholder_marker_pattern(), - \ '\\d\\+', cnt, '') - call setline(a:line, substitute(current_line, pattern, - \ '<{'.cnt.':'.escape(default, '\').'}>', '')) - let pos[2] += len('<{'.cnt.':') - else - " Substitute holder. - call setline(a:line, - \ substitute(current_line, pattern, escape(default, '\'), '')) - endif - - call setpos('.', pos) - - if is_target - " Expand target - return s:expand_target_placeholder(a:line, match+1) - endif - - if default_len > 0 && is_select - " Select default value. - let len = default_len-1 - if &l:selection == 'exclusive' - let len += 1 - endif - - stopinsert - execute 'normal! v'. repeat('l', len) . "\" - elseif pos[2] < col('$') - startinsert - else - startinsert! - endif -endfunction"}}} -function! s:expand_target_placeholder(line, col) "{{{ - " Expand target - let neosnippet = neosnippet#variables#current_neosnippet() - let next_line = getline(a:line)[a:col-1 :] - let target_lines = split(neosnippet.target, '\n', 1) - - let cur_text = getline(a:line)[: a:col-2] - let target_lines[0] = cur_text . target_lines[0] - let next_col = len(target_lines[-1]) + 1 - let target_lines[-1] = target_lines[-1] . next_line - - let begin_line = a:line - let end_line = a:line + len(target_lines) - 1 - - let col = col('.') - try - let base_indent = matchstr(cur_text, '^\s\+') - call setline(a:line, target_lines[0]) - if len(target_lines) > 1 - call append(a:line, map(target_lines[1:], - \ 'base_indent . v:val')) - endif - - call cursor(end_line, 0) - - if next_line != '' - startinsert - let col = col('.') - else - startinsert! - let col = col('$') - endif - finally - if has('folding') - silent! execute begin_line . ',' . end_line . 'foldopen!' - endif - endtry - - let neosnippet.target = '' - - call neosnippet#jump(neosnippet#util#get_cur_text(), col) -endfunction"}}} -function! s:search_sync_placeholder(start, end, number) "{{{ - if a:end == 0 - " Search in current buffer. - let cnt = matchstr(getline('.'), - \ substitute(neosnippet#get_placeholder_marker_pattern(), - \ '\\d\\+', '\\zs\\d\\+\\ze', '')) - return search(substitute( - \ neosnippet#get_mirror_placeholder_marker_pattern(), - \ '\\d\\+', cnt, ''), 'nw') > 0 ? cnt : -1 - endif - - let pattern = substitute( - \ neosnippet#get_mirror_placeholder_marker_pattern(), - \ '\\d\\+', a:number, '') - for line in filter(range(a:start, a:end), - \ 'getline(v:val) =~ pattern') - return a:number - endfor - - return -1 -endfunction"}}} -function! s:substitute_placeholder_marker(start, end, snippet_holder_cnt) "{{{ - if a:snippet_holder_cnt > 0 - let cnt = a:snippet_holder_cnt-1 - let sync_marker = substitute(neosnippet#get_sync_placeholder_marker_pattern(), - \ '\\d\\+', cnt, '') - let mirror_marker = substitute( - \ neosnippet#get_mirror_placeholder_marker_pattern(), - \ '\\d\\+', cnt, '') - let line = a:start - - for line in range(a:start, a:end) - if getline(line) =~ sync_marker - let sub = escape(matchstr(getline(line), - \ substitute(neosnippet#get_sync_placeholder_marker_default_pattern(), - \ '\\d\\+', cnt, '')), '/\') - silent execute printf('%d,%ds/\m' . mirror_marker . '/%s/' - \ . (&gdefault ? '' : 'g'), a:start, a:end, sub) - call setline(line, substitute(getline(line), sync_marker, sub, '')) - endif - endfor - elseif search(neosnippet#get_sync_placeholder_marker_pattern(), 'wb') > 0 - let sub = escape(matchstr(getline('.'), - \ neosnippet#get_sync_placeholder_marker_default_pattern()), '/\') - let cnt = matchstr(getline('.'), - \ substitute(neosnippet#get_sync_placeholder_marker_pattern(), - \ '\\d\\+', '\\zs\\d\\+\\ze', '')) - let mirror_marker = substitute( - \ neosnippet#get_mirror_placeholder_marker_pattern(), - \ '\\d\\+', cnt, '') - silent execute printf('%%s/\m' . mirror_marker . '/%s/' - \ . (&gdefault ? 'g' : ''), sub) - let sync_marker = substitute(neosnippet#get_sync_placeholder_marker_pattern(), - \ '\\d\\+', cnt, '') - call setline('.', substitute(getline('.'), sync_marker, sub, '')) - endif -endfunction"}}} -function! s:eval_snippet(snippet_text) "{{{ - let snip_word = '' - let prev_match = 0 - let match = match(a:snippet_text, '\\\@= 0 - if match - prev_match > 0 - let snip_word .= a:snippet_text[prev_match : match - 1] - endif - let prev_match = matchend(a:snippet_text, - \ '\\\@= 0 - let snip_word .= a:snippet_text[prev_match :] - endif - - return snip_word -endfunction"}}} - function! neosnippet#get_snippets_directory() "{{{ return neosnippet#helpers#get_snippets_directory() endfunction"}}} @@ -568,19 +84,6 @@ function! neosnippet#get_mirror_placeholder_marker_substitute_pattern() "{{{ return '\$\(\d\+\)' endfunction"}}} -function! s:skip_next_auto_completion() "{{{ - " Skip next auto completion. - if exists('*neocomplcache#skip_next_complete') - call neocomplcache#skip_next_complete() - endif - if exists('*neocomplete#skip_next_complete') - call neocomplete#skip_next_complete() - endif - - let neosnippet = neosnippet#variables#current_neosnippet() - let neosnippet.trigger = 0 -endfunction"}}} - let &cpo = s:save_cpo unlet s:save_cpo diff --git a/autoload/neosnippet/init.vim b/autoload/neosnippet/init.vim index c5c822a..4b6a0af 100644 --- a/autoload/neosnippet/init.vim +++ b/autoload/neosnippet/init.vim @@ -77,14 +77,14 @@ endfunction"}}} function! s:initialize_others() "{{{ augroup neosnippet "{{{ autocmd! - " Set caching event. + " Set make cache event. autocmd FileType * call neosnippet#commands#_make_cache(&filetype) - " Recaching events + " Re make cache events autocmd BufWritePost *.snip,*.snippets \ call neosnippet#variables#set_snippets({}) autocmd BufEnter * \ call neosnippet#mappings#_clear_select_mode_mappings() - autocmd InsertLeave * call s:on_insert_leave() + autocmd InsertLeave * call neosnippet#view#_on_insert_leave() augroup END"}}} augroup neosnippet @@ -125,52 +125,6 @@ function! s:initialize_others() "{{{ endif"}}} endfunction"}}} -function! s:on_insert_leave() "{{{ - let expand_stack = neosnippet#variables#expand_stack() - - " Get patterns and count. - if empty(expand_stack) - \ || neosnippet#variables#current_neosnippet().trigger - return - endif - - let expand_info = expand_stack[-1] - - if expand_info.begin_line != expand_info.end_line - return - endif - - " Search patterns. - let [begin, end] = neosnippet#_get_snippet_range( - \ expand_info.begin_line, - \ expand_info.begin_patterns, - \ expand_info.end_line, - \ expand_info.end_patterns) - - let pos = getpos('.') - - " Found snippet. - let found = 0 - try - while neosnippet#_search_snippet_range(begin, end, expand_info.holder_cnt, 0) - " Next count. - let expand_info.holder_cnt += 1 - let found = 1 - endwhile - - " Search placeholder 0. - if neosnippet#_search_snippet_range(begin, end, 0) - let found = 1 - endif - finally - if found - stopinsert - endif - - call setpos('.', pos) - endtry -endfunction"}}} - let &cpo = s:save_cpo unlet s:save_cpo diff --git a/autoload/neosnippet/mappings.vim b/autoload/neosnippet/mappings.vim index 1df34bf..776cd17 100644 --- a/autoload/neosnippet/mappings.vim +++ b/autoload/neosnippet/mappings.vim @@ -94,12 +94,44 @@ function! neosnippet#mappings#_register_oneshot_snippet() "{{{ echo 'Registered trigger : ' . trigger endfunction"}}} +function! neosnippet#mappings#_expand_target() "{{{ + let trigger = input('Please input snippet trigger: ', + \ '', 'customlist,neosnippet#commands#_complete_target_snippets') + let neosnippet = neosnippet#variables#current_neosnippet() + if !has_key(neosnippet#helpers#get_snippets(), trigger) || + \ neosnippet#helpers#get_snippets()[trigger].snip !~# + \ neosnippet#get_placeholder_target_marker_pattern() + if trigger != '' + echo 'The trigger is invalid.' + endif + + let neosnippet.target = '' + return + endif + + call neosnippet#mappings#_expand_target_trigger(trigger) +endfunction"}}} +function! neosnippet#mappings#_expand_target_trigger(trigger) "{{{ + let neosnippet = neosnippet#variables#current_neosnippet() + let neosnippet.target = substitute( + \ neosnippet#helpers#get_selected_text(visualmode(), 1), '\n$', '', '') + + let line = getpos("'<")[1] + let col = getpos("'<")[2] + + call neosnippet#helpers#delete_selected_text(visualmode()) + + call cursor(line, col) + + call neosnippet#view#_expand(neosnippet#util#get_cur_text(), col, a:trigger) +endfunction"}}} + function! s:snippets_expand(cur_text, col) "{{{ let cur_word = neosnippet#helpers#get_cursor_snippet( \ neosnippet#helpers#get_snippets(), \ a:cur_text) - call neosnippet#expand( + call neosnippet#view#_expand( \ a:cur_text, a:col, cur_word) endfunction"}}} @@ -109,10 +141,10 @@ function! s:snippets_expand_or_jump(cur_text, col) "{{{ if cur_word != '' " Found snippet trigger. - call neosnippet#expand( + call neosnippet#view#_expand( \ a:cur_text, a:col, cur_word) else - call neosnippet#jump(a:cur_text, a:col) + call neosnippet#view#_jump(a:cur_text, a:col) endif endfunction"}}} @@ -122,9 +154,9 @@ function! s:snippets_jump_or_expand(cur_text, col) "{{{ if search(neosnippet#get_placeholder_marker_pattern(). '\|' \ .neosnippet#get_sync_placeholder_marker_pattern(), 'nw') > 0 " Found snippet placeholder. - call neosnippet#jump(a:cur_text, a:col) + call neosnippet#view#_jump(a:cur_text, a:col) else - call neosnippet#expand( + call neosnippet#view#_expand( \ a:cur_text, a:col, cur_word) endif endfunction"}}} diff --git a/autoload/neosnippet/view.vim b/autoload/neosnippet/view.vim new file mode 100644 index 0000000..2ae387b --- /dev/null +++ b/autoload/neosnippet/view.vim @@ -0,0 +1,545 @@ +"============================================================================= +" FILE: view.vim +" AUTHOR: Shougo Matsushita +" Last Modified: 21 Nov 2013. +" License: MIT license {{{ +" Permission is hereby granted, free of charge, to any person obtaining +" a copy of this software and associated documentation files (the +" "Software"), to deal in the Software without restriction, including +" without limitation the rights to use, copy, modify, merge, publish, +" distribute, sublicense, and/or sell copies of the Software, and to +" permit persons to whom the Software is furnished to do so, subject to +" the following conditions: +" +" The above copyright notice and this permission notice shall be included +" in all copies or substantial portions of the Software. +" +" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +" IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +" CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +" TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +" SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +" }}} +"============================================================================= + +let s:save_cpo = &cpo +set cpo&vim + +function! neosnippet#view#_expand(cur_text, col, trigger_name) "{{{ + call s:skip_next_auto_completion() + + let snippets = neosnippet#helpers#get_snippets() + + if a:trigger_name == '' || !has_key(snippets, a:trigger_name) + let pos = getpos('.') + let pos[2] = len(a:cur_text)+1 + call setpos('.', pos) + + if pos[2] < col('$') + startinsert + else + startinsert! + endif + + return + endif + + let snippet = snippets[a:trigger_name] + let cur_text = a:cur_text[: -1-len(a:trigger_name)] + + let snip_word = snippet.snip + if snip_word =~ '\\\@', 'g') + let snip_word = substitute(snip_word, + \ '\\\@', 'g') + let snip_word = substitute(snip_word, + \ '\\'.neosnippet#get_mirror_placeholder_marker_substitute_pattern().'\|'. + \ '\\'.neosnippet#get_placeholder_marker_substitute_pattern(), + \ '\=submatch(0)[1:]', 'g') + + " Insert snippets. + let next_line = getline('.')[a:col-1 :] + let snippet_lines = split(snip_word, '\n', 1) + if empty(snippet_lines) + return + endif + + let begin_line = line('.') + let end_line = line('.') + len(snippet_lines) - 1 + + let snippet_lines[0] = cur_text . snippet_lines[0] + let next_col = len(snippet_lines[-1]) + 1 + let snippet_lines[-1] = snippet_lines[-1] . next_line + + if has('folding') + " Note: Change foldmethod to "manual". Because, if you use foldmethod is + " expr, whole snippet is visually selected. + let foldmethod_save = &l:foldmethod + let &l:foldmethod = 'manual' + endif + + let expand_stack = neosnippet#variables#expand_stack() + + try + call setline('.', snippet_lines[0]) + if len(snippet_lines) > 1 + call append('.', snippet_lines[1:]) + endif + + if begin_line != end_line || snippet.options.indent + call s:indent_snippet(begin_line, end_line) + endif + + let begin_patterns = (begin_line > 1) ? + \ [getline(begin_line - 1)] : [] + let end_patterns = (end_line < line('$')) ? + \ [getline(end_line + 1)] : [] + call add(expand_stack, { + \ 'begin_line' : begin_line, + \ 'begin_patterns' : begin_patterns, + \ 'end_line' : end_line, + \ 'end_patterns' : end_patterns, + \ 'holder_cnt' : 1, + \ }) + + if snip_word =~ neosnippet#get_placeholder_marker_pattern() + call neosnippet#view#_jump(a:cur_text, a:col) + endif + finally + if has('folding') + if foldmethod_save !=# &l:foldmethod + let &l:foldmethod = foldmethod_save + endif + + silent! execute begin_line . ',' . end_line . 'foldopen!' + endif + endtry + + let &l:iminsert = 0 + let &l:imsearch = 0 +endfunction"}}} +function! neosnippet#view#_jump(cur_text, col) "{{{ + call s:skip_next_auto_completion() + + let expand_stack = neosnippet#variables#expand_stack() + + " Get patterns and count. + if empty(expand_stack) + return s:search_outof_range(a:col) + endif + + let expand_info = expand_stack[-1] + " Search patterns. + let [begin, end] = s:get_snippet_range( + \ expand_info.begin_line, + \ expand_info.begin_patterns, + \ expand_info.end_line, + \ expand_info.end_patterns) + if s:search_snippet_range(begin, end, expand_info.holder_cnt) + " Next count. + let expand_info.holder_cnt += 1 + return 1 + endif + + " Search placeholder 0. + if s:search_snippet_range(begin, end, 0) + return 1 + endif + + " Not found. + let expand_stack = neosnippet#variables#expand_stack() + let expand_stack = expand_stack[: -2] + + return s:search_outof_range(a:col) +endfunction"}}} + +function! neosnippet#view#_on_insert_leave() "{{{ + let expand_stack = neosnippet#variables#expand_stack() + + " Get patterns and count. + if empty(expand_stack) + \ || neosnippet#variables#current_neosnippet().trigger + return + endif + + let expand_info = expand_stack[-1] + + if expand_info.begin_line != expand_info.end_line + return + endif + + " Search patterns. + let [begin, end] = s:get_snippet_range( + \ expand_info.begin_line, + \ expand_info.begin_patterns, + \ expand_info.end_line, + \ expand_info.end_patterns) + + let pos = getpos('.') + + " Found snippet. + let found = 0 + try + while s:search_snippet_range(begin, end, expand_info.holder_cnt, 0) + " Next count. + let expand_info.holder_cnt += 1 + let found = 1 + endwhile + + " Search placeholder 0. + if s:search_snippet_range(begin, end, 0) + let found = 1 + endif + finally + if found + stopinsert + endif + + call setpos('.', pos) + endtry +endfunction"}}} + +function! s:indent_snippet(begin, end) "{{{ + if a:begin > a:end + return + endif + + let pos = getpos('.') + + let neosnippet = neosnippet#variables#current_neosnippet() + + let equalprg = &l:equalprg + try + setlocal equalprg= + + " Indent begin line? + let begin = (neosnippet.target == '') ? a:begin : a:begin + 1 + + let base_indent = matchstr(getline(a:begin), '^\s\+') + for line_nr in range(begin, a:end) + call cursor(line_nr, 0) + + if getline('.') =~ '^\t\+' + " Delete head tab character. + let current_line = substitute(getline('.'), '^\t', '', '') + + if &l:expandtab && current_line =~ '^\t\+' + " Expand tab. + cal setline('.', substitute(current_line, + \ '^\t\+', base_indent . repeat(' ', &shiftwidth * + \ len(matchstr(current_line, '^\t\+'))), '')) + elseif line_nr != a:begin + call setline('.', base_indent . current_line) + endif + else + silent normal! == + endif + endfor + finally + let &l:equalprg = equalprg + call setpos('.', pos) + endtry +endfunction"}}} + +function! s:get_snippet_range(begin_line, begin_patterns, end_line, end_patterns) "{{{ + let pos = getpos('.') + + call cursor(a:begin_line, 0) + if empty(a:begin_patterns) + let begin = line('.') - 50 + else + let [begin, _] = searchpos('^' . neosnippet#util#escape_pattern( + \ a:begin_patterns[0]) . '$', 'bnW') + if begin <= 0 + let begin = line('.') - 50 + endif + endif + if begin <= 0 + let begin = 1 + endif + + call cursor(a:end_line, 0) + if empty(a:end_patterns) + let end = line('.') + 50 + else + let [end, _] = searchpos('^' . neosnippet#util#escape_pattern( + \ a:end_patterns[0]) . '$', 'nW') + if end <= 0 + let end = line('.') + 50 + endif + endif + if end > line('$') + let end = line('$') + endif + + call setpos('.', pos) + return [begin, end] +endfunction"}}} +function! s:search_snippet_range(start, end, cnt, ...) "{{{ + let is_select = get(a:000, 0, 1) + call s:substitute_placeholder_marker(a:start, a:end, a:cnt) + + " Search marker pattern. + let pattern = substitute(neosnippet#get_placeholder_marker_pattern(), + \ '\\d\\+', a:cnt, '') + + for line in filter(range(a:start, a:end), + \ 'getline(v:val) =~ pattern') + call s:expand_placeholder(a:start, a:end, a:cnt, line, is_select) + return 1 + endfor + + return 0 +endfunction"}}} +function! s:search_outof_range(col) "{{{ + call s:substitute_placeholder_marker(1, 0, 0) + + let pattern = neosnippet#get_placeholder_marker_pattern() + if search(pattern, 'w') > 0 + call s:expand_placeholder(line('.'), 0, '\\d\\+', line('.')) + return 1 + endif + + let pos = getpos('.') + if a:col == 1 + let pos[2] = 1 + call setpos('.', pos) + startinsert + elseif a:col >= col('$') + startinsert! + else + let pos[2] = a:col+1 + call setpos('.', pos) + startinsert + endif + + " Not found. + return 0 +endfunction"}}} +function! s:expand_placeholder(start, end, holder_cnt, line, ...) "{{{ + let is_select = get(a:000, 0, 1) + + let pattern = substitute(neosnippet#get_placeholder_marker_pattern(), + \ '\\d\\+', a:holder_cnt, '') + let current_line = getline(a:line) + let match = match(current_line, pattern) + let neosnippet = neosnippet#variables#current_neosnippet() + + let default_pattern = substitute( + \ neosnippet#get_placeholder_marker_default_pattern(), + \ '\\d\\+', a:holder_cnt, '') + let default = substitute( + \ matchstr(current_line, default_pattern), + \ '\\\ze[^\\]', '', 'g') + + if default =~ '^TARGET\>' && neosnippet.target != '' + let default = '' + let is_target = 1 + else + let is_target = 0 + endif + + let default = substitute(default, '^TARGET:\?', '', '') + + let neosnippet.selected_text = default + + " Substitute marker. + let default = substitute(default, + \ neosnippet#get_placeholder_marker_substitute_pattern(), + \ '<`\1`>', 'g') + let default = substitute(default, + \ neosnippet#get_mirror_placeholder_marker_substitute_pattern(), + \ '<|\1|>', 'g') + + " len() cannot use for multibyte. + let default_len = len(substitute(default, '.', 'x', 'g')) + + let pos = getpos('.') + let pos[1] = a:line + let pos[2] = match+1 + + let cnt = s:search_sync_placeholder(a:start, a:end, a:holder_cnt) + if cnt >= 0 + let pattern = substitute(neosnippet#get_placeholder_marker_pattern(), + \ '\\d\\+', cnt, '') + call setline(a:line, substitute(current_line, pattern, + \ '<{'.cnt.':'.escape(default, '\').'}>', '')) + let pos[2] += len('<{'.cnt.':') + else + " Substitute holder. + call setline(a:line, + \ substitute(current_line, pattern, escape(default, '\'), '')) + endif + + call setpos('.', pos) + + if is_target + " Expand target + return s:expand_target_placeholder(a:line, match+1) + endif + + if default_len > 0 && is_select + " Select default value. + let len = default_len-1 + if &l:selection == 'exclusive' + let len += 1 + endif + + stopinsert + execute 'normal! v'. repeat('l', len) . "\" + elseif pos[2] < col('$') + startinsert + else + startinsert! + endif +endfunction"}}} +function! s:expand_target_placeholder(line, col) "{{{ + " Expand target + let neosnippet = neosnippet#variables#current_neosnippet() + let next_line = getline(a:line)[a:col-1 :] + let target_lines = split(neosnippet.target, '\n', 1) + + let cur_text = getline(a:line)[: a:col-2] + let target_lines[0] = cur_text . target_lines[0] + let next_col = len(target_lines[-1]) + 1 + let target_lines[-1] = target_lines[-1] . next_line + + let begin_line = a:line + let end_line = a:line + len(target_lines) - 1 + + let col = col('.') + try + let base_indent = matchstr(cur_text, '^\s\+') + call setline(a:line, target_lines[0]) + if len(target_lines) > 1 + call append(a:line, map(target_lines[1:], + \ 'base_indent . v:val')) + endif + + call cursor(end_line, 0) + + if next_line != '' + startinsert + let col = col('.') + else + startinsert! + let col = col('$') + endif + finally + if has('folding') + silent! execute begin_line . ',' . end_line . 'foldopen!' + endif + endtry + + let neosnippet.target = '' + + call neosnippet#view#_jump(neosnippet#util#get_cur_text(), col) +endfunction"}}} +function! s:search_sync_placeholder(start, end, number) "{{{ + if a:end == 0 + " Search in current buffer. + let cnt = matchstr(getline('.'), + \ substitute(neosnippet#get_placeholder_marker_pattern(), + \ '\\d\\+', '\\zs\\d\\+\\ze', '')) + return search(substitute( + \ neosnippet#get_mirror_placeholder_marker_pattern(), + \ '\\d\\+', cnt, ''), 'nw') > 0 ? cnt : -1 + endif + + let pattern = substitute( + \ neosnippet#get_mirror_placeholder_marker_pattern(), + \ '\\d\\+', a:number, '') + for line in filter(range(a:start, a:end), + \ 'getline(v:val) =~ pattern') + return a:number + endfor + + return -1 +endfunction"}}} +function! s:substitute_placeholder_marker(start, end, snippet_holder_cnt) "{{{ + if a:snippet_holder_cnt > 0 + let cnt = a:snippet_holder_cnt-1 + let sync_marker = substitute(neosnippet#get_sync_placeholder_marker_pattern(), + \ '\\d\\+', cnt, '') + let mirror_marker = substitute( + \ neosnippet#get_mirror_placeholder_marker_pattern(), + \ '\\d\\+', cnt, '') + let line = a:start + + for line in range(a:start, a:end) + if getline(line) =~ sync_marker + let sub = escape(matchstr(getline(line), + \ substitute(neosnippet#get_sync_placeholder_marker_default_pattern(), + \ '\\d\\+', cnt, '')), '/\') + silent execute printf('%d,%ds/\m' . mirror_marker . '/%s/' + \ . (&gdefault ? '' : 'g'), a:start, a:end, sub) + call setline(line, substitute(getline(line), sync_marker, sub, '')) + endif + endfor + elseif search(neosnippet#get_sync_placeholder_marker_pattern(), 'wb') > 0 + let sub = escape(matchstr(getline('.'), + \ neosnippet#get_sync_placeholder_marker_default_pattern()), '/\') + let cnt = matchstr(getline('.'), + \ substitute(neosnippet#get_sync_placeholder_marker_pattern(), + \ '\\d\\+', '\\zs\\d\\+\\ze', '')) + let mirror_marker = substitute( + \ neosnippet#get_mirror_placeholder_marker_pattern(), + \ '\\d\\+', cnt, '') + silent execute printf('%%s/\m' . mirror_marker . '/%s/' + \ . (&gdefault ? 'g' : ''), sub) + let sync_marker = substitute(neosnippet#get_sync_placeholder_marker_pattern(), + \ '\\d\\+', cnt, '') + call setline('.', substitute(getline('.'), sync_marker, sub, '')) + endif +endfunction"}}} +function! s:eval_snippet(snippet_text) "{{{ + let snip_word = '' + let prev_match = 0 + let match = match(a:snippet_text, '\\\@= 0 + if match - prev_match > 0 + let snip_word .= a:snippet_text[prev_match : match - 1] + endif + let prev_match = matchend(a:snippet_text, + \ '\\\@= 0 + let snip_word .= a:snippet_text[prev_match :] + endif + + return snip_word +endfunction"}}} +function! s:skip_next_auto_completion() "{{{ + " Skip next auto completion. + if exists('*neocomplcache#skip_next_complete') + call neocomplcache#skip_next_complete() + endif + if exists('*neocomplete#skip_next_complete') + call neocomplete#skip_next_complete() + endif + + let neosnippet = neosnippet#variables#current_neosnippet() + let neosnippet.trigger = 0 +endfunction"}}} + +let &cpo = s:save_cpo +unlet s:save_cpo + +" vim: foldmethod=marker diff --git a/autoload/unite/sources/snippet.vim b/autoload/unite/sources/snippet.vim index 0dedf3d..7ed92a5 100644 --- a/autoload/unite/sources/snippet.vim +++ b/autoload/unite/sources/snippet.vim @@ -87,7 +87,7 @@ function! s:action_table.expand.func(candidate) "{{{ let cur_text = neosnippet#util#get_cur_text() let cur_keyword_str = matchstr(cur_text, '\S\+$') let context = unite#get_context() - call neosnippet#expand( + call neosnippet#view#_expand( \ cur_text . a:candidate.action__complete_word[len(cur_keyword_str)], \ context.col, a:candidate.action__complete_word) endfunction"}}} diff --git a/autoload/unite/sources/snippet_target.vim b/autoload/unite/sources/snippet_target.vim index acc3e72..b5addbe 100644 --- a/autoload/unite/sources/snippet_target.vim +++ b/autoload/unite/sources/snippet_target.vim @@ -82,7 +82,7 @@ function! s:source.action_table.select.func(candidate) "{{{ return endif - call neosnippet#expand_target_trigger(a:candidate.source__trigger) + call neosnippet#mappings#_expand_target_trigger(a:candidate.source__trigger) endfunction"}}} "}}} diff --git a/plugin/neosnippet.vim b/plugin/neosnippet.vim index ba28917..7475cb3 100644 --- a/plugin/neosnippet.vim +++ b/plugin/neosnippet.vim @@ -59,7 +59,7 @@ xnoremap (neosnippet_get_selected_text) \ :call neosnippet#helpers#get_selected_text(visualmode(), 1) xnoremap (neosnippet_expand_target) - \ :call neosnippet#expand_target() + \ :call neosnippet#mappings#_expand_target() xnoremap (neosnippet_start_unite_snippet_target) \ unite#sources#snippet_target#start() xnoremap (neosnippet_register_oneshot_snippet)