Skip to content

Instantly share code, notes, and snippets.

@niha
Created July 24, 2010 10:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niha/488591 to your computer and use it in GitHub Desktop.
Save niha/488591 to your computer and use it in GitHub Desktop.
let w:gx_history_list = [{}]
let w:gx_history_current_index = 0
let w:gx_original_qflist = {}
function! s:GetCurrentQFIndex()
let qflist = getqflist()
if empty(qflist)
return -1
endif
let win_num = winnr()
wincmd b
if win_num == winnr() " not displayed
return -1
endif
let ret = line('.')
execute win_num ':wincmd w'
return ret
endfunction
function! s:GetNearestQFIndex()
let qflist = getqflist()
if empty(qflist)
return
endif
let line = line('.')
let buf_num = bufnr('%')
let next = -1
let index = 0
for elem in qflist
if buf_num != elem['bufnr']
let index += 1
continue
endif
if next == -1
let next = index
endif
if line >= elem['lnum']
if qflist[next]['lnum'] >= line || qflist[next]['lnum'] < elem['lnum']
let next = index
endif
else
if qflist[next]['lnum'] >= line && qflist[next]['lnum'] > elem['lnum']
let next = index
endif
endif
let index += 1
endfor
return next != -1 ? next + 1 : 1
endfunction
function! s:ResizeQFWindow()
let qflist = getqflist()
if empty(qflist)
return
endif
let height = min([len(qflist), 2 + &lines / 5])
let win_num = winnr()
wincmd b
if win_num == winnr()
return
endif
execute ":resize " . height
execute win_num ":wincmd w"
endfunction
function! s:CreateHistory()
let ret = {}
let ret['pos'] = getpos('.')
let ret['bufnr'] = bufnr('%')
let ret['qflist'] = getqflist()
let ret['qfindex'] = s:GetCurrentQFIndex()
return ret
endfunction
function! s:SaveCurrentHistory()
let w:gx_history_list[w:gx_history_current_index] = s:CreateHistory()
endfunction
function! s:CutOldHistory()
if len(w:gx_history_list) > w:gx_history_current_index + 1
call remove(w:gx_history_list, w:gx_history_current_index + 1, -1)
endif
endfunction
function! s:UpdateHistoryAtJump()
if len(w:gx_history_list) > w:gx_history_current_index + 1
call remove(w:gx_history_list, w:gx_history_current_index + 1, -1)
endif
call add(w:gx_history_list, {})
let w:gx_history_current_index += 1
endfunction
function! s:SetQFListAtCenter()
let win_num = winnr()
wincmd b
if win_num == winnr() " not displayed
return
endif
let height = winheight(0)
let size = len(getqflist())
let index = line('.')
if height == size
execute "normal 1zt"
else
if index <= size - (height + 1) / 2
execute "normal zz"
else
let before = line('.')
execute "normal" (size - (height + 1) / 2 + 1) . "zz"
let after = line('.')
if before > after
execute "normal" (before - after) . "j"
endif
endif
endif
execute win_num ':wincmd w'
endfunction
function! s:SetMainWindowAtCenter(prev_top_pos)
let current_pos = getpos('.')
if a:prev_top_pos[0] == current_pos[0]
" 表示上の行じゃないのでたまにおかしくなる
if a:prev_top_pos[1] < current_pos[1] && current_pos[1] < a:prev_top_pos[1] + winheight(0) - 1
return
endif
endif
normal ":zz"
endfunction
function! s:TruncateQFList(list)
let width = winwidth(0)
let i = 0
while i < len(a:list)
let rest = width - 3 - len(a:list[i]['lnum']) - len(bufname(a:list[i]['bufnr']))
if rest < 0
let rest = 0
endif
let a:list[i]['text'] = substitute(a:list[i]['text'], "^\\s\\+", "", "")
let a:list[i]['text'] = substitute(a:list[i]['text'], "\t", repeat(" ", &tabstop), "g")
let a:list[i]['text'] = matchstr(a:list[i]['text'], "^.*\\%<" . (rest+2) . "v")
let i += 1
endwhile
endfunction
function! s:CompateTag(lhs, rhs)
if a:lhs['bufnr'] == a:rhs['bufnr']
return a:lhs['lnum'] == a:rhs['lnum'] ? 0 : a:lhs['lnum'] > a:rhs['lnum'] ? 1 : -1
else
return a:lhs['bufnr'] > a:rhs['bufnr'] ? 1 : -1
endif
endfunction
function! s:GtagsEx(arg)
if &lines < 4
return
endif
call s:SaveCurrentHistory()
let bufnr = bufnr('%')
let pos = getpos('.')
let top_pos = getpos('w0')
call setqflist([])
execute 'Gtags ' . a:arg
let qflist = getqflist()
if empty(qflist)
cclose
return
endif
call sort(qflist, 's:CompateTag')
call s:TruncateQFList(qflist)
call setqflist(qflist, 'r')
call s:UpdateHistoryAtJump()
execute ":buffer" . bufnr
call setpos('.', pos)
execute ":crewind " . s:GetNearestQFIndex()
call s:ResizeQFWindow()
call s:SetQFListAtCenter()
call s:SetMainWindowAtCenter(top_pos)
endfunction
function! s:GtagsExFile()
if &lines < 4
return
endif
call s:SaveCurrentHistory()
let pos = getpos('.')
call setqflist([])
execute 'Gtags -f %'
let qflist = getqflist()
if empty(qflist)
cclose
return
endif
call sort(qflist, 's:CompateTag')
call s:TruncateQFList(qflist)
call setqflist(qflist, 'r')
call setpos('.', pos)
execute ":crewind " . s:GetNearestQFIndex()
call setpos('.', pos)
call s:ResizeQFWindow()
call s:SetQFListAtCenter()
endfunction
function! s:GtagsExToggle()
let win_count = winnr('$')
cclose
if win_count != winnr('$')
return
endif
if &lines < 4
return
endif
let qflist = getqflist()
if empty(qflist)
call s:GtagsExFile()
else
let pos = getpos('.')
let win_num = winnr()
call sort(qflist, 's:CompateTag')
call s:TruncateQFList(qflist)
call setqflist(qflist)
copen
execute win_num ":wincmd w"
call setpos('.', pos)
execute ":crewind" . s:GetNearestQFIndex()
call setpos('.', pos)
call s:ResizeQFWindow()
call s:SetQFListAtCenter()
end
endfunction
function! s:GtagsExCursor()
if &lines < 4
return
endif
call s:SaveCurrentHistory()
let bufnr = bufnr('%')
let pos = getpos('.')
let top_pos = getpos('w0')
call setqflist([])
GtagsCursor
let qflist = getqflist()
if empty(qflist)
cclose
return
endif
call sort(qflist , 's:CompateTag')
call s:TruncateQFList(qflist)
call setqflist(qflist, 'r')
call s:UpdateHistoryAtJump()
execute ":buffer" . bufnr
call setpos('.', pos)
execute ":crewind " . s:GetNearestQFIndex()
call s:ResizeQFWindow()
call s:SetQFListAtCenter()
call s:SetMainWindowAtCenter(top_pos)
endfunction
function! s:JumpHistory(index)
if len(w:gx_history_list) <= a:index
return 0
endif
let history = w:gx_history_list[a:index]
if empty(history) || empty(history['pos']) || history['bufnr'] == 0
return 0
endif
call s:SaveCurrentHistory()
let top_pos = getpos('w0')
call setqflist(history['qflist'])
copen
if !empty(history['qflist']) && history['qfindex'] != -1
execute ':crewind ' . history['qfindex']
call s:ResizeQFWindow()
call s:SetQFListAtCenter()
else
cclose
endif
execute ':buffer ' . history['bufnr']
call setpos('.', history['pos'])
call s:SetMainWindowAtCenter(top_pos)
return 1
endfunction
function! s:GtagsExHistoryNext()
if len(w:gx_history_list) <= w:gx_history_current_index + 1
return
endif
if s:JumpHistory(w:gx_history_current_index + 1)
let w:gx_history_current_index += 1
endif
endfunction
function! s:GtagsExHistoryPrev()
if w:gx_history_current_index - 1 <= -1
return
endif
if s:JumpHistory(w:gx_history_current_index - 1)
let w:gx_history_current_index -= 1
endif
endfunction
function! s:GtagsExListNext()
let qflist = getqflist()
if empty(qflist)
return
endif
let next = -1
let line = line('.')
let buf_num = bufnr('%')
let index = 0
for elem in qflist
if buf_num != elem['bufnr']
let index += 1
continue
endif
if next == -1
let next = index
endif
if line < elem['lnum']
if qflist[next]['lnum'] <= line || qflist[next]['lnum'] > elem['lnum']
let next = index
endif
else
if qflist[next]['lnum'] <= line && qflist[next]['lnum'] < elem['lnum']
let next = index
endif
endif
let index += 1
endfor
if next == -1
let top_pos = getpos('w0')
execute ':crewind 1'
call s:SetMainWindowAtCenter(top_pos)
return
endif
if qflist[next]['lnum'] <= line
let next += 1
endif
if next < len(qflist)
let top_pos = getpos('w0')
execute ':crewind' . (next + 1)
call s:SetQFListAtCenter()
call s:SetMainWindowAtCenter(top_pos)
endif
endfunction
function! s:GtagsExListPrev()
let qflist = getqflist()
if empty(qflist)
return
endif
let next = -1
let line = line('.')
let buf_num = bufnr('%')
let index = 0
for elem in qflist
if buf_num != elem['bufnr']
let index += 1
continue
endif
if next == -1
let next = index
endif
if line > elem['lnum']
if qflist[next]['lnum'] >= line || qflist[next]['lnum'] < elem['lnum']
let next = index
endif
else
if qflist[next]['lnum'] >= line && qflist[next]['lnum'] > elem['lnum']
let next = index
endif
endif
let index += 1
endfor
if next == -1
let top_pos = getpos('w0')
execute ':crewind 1'
call s:SetMainWindowAtCenter(top_pos)
return
endif
if line <= qflist[next]['lnum']
let next -= 1
endif
if -1 < next
let top_pos = getpos('w0')
execute ':crewind' . (next + 1)
call s:SetQFListAtCenter()
call s:SetMainWindowAtCenter(top_pos)
endif
endfunction
command! -nargs=* -complete=custom,Candidate GtagsEx call s:GtagsEx(<q-args>)
command! -nargs=0 GtagsExToggle call s:GtagsExToggle()
command! -nargs=0 GtagsExFile call s:GtagsExFile()
command! -nargs=0 GtagsExCursor call s:GtagsExCursor()
command! -nargs=0 GtagsExHistoryNext call s:GtagsExHistoryNext()
command! -nargs=0 GtagsExHistoryPrev call s:GtagsExHistoryPrev()
command! -nargs=0 GtagsExListNext call s:GtagsExListNext()
command! -nargs=0 GtagsExListPrev call s:GtagsExListPrev()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment