"=============================================================================
" FILE: jump_list.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" 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
" Variables "{{{
if !exists('g:unite_kind_jump_list_after_jump_scroll')
let g:unite_kind_jump_list_after_jump_scroll = 25
else
let g:unite_kind_jump_list_after_jump_scroll =
\ min([max([0, g:unite_kind_jump_list_after_jump_scroll]), 100])
endif
"}}}
function! unite#kinds#jump_list#define() abort "{{{
let kind = {
\ 'name' : 'jump_list',
\ 'default_action' : 'open',
\ 'action_table': {},
\ 'alias_table' : { 'rename' : 'replace' },
\ 'parents': ['common', 'openable'],
\}
" Actions "{{{
let kind.action_table.open = {
\ 'description' : 'jump to this position',
\ 'is_selectable' : 1,
\ }
function! kind.action_table.open.func(candidates) abort "{{{
for candidate in a:candidates
" Save current line in jump_list
execute 'normal!' line('.').'G'
if s:convert_path(bufname('%')) !=#
\ s:convert_path(s:get_filename(candidate))
let bufnr = s:open(candidate)
call unite#remove_previewed_buffer_list(bufnr)
endif
call s:jump(candidate, 0)
" Open folds.
normal! zv
call s:adjust_scroll(s:best_winline())
call unite#view#_clear_match_highlight()
endfor
" Add search history
let context = unite#get_context()
if has_key(context, 'input_list')
\ && len(context.input_list) == 1
\ && context.input != ''
call histadd("search", context.input)
endif
endfunction"}}}
let kind.action_table.preview = {
\ 'description' : 'preview this position',
\ 'is_quit' : 0,
\ }
function! kind.action_table.preview.func(candidate) abort "{{{
let filename = s:get_filename(a:candidate)
let bufwinnr = bufwinnr(filename)
let buflisted = buflisted(filename)
let preview_windows = filter(range(1, winnr('$')),
\ 'getwinvar(v:val, "&previewwindow") != 0')
if empty(preview_windows)
call unite#view#_preview_file(filename)
endif
let winnr = winnr()
wincmd P
try
let bufnr = s:open(a:candidate)
if bufwinnr < 0 && !buflisted
call unite#add_previewed_buffer_list(bufnr)
endif
call s:jump(a:candidate, 1)
finally
execute winnr.'wincmd w'
endtry
endfunction"}}}
let kind.action_table.highlight = {
\ 'description' : 'highlight this position',
\ 'is_quit' : 0,
\ }
function! kind.action_table.highlight.func(candidate) abort "{{{
let candidate_winnr = bufwinnr(s:get_bufnr(a:candidate))
if candidate_winnr > 0
let unite = unite#get_current_unite()
let current_winnr = winnr()
noautocmd execute candidate_winnr 'wincmd w'
call s:jump(a:candidate, 1)
let unite_winnr = bufwinnr(unite.bufnr)
if unite_winnr < 0
let unite_winnr = current_winnr
endif
if unite_winnr > 0
noautocmd execute unite_winnr 'wincmd w'
endif
endif
endfunction"}}}
let kind.action_table.replace = {
\ 'description' : 'replace with qfreplace',
\ 'is_selectable' : 1,
\ }
function! kind.action_table.replace.func(candidates) abort "{{{
if globpath(&runtimepath, 'autoload/qfreplace.vim') == ''
echo 'qfreplace.vim is not installed.'
return
endif
let qflist = []
for candidate in a:candidates
if has_key(candidate, 'action__line')
\ && has_key(candidate, 'action__text')
let filename = s:get_filename(candidate)
call add(qflist, {
\ 'filename' : filename,
\ 'lnum' : candidate.action__line,
\ 'text' : candidate.action__text,
\ })
endif
endfor
if !empty(qflist)
call setqflist(qflist)
call qfreplace#start('')
endif
endfunction"}}}
return kind
endfunction"}}}
"}}}
" Misc.
function! s:jump(candidate, is_highlight) abort "{{{
let line = get(a:candidate, 'action__line', 1)
let pattern = get(a:candidate, 'action__pattern', '')
if line == ''
" Use default line number.
let line = 1
endif
if line !~ '^\d\+$'
call unite#print_error('jump_list: Invalid action__line format.')
return
endif
if !has_key(a:candidate, 'action__pattern')
" Jump to the line number.
let col = get(a:candidate, 'action__col', 0)
if col == 0 && has_key(a:candidate, 'action__col_pattern')
" Search col pattern.
let pattern = a:candidate.action__col_pattern
if pattern == ''
" Use context.input
let pattern = unite#get_context().input
endif
let col = 0
silent! let col = match(getline(line), pattern) + 1
endif
call cursor(line, col)
call s:open_current_line(a:is_highlight)
return
endif
" Jump by search().
let source = unite#get_sources(a:candidate.source)
if !(has_key(a:candidate, 'action__signature')
\ && has_key(source, 'calc_signature'))
" Not found signature.
if line != '' && getline(line) =~# pattern
if line('.') != line
execute line
endif
else
silent! call search(pattern, 'w')
endif
call s:open_current_line(a:is_highlight)
return
endif
silent! call search(pattern, 'w')
let lnum_prev = line('.')
silent! call search(pattern, 'w')
let lnum = line('.')
if lnum != lnum_prev
" Detected same pattern lines!!
let start_lnum = lnum
while source.calc_signature(lnum) !=#
\ a:candidate.action__signature
silent! call search(pattern, 'w')
let lnum = line('.')
if lnum == start_lnum
" Not found.
call unite#print_error(
\ 'jump_list: Target position is not found.')
call cursor(1, 1)
return
endif
endwhile
endif
call s:open_current_line(a:is_highlight)
endfunction"}}}
function! s:best_winline() abort "{{{
return max([1, winheight(0) * g:unite_kind_jump_list_after_jump_scroll / 100])
endfunction"}}}
function! s:adjust_scroll(best_winline) abort "{{{
normal! zt
let save_cursor = getpos('.')
let winl = 1
" Scroll the cursor line down.
while winl <= a:best_winline
let winl_prev = winl
execute "normal! \<C-y>"
let winl = winline()
if winl == winl_prev
break
end
let winl_prev = winl
endwhile
if winl > a:best_winline
execute "normal! \<C-e>"
endif
call setpos('.', save_cursor)
endfunction"}}}
function! s:open_current_line(is_highlight) abort "{{{
normal! zv
normal! zz
if a:is_highlight
call unite#view#_clear_match_highlight()
call unite#view#_match_line('Search', line('.'), 10)
endif
endfunction"}}}
function! s:open(candidate) abort "{{{
let bufnr = s:get_bufnr(a:candidate)
if bufnr != bufnr('%')
if has_key(a:candidate, 'action__buffer_nr')
silent execute 'keepjumps buffer' bufnr
else
silent call unite#util#smart_execute_command(
\ 'keepjumps edit!', unite#util#expand(
\ fnamemodify(a:candidate.action__path, ':~:.')))
let bufnr = bufnr('%')
endif
endif
return bufnr
endfunction"}}}
function! s:get_filename(candidate) abort "{{{
return has_key(a:candidate, 'action__path') ?
\ a:candidate.action__path :
\ bufname(a:candidate.action__buffer_nr)
endfunction"}}}
function! s:get_bufnr(candidate) abort "{{{
return has_key(a:candidate, 'action__buffer_nr') ?
\ a:candidate.action__buffer_nr :
\ bufnr(a:candidate.action__path)
endfunction"}}}
function! s:convert_path(path) abort "{{{
return unite#util#substitute_path_separator(fnamemodify(a:path, ':p'))
endfunction"}}}
let &cpo = s:save_cpo
unlet s:save_cpo
" vim: foldmethod=marker