1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-24 06:20:05 +08:00
SpaceVim/bundle/vim-unstack/autoload/unstack.vim
2022-10-27 15:44:42 +08:00

251 lines
7.7 KiB
VimL
Vendored

"Initialization: {{{
if !exists("s:unstack_signs")
let s:unstack_signs = {}
endif
"When the user switches tabs, check if it's due to an unstack tab being closed.
"If so, remove signs from the stack trace that was in that tab.
augroup unstack_sign_clear
autocmd!
autocmd TabEnter * call unstack#RemoveSignsFromClosedTabs()
augroup end
"}}}
"unstack#Unstack(selection_type) called by hotkeys {{{
function! unstack#Unstack(selection_type) abort
let stack = unstack#ExtractFiles(a:selection_type)
if len(stack) > 0
if g:unstack_populate_quickfix
call unstack#PopulateQuickfix(stack)
endif
if g:unstack_open_tab
call unstack#OpenStackTrace(stack)
endif
else
echohl Error
echo "No stack trace found!"
echohl None
endif
endfunction
"}}}
"unstack#UnstackFromText(text) call unstack with text as input {{{
function! unstack#UnstackFromText(text) abort
let stack = unstack#ExtractFilesFromText(a:text)
if len(stack) > 0
if g:unstack_populate_quickfix
call unstack#PopulateQuickfix(stack)
endif
if g:unstack_open_tab
call unstack#OpenStackTrace(stack)
endif
else
echohl WarningMsg
echo "No stack trace found!"
echohl None
endif
endfunction
"}}}
"unstack#UnstackFromTmuxPasteBuffer() use tmux paste buffer as input for unstack {{{
function! unstack#UnstackFromTmuxPasteBuffer()
if executable('tmux') && $TMUX != ''
let text = system('tmux show-buffer')
call unstack#UnstackFromText(l:text)
else
echoerr "No tmux session is running!"
endif
endfunction
"}}}
"Extraction:
"unstack#ExtractFiles(selection_type) extract files and line numbers {{{
function! unstack#ExtractFiles(selection_type)
if &buftype == "quickfix"
let fileList = unstack#ExtractFilesFromQuickfix(a:selection_type)
else
let text = unstack#GetSelectedText(a:selection_type)
let fileList = unstack#ExtractFilesFromText(text)
endif
return fileList
endfunction
"}}}
"unstack#ExtractFilesFromQuickfix(type) extract files from selected text or normal cmd range {{{
function! unstack#ExtractFilesFromQuickfix(type)
if a:type ==# "v" || a:type ==# "V"
let marks = ["'<", "'>"]
else
let marks = ["'[", "']"]
endif
let start_line = line(marks[0]) - 1 "lines are 0-indexed in quickfix list
let stop_line = line(marks[1]) - 1 "lines are 0-indexed in quickfix list
let file_list = []
while start_line <= stop_line
let qfline = getqflist()[start_line]
let fname = bufname(qfline["bufnr"])
let lineno = qfline["lnum"]
call add(file_list, [fname, lineno])
let start_line = start_line + 1
endwhile
return file_list
endfunction
"}}}
"unstack#GetSelectedText(selection_type) extract selected text {{{
function! unstack#GetSelectedText(selection_type)
"save these values because we have to change them
let sel_save = &selection
let reg_save = @@
let &selection = "inclusive"
"yank the text
if a:selection_type ==# 'V'
execute "normal! `<V`>y"
elseif a:selection_type ==# 'v'
execute "normal! `<v`>y"
elseif a:selection_type ==# 'char'
execute "normal! `[v`]y"
elseif a:selection_type ==# 'line'
execute "normal! `[V`]y"
else
"unknown selection type; reset vars and return ""
let &selection = sel_save
let @@ = reg_save
return ""
endif
"get the text we just yanked
let selected_text = @@
"reset vars
let &selection = sel_save
let @@ = reg_save
"return the text
return selected_text
endfunction
"}}}
"unstack#ExtractFilesFromText(stacktrace) extract files and lines from a stacktrace {{{
"return [[file1, line1], [file2, line2] ... ] from a stacktrace
"tries each extractor in order and stops when an extractor returns a non-empty
"stack
function! unstack#ExtractFilesFromText(text)
for extractor in g:unstack_extractors
let stack = extractor.extract(a:text)
if(!empty(stack))
return stack
endif
endfor
return []
endfunction
"}}}
"Opening:
"unstack#PopulateQuickfix(stack) set quickfix list to extracted files{{{
function! unstack#PopulateQuickfix(stack)
let qflist = []
for [filepath, lineno] in a:stack
call add(qflist, {"filename": filepath, "lnum": lineno})
endfor
call setqflist(qflist)
endfunction
"}}}
"unstack#OpenStackTrace(files) open extracted files in new tab {{{
"files: [[file1, line1], [file2, line2] ... ] from a stacktrace
function! unstack#OpenStackTrace(files)
"disable redraw when opening files
"still redraws when a split occurs but might *slightly* improve performance
let lazyredrawSet = &lazyredraw
set lazyredraw
tabnew
if (g:unstack_showsigns)
sign define errline text=>> linehl=Error texthl=Error
"sign ID's should be unique. If you open a stack trace with 5 levels,
"you'd have to wait 5 seconds before opening another or risk signs
"colliding.
let signId = localtime()
let t:unstack_tabId = signId
let s:unstack_signs[t:unstack_tabId] = []
endif
if g:unstack_scrolloff
let old_scrolloff = &scrolloff
let &scrolloff = g:unstack_scrolloff
endif
for [filepath, lineno] in a:files
if filereadable(filepath) || (match(filepath, "://") > -1)
execute "edit" filepath
call unstack#MoveToLine(lineno)
if (g:unstack_showsigns)
execute "sign place" signId "line=".lineno "name=errline" "buffer=".bufnr('%')
"store the signs so they can be removed later
call add(s:unstack_signs[t:unstack_tabId], signId)
let signId += 1
endif
call unstack#SplitWindow()
endif
endfor
"after adding the last file, the loop splits again.
"delete this last empty vertical split
quit
if (!lazyredrawSet)
set nolazyredraw
endif
if g:unstack_scrolloff
let &scrolloff = old_scrolloff
endif
endfunction
"}}}
"unstack#GetOpenTabIds() get unstack id's for current tabs {{{
function! unstack#GetOpenTabIds()
let curTab = tabpagenr()
"determine currently open tabs
let open_tab_ids = []
tabdo if exists('t:unstack_tabId') | call add(open_tab_ids, string(t:unstack_tabId)) | endif
"jump back to prev. tab
execute "tabnext" curTab
return open_tab_ids
endfunction
"}}}
"unstack#RemoveSigns(tabId) remove signs from the files initially opened in a tab {{{
function! unstack#RemoveSigns(tabId)
for sign_id in s:unstack_signs[a:tabId]
execute "sign unplace" sign_id
endfor
unlet s:unstack_signs[a:tabId]
endfunction
"}}}
"unstack#RemoveSignsFromClosedTabs() remove signs that were placed in tabs that are {{{
"now closed
function! unstack#RemoveSignsFromClosedTabs()
let openTabIds = unstack#GetOpenTabIds()
"for each tab with signs
for tabId in keys(s:unstack_signs)
"if this tab no longer exists, remove the signs
if index(openTabIds, tabId) == -1
call unstack#RemoveSigns(tabId)
endif
endfor
endfunction
"}}}
"unstack#GetLayout() returns layout setting ("portrait"/"landscape") {{{
function! unstack#GetLayout()
let layout = get(g:, "unstack_layout", "landscape")
if layout == "landscape" || layout == "portrait"
return layout
else
throw "g:unstack_layout must be portrait or landscape"
endif
endfunction
"}}}
"unstack#MoveToLine move cursor to the line and put it in the right part of the screen {{{
let s:movement_cmd = {}
let s:movement_cmd["top"] = "z+"
let s:movement_cmd["middle"] = "z."
let s:movement_cmd["bottom"] = "z-"
function! unstack#MoveToLine(lineno)
execute "normal!" a:lineno . s:movement_cmd[g:unstack_vertical_alignment]
endfunction
"}}}
"unstack#SplitWindow() split window horizontally/vertically based on layout{{{
function! unstack#SplitWindow()
let layout = unstack#GetLayout()
if layout == "landscape"
let split_cmd = "vnew"
else
let split_cmd = "new"
endif
execute "botright" split_cmd
endfunction
"}}}
" vim: et sw=2 sts=2 foldmethod=marker foldmarker={{{,}}}