mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-24 06:20:05 +08:00
251 lines
7.7 KiB
VimL
Vendored
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={{{,}}}
|