mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-04-14 07:09:11 +08:00
feat(unstack): include vim-unstack
This commit is contained in:
parent
972787e537
commit
591f725e18
@ -14,17 +14,18 @@ let s:CMP = SpaceVim#api#import('vim#compatible')
|
||||
|
||||
function! SpaceVim#layers#tools#plugins() abort
|
||||
let plugins = []
|
||||
call add(plugins, ['tpope/vim-scriptease', { 'merged' : 0}])
|
||||
call add(plugins, ['lymslive/vimloo', { 'merged' : 0}])
|
||||
call add(plugins, ['lymslive/vnote', { 'merged' : 0}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/rainbow', { 'merged' : 0}])
|
||||
call add(plugins, ['mbbill/fencview', { 'on_cmd' : 'FencAutoDetect'}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/vim-cheat', { 'on_cmd' : 'Cheat'}])
|
||||
call add(plugins, ['wsdjeg/Mysql.vim', { 'on_cmd' : 'SQLGetConnection'}])
|
||||
call add(plugins, ['wsdjeg/SourceCounter.vim', { 'on_cmd' : 'SourceCounter'}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/calendar.vim', { 'on_cmd' : 'Calendar'}])
|
||||
call add(plugins, ['junegunn/limelight.vim', { 'on_cmd' : 'Limelight'}])
|
||||
call add(plugins, ['junegunn/goyo.vim', { 'on_cmd' : 'Goyo', 'loadconf' : 1}])
|
||||
call add(plugins, ['tpope/vim-scriptease', { 'merged' : 0}])
|
||||
call add(plugins, ['lymslive/vimloo', { 'merged' : 0}])
|
||||
call add(plugins, ['lymslive/vnote', { 'merged' : 0}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/rainbow', { 'merged' : 0}])
|
||||
call add(plugins, ['mbbill/fencview', { 'on_cmd' : 'FencAutoDetect'}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/vim-cheat', { 'on_cmd' : 'Cheat'}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/vim-unstack', { 'merged' : 0}])
|
||||
call add(plugins, ['wsdjeg/Mysql.vim', { 'on_cmd' : 'SQLGetConnection'}])
|
||||
call add(plugins, ['wsdjeg/SourceCounter.vim', { 'on_cmd' : 'SourceCounter'}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/calendar.vim',{ 'on_cmd' : 'Calendar'}])
|
||||
call add(plugins, ['junegunn/limelight.vim', { 'on_cmd' : 'Limelight'}])
|
||||
call add(plugins, ['junegunn/goyo.vim', { 'on_cmd' : 'Goyo', 'loadconf' : 1}])
|
||||
call add(plugins, [g:_spacevim_root_dir . 'bundle/vim-bookmarks',
|
||||
\ {'merged': 0,
|
||||
\ 'loadconf_before' : 1}])
|
||||
|
1
bundle/README.md
vendored
1
bundle/README.md
vendored
@ -30,6 +30,7 @@ This plugins are changed based on a specific version of origin plugin.
|
||||
- `verilog`: based on [`vhda/verilog_systemverilog.vim@0b88f2c`](https://github.com/vhda/verilog_systemverilog.vim/tree/0b88f2ccf81983944bf00d15ec810dd807053d19)
|
||||
- `rainbow`: based on [`luochen1990/rainbow@c18071e5`](https://github.com/luochen1990/rainbow/tree/c18071e5c7790928b763c2e88c487dfc93d84a15)
|
||||
- `jedi-vim`: based on [`jedi-vim@e82d07`](https://github.com/davidhalter/jedi-vim/tree/e82d07faa17c3b3fe04b4fa6ab074e8e8601a596)
|
||||
- `vim-unstack`: based on [`vim-unstack@9b191419`](https://github.com/mattboehm/vim-unstack/tree/9b191419b4d3f26225a5ae3df5e409c62b426941)
|
||||
|
||||
### No changed plugins
|
||||
|
||||
|
1
bundle/vim-unstack/.gitignore
vendored
Normal file
1
bundle/vim-unstack/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/doc/tags
|
75
bundle/vim-unstack/README.markdown
vendored
Normal file
75
bundle/vim-unstack/README.markdown
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
unstack.vim
|
||||
=============
|
||||
|
||||
Parse stack traces or quickfix entries and open the result in vim splits!
|
||||
|
||||
Go from this:
|
||||
|
||||
<img src="http://i.imgur.com/DgXSAkq.png" width="800"/>
|
||||
|
||||
To this!
|
||||
|
||||
<img src="http://i.imgur.com/Q31wohX.png" width="800"/>
|
||||
|
||||
Version 0.5.0
|
||||
|
||||
No backwards compatability is guaranteed at this time.
|
||||
|
||||
Usage
|
||||
-----
|
||||
Visually select part/all of a stacktrace and hit `<leader>s`. If you want to use a different map key, put `let g:unstack_mapkey=<F10>` (replacing `<F10>` with the key of your choice, or an empty string to disable the mapping).
|
||||
|
||||
You can also copy a stack trace to your system clipboard (from any program) and run `:UnstackFromClipboard`.
|
||||
|
||||
Tmux users can copy a stack trace to the tmux paste buffer and call `:UnstackFromTmux`.
|
||||
|
||||
If this results in too many vsplits crowding the screen, consider taking a look at the [accordion](https://github.com/mattboehm/vim-accordion) plugin (shameless plug).
|
||||
|
||||
Signs
|
||||
-----
|
||||
By default, Unstack uses signs to highlight lines from stack traces in red. Signs are removed when the tab they were created in is closed. Sometimes a sign will appear to stick around after it's been removed until you switch tabs again. If you want to disable this feature add `set unstack_showsigns=0` to your .vimrc.
|
||||
|
||||
Portrait Layout
|
||||
---------------
|
||||
If you want the levels of the stack to open in hsplits (top to bottom instead of left to right), add the following to your .vimrc:
|
||||
|
||||
let g:unstack_layout = "portrait"
|
||||
|
||||
Line Positioning
|
||||
----------------
|
||||
By default, the line will be centered on the screen. Alternatively, you can tell Unstack to move the line to the top or bottom of the screen by adding `let g:unstack_vertical_alignment = "top"' (or `"bottom"`) to your vimrc.
|
||||
|
||||
This will respect your `scrolloff` setting. If you wish unstack to have a different amount of padding than your scrolloff, you can use `let g:unstack_scrolloff = 5`. Combined with changing the alignment to top, this would put the highlighted line 5 lines from the top of the file.
|
||||
|
||||
Note that because vim doesn't let the first line of the file go below the top of the window, if the highlighted line is close to the start of the file, a vertical alignment of middle or bottom will not move the line all the way to the middle/bottom of the window.
|
||||
|
||||
Supported Languages
|
||||
-------------------
|
||||
Currently the following stack traces are supported:
|
||||
|
||||
* Python
|
||||
* Ruby
|
||||
* C#
|
||||
* Perl
|
||||
* Go
|
||||
* Node.js
|
||||
* Erlang (R15+)
|
||||
* Valgrind
|
||||
* GDB / LLDB
|
||||
|
||||
Is there another language you'd like supported? Open an issue with some sample stack traces or read on to learn how to add custom languages (pull requests welcome).
|
||||
|
||||
Customizing Languages
|
||||
---------------------
|
||||
Unstack can easily be extended to support additional stack trace formats. Check out `:help unstack_extractors` and `:help unstack_regex_extractors` for more information.
|
||||
|
||||
Feel free to submit pull requests or open issues for other stack trace languages.
|
||||
|
||||
License
|
||||
-------
|
||||
Copyright (c) Matthew Boehm. Distributed under the same terms as Vim itself.
|
||||
See `:help license`.
|
||||
|
||||
|
||||
[](https://bitdeli.com/free "Bitdeli Badge")
|
||||
|
250
bundle/vim-unstack/autoload/unstack.vim
vendored
Normal file
250
bundle/vim-unstack/autoload/unstack.vim
vendored
Normal file
@ -0,0 +1,250 @@
|
||||
"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={{{,}}}
|
51
bundle/vim-unstack/autoload/unstack/extractors.vim
vendored
Normal file
51
bundle/vim-unstack/autoload/unstack/extractors.vim
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
"unstack#extractors#Regex(regex, file_replacement, line_replacement) constructs {{{
|
||||
"an extractor that uses regexes
|
||||
function! unstack#extractors#Regex(regex, file_replacement, line_replacement, ...)
|
||||
let extractor = {"regex": a:regex, "file_replacement": a:file_replacement,
|
||||
\ "line_replacement": a:line_replacement, "reverse": (a:0 > 0) ? a:1 : 0}
|
||||
function extractor.extract(text) dict
|
||||
let stack = []
|
||||
for line in split(a:text, "\n")
|
||||
let fname = substitute(line, self.regex, self.file_replacement, '')
|
||||
"if this line has a matching filename
|
||||
if (fname != line)
|
||||
let lineno = substitute(line, self.regex, self.line_replacement, '')
|
||||
call add(stack, [fname, lineno])
|
||||
endif
|
||||
endfor
|
||||
if self.reverse
|
||||
call reverse(stack)
|
||||
endif
|
||||
return stack
|
||||
endfunction
|
||||
|
||||
return extractor
|
||||
endfunction
|
||||
"}}}
|
||||
|
||||
function! unstack#extractors#GetDefaults()
|
||||
"I'm writing this as multiple statemnts because vim line continuations make
|
||||
"me cry
|
||||
let extractors = []
|
||||
"Python
|
||||
call add(extractors, unstack#extractors#Regex('\v^ *File "([^"]+)", line ([0-9]+).*', '\1', '\2'))
|
||||
"Ruby
|
||||
call add(extractors, unstack#extractors#Regex('\v^[ \t]*from (.+):([0-9]+):in `.*', '\1', '\2'))
|
||||
"C#
|
||||
call add(extractors, unstack#extractors#Regex('\v^[ \t]*at .*\(.*\) in (.+):line ([0-9]+) *$', '\1', '\2'))
|
||||
"Perl
|
||||
call add(extractors, unstack#extractors#Regex('\v^%(Trace begun|.+ called) at (.+) line (\d+)$', '\1', '\2'))
|
||||
" Go
|
||||
call add(extractors, unstack#extractors#Regex('\v^[ \t]*(.+):(\d+) \+0x\x+$', '\1', '\2'))
|
||||
" Node.js
|
||||
call add(extractors, unstack#extractors#Regex('\v^ +at .+\((.+):(\d+):\d+\)$', '\1', '\2'))
|
||||
" Erlang R15+
|
||||
call add(extractors, unstack#extractors#Regex('\v^.+\[\{file,"([^"]+)"\},\{line,([0-9]+)\}\]\}.*$', '\1', '\2'))
|
||||
" Valgrind
|
||||
call add(extractors, unstack#extractors#Regex('\v^\=\=\d+\=\=[ \t]*%(at|by).*\((.+):(\d+)\)$', '\1', '\2', 1))
|
||||
" GDB / LLDB
|
||||
call add(extractors, unstack#extractors#Regex('\v^[ *]*%(frame )?#\d+:? +0[xX][0-9a-fA-F]+ .+ at (.+):(\d+)', '\1', '\2', 1))
|
||||
return extractors
|
||||
endfunction
|
||||
|
||||
" vim: et sw=2 sts=2 foldmethod=marker foldmarker={{{,}}}
|
216
bundle/vim-unstack/doc/unstack.txt
vendored
Normal file
216
bundle/vim-unstack/doc/unstack.txt
vendored
Normal file
@ -0,0 +1,216 @@
|
||||
*unstack.txt* Extract/Open lines from stack traces
|
||||
*unstack*
|
||||
|
||||
Author: Matthew Boehm <http://github.com/mattboehm>
|
||||
|
||||
==============================================================================
|
||||
CONTENTS *unstack_contents*
|
||||
|
||||
╓ Introduction ─────────────────────────────── |unstack_intro|
|
||||
║
|
||||
╠ Commands ─────────────────────────────────── |unstack_commands|
|
||||
║ ├ UnstackFromText.......................... |:UnstackFromText|
|
||||
║ ├ UnstackFromClipboard..................... |:UnstackFromClipboard|
|
||||
║ ├ UnstackFromTmux.......................... |:UnstackFromTmux|
|
||||
║ ├ UnstackFromSelection..................... |:UnstackFromSelection|
|
||||
║
|
||||
╠ Options ──────────────────────────────────── |unstack_options|
|
||||
║ ├ mapkey................................... |unstack_mapkey|
|
||||
║ ├ showsigns................................ |unstack_showsigns|
|
||||
║ ├ layout................................... |unstack_layout|
|
||||
║ ├ vertical_alignment....................... |unstack_vertical_alignment|
|
||||
║ ├ scrolloff................................ |unstack_scrolloff|
|
||||
║ ├ populate_quickfix........................ |unstack_populate_quickfix|
|
||||
║ ├ open_tab................................. |unstack_open_tab|
|
||||
║ └ extractors............................... |unstack_extractors|
|
||||
║
|
||||
╠ Extractors ───────────────────────────────── |unstack_extraction_engines|
|
||||
║ └ Regex Extractors......................... |unstack_regex_extractors|
|
||||
║
|
||||
╙ Limitations ──────────────────────────────── |unstack_limitations|
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *unstack_intro*
|
||||
|
||||
Feed all or part of a stacktrace into this plugin and it will open a new tab
|
||||
with each level of the stacktrace in a new vsplit. This can be useful for
|
||||
seeing more context around an exception or to quickly edit offending files.
|
||||
|
||||
Unstack also supports opening lines from the quickfix list.
|
||||
|
||||
The basic usage is to highlight a block of text and type <leader>s. Not sure
|
||||
what <leader> is? It defaults to \ but to be sure, run `:echo mapleader`.
|
||||
|
||||
You can also copy a stack trace to your system clipboard from any program and
|
||||
then run |:UnstackFromClipboard|. If you use this a lot, you may want to map
|
||||
it to a hotkey like this:
|
||||
>
|
||||
nnoremap <F10> :UnstackFromClipboard<CR>
|
||||
<
|
||||
This allows you to copy from an external program and hit <F10> in vim to open
|
||||
the stack trace.
|
||||
|
||||
Tmux users can call |:UnstackFromTmux| instead to load a stack trace from the
|
||||
tmux paste buffer. That is particularly useful when working on remote machines
|
||||
that don't have a running x server.
|
||||
|
||||
When you launch unstack, it opens the files from the stack trace in a new tab.
|
||||
When you're done with the stack trace, run `:tabclose` to close the tab and
|
||||
return vim to the state it was in before you ran Unstack. If you are
|
||||
unfamiliar with tabs, read `:help |tabpage|` to learn more.
|
||||
==============================================================================
|
||||
COMMANDS *unstack_commands*
|
||||
|
||||
*:UnstackFromText* <text> Call unstack with text as input. Text can be:
|
||||
>
|
||||
:UnstackFromText g:foo "a variable
|
||||
:UnstackFromText @a "register a
|
||||
:UnstackFromText "some text" "literal text escaped with quotes
|
||||
<
|
||||
|
||||
*:UnstackFromClipboard* Call unstack with the contents of the clipboard
|
||||
Note: this is identical to `:UnstackFromText @+`
|
||||
|
||||
*:UnstackFromTmux* Call unstack with the contents of the tmux paste
|
||||
buffer
|
||||
|
||||
*:UnstackFromSelection* Call unstack with the contents of the X selection
|
||||
clipboard
|
||||
Note: this is identical to `:UnstackFromText @*`
|
||||
|
||||
==============================================================================
|
||||
OPTIONS *unstack_options*
|
||||
|
||||
|unstack_mapkey| shortcut to launch unstack default <leader>s
|
||||
|unstack_showsigns| whether or not to show signs on stacktrace lines
|
||||
|unstack_extractors| regexes for finding files/lines
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
let g:unstack_mapkey="<leader>s" *unstack_mapkey*
|
||||
|
||||
Press this combination with a visual selection (or in normal mode followed by
|
||||
a motion) to edit. To not define any key mapping, assign an empty string to
|
||||
this variable.
|
||||
------------------------------------------------------------------------------
|
||||
let g:unstack_showsigns=1 *unstack_showsigns*
|
||||
|
||||
If this is set to 1, unstack will put a |sign| on lines in the stacktrace.
|
||||
These signs will be visible in any window in the current vim session showing
|
||||
that file. Set to 0 to disable this.
|
||||
------------------------------------------------------------------------------
|
||||
let g:unstack_layout="landscape" *unstack_layout*
|
||||
|
||||
Determines how to layout windows when opening a stack trace
|
||||
* "landscape": open vsplits
|
||||
* "portrait": open hsplits
|
||||
------------------------------------------------------------------------------
|
||||
let g:unstack_vertical_alignment="middle" *unstack_vertical_alignment*
|
||||
|
||||
Options: "top", "middle", "bottom"
|
||||
|
||||
Where the line from the stack trace should be on the screen.
|
||||
If the line is too close to the beginning or end of the file, its position may
|
||||
differ slightly.
|
||||
------------------------------------------------------------------------------
|
||||
let g:unstack_scrolloff=0 *unstack_scrolloff*
|
||||
|
||||
The value for 'scrolloff' while unstack is opening files. This determines how
|
||||
many lines above the highlighted line are shown. The benefit of scrolloff is
|
||||
that it provides more context above the line being called, but the main issue
|
||||
is that it can cause highlighted lines to be at differing heights if the lines
|
||||
are near the top of the file.
|
||||
------------------------------------------------------------------------------
|
||||
let g:unstack_populate_quickfix=0 *unstack_populate_quickfix*
|
||||
|
||||
If true, puts lines from stack trace in quickfix list
|
||||
------------------------------------------------------------------------------
|
||||
let g:unstack_open_tab=1 *unstack_open_tab*
|
||||
|
||||
If true, opens the stack trace in vsplits in a new tab
|
||||
|
||||
This is the default behavior, and should remain true unless you only want
|
||||
unstack to populate the quickfix via |unstack_populate_quickfix|.
|
||||
------------------------------------------------------------------------------
|
||||
*unstack_extractors*
|
||||
let g:unstack_extractors=unstack#extractors#GetDefaults()
|
||||
Format: [extractor1, extractor2... ]
|
||||
|
||||
This is the list of |unstack_extraction_engines| that will be evaluated in order to
|
||||
extract a stack trace from the selected block of text. Setting this list wipes
|
||||
out any default extractors. If you want to keep the defaults but add an
|
||||
extractor to the list:
|
||||
* get the defaults by calling unstack#extractors#GetDefaults()
|
||||
* add your extractors to the defaults
|
||||
* set g:unstack_extractors to the combined list
|
||||
|
||||
==============================================================================
|
||||
EXTRACTORS *unstack_extraction_engines*
|
||||
|
||||
Extractors are dicts with an extract method that takes in text and returns a
|
||||
stack trace in the form [[filea, linea], [fileb, lineb]... ] by writing your
|
||||
own extractors, you can extend Unstack to handle parse stack traces with new
|
||||
formats!
|
||||
|
||||
If your extractor does not find any files, it should return an empty list
|
||||
If you can't extract line numbers, just use 0 for all line numbers
|
||||
|
||||
To make an extractor, do something like this:
|
||||
|
||||
let my_extractor = {}
|
||||
function my_extractor.extract(text) dict
|
||||
"convert text to a "stack" or return empty list if text format invalid
|
||||
endfunction
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
REGEX EXTRACTORS *unstack#extractors#regex*
|
||||
*unstack_regex_extractors*
|
||||
|
||||
If you want to write an extractor for a format where file path and line number
|
||||
can be extracted with regular expressions, there's a built-in factory to help
|
||||
you.
|
||||
|
||||
For instance, in python, stack traces look like this:
|
||||
|
||||
File "foo.py", line 10, in my_function
|
||||
divide(1, 0)
|
||||
File "math.py", line 6, in divide
|
||||
return a / b
|
||||
|
||||
First we want to form a regex that only matches valid lines with files:
|
||||
'\v^ *File "([^"]+)", line ([0-9]+).+'
|
||||
|
||||
Replacing this with the thing in the first perens (\1) yields the file path.
|
||||
you can test this by putting your cursor on the first line of the stack trace
|
||||
and running:
|
||||
:s/'\v^ *File "([^"]+)", line ([0-9]+).+'/\1/
|
||||
|
||||
running this should yield foo.py
|
||||
|
||||
repeating the process with \2 should yield the line number (10)
|
||||
|
||||
We now have all the necessary pieces. We can make our extractor by calling:
|
||||
|
||||
unstack#extractors#Regex('\v^ *File "([^"]+)", line ([0-9]+).+', '\1', '\2')
|
||||
|
||||
To use this extractor, you'd do one of the following:
|
||||
"Use only this extractor
|
||||
let g:unstack_extractors = [unstack#extractors#Regex('\v^ *File "([^"]+)", line ([0-9]+).+', '\1', '\2')]
|
||||
"Add this extractor to the list of defaults
|
||||
let g:unstack_extractors = unstack#extractors#GetDefaults() + [unstack#extractors#Regex('\v^ *File "([^"]+)", line ([0-9]+).+', '\1', '\2')]
|
||||
|
||||
unstack#extractors#Regex takes an optional argument that can be set to 1 to
|
||||
reverse the stack order (the default order is from top to bottom). For example
|
||||
for valgrind traces (which are in reversed order) you could use:
|
||||
|
||||
unstack#extractors#Regex('\v^\=\=\d+\=\=[ \t]*%(at|by).*\((.+):(\d+)\)$', '\1', '\2', 1)
|
||||
|
||||
==============================================================================
|
||||
LIMITATIONS *unstack_limitations*
|
||||
|
||||
1. Unstack only recognizes stack trace styles listed in README.markdown,
|
||||
but this can be extended via the |unstack_extractors| setting.
|
||||
2. If a stack trace contains relative paths, they must be relative to Vim's
|
||||
current working directory.
|
||||
|
||||
vim:tw=78:et:ft=help:norl:
|
56
bundle/vim-unstack/plugin/unstack.vim
vendored
Normal file
56
bundle/vim-unstack/plugin/unstack.vim
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
if exists('g:loaded_unstack')
|
||||
finish
|
||||
endif
|
||||
let g:loaded_unstack = 1
|
||||
|
||||
"Settings {{{
|
||||
if !exists('g:unstack_mapkey')
|
||||
let g:unstack_mapkey = '<leader>s'
|
||||
endif
|
||||
if g:unstack_mapkey !~# '^\s*$'
|
||||
exe 'nnoremap <silent> '.g:unstack_mapkey.' :set operatorfunc=unstack#Unstack<cr>g@'
|
||||
exe 'vnoremap <silent> '.g:unstack_mapkey.' :<c-u>call unstack#Unstack(visualmode())<cr>'
|
||||
endif
|
||||
|
||||
"List of text extractors
|
||||
if (!exists('g:unstack_extractors'))
|
||||
let g:unstack_extractors = unstack#extractors#GetDefaults()
|
||||
endif
|
||||
|
||||
"populate quickfix with stack
|
||||
if (!exists('g:unstack_populate_quickfix'))
|
||||
let g:unstack_populate_quickfix = 0
|
||||
endif
|
||||
|
||||
"open stack in vsplits in a new tab
|
||||
if (!exists('g:unstack_open_tab'))
|
||||
let g:unstack_open_tab = 1
|
||||
endif
|
||||
|
||||
"Either landscape (vsplits) or portrait (splits)
|
||||
if (!exists('g:unstack_layout'))
|
||||
let g:unstack_layout = "landscape"
|
||||
endif
|
||||
|
||||
"'scrolloff' value while files are opened
|
||||
if (!exists('g:unstack_scrolloff'))
|
||||
let g:unstack_scrolloff = 0
|
||||
endif
|
||||
|
||||
"where to put the line from the stack trace
|
||||
if (!exists('g:unstack_vertical_alignment'))
|
||||
let g:unstack_vertical_alignment = "middle"
|
||||
endif
|
||||
|
||||
"Whether or not to show signs on error lines (highlights them red)
|
||||
if !exists('g:unstack_showsigns')
|
||||
let g:unstack_showsigns = 1
|
||||
endif "}}}
|
||||
"Commands {{{
|
||||
command! -nargs=1 UnstackFromText call unstack#UnstackFromText(eval(<f-args>))
|
||||
command! UnstackFromClipboard call unstack#UnstackFromText(@+)
|
||||
command! UnstackFromSelection call unstack#UnstackFromText(@*)
|
||||
command! UnstackFromTmux call unstack#UnstackFromTmuxPasteBuffer()
|
||||
"}}}
|
||||
|
||||
" vim: et sw=2 sts=2 foldmethod=marker foldmarker={{{,}}}
|
@ -32,6 +32,7 @@ To use this configuration layer, update your custom configuration file with:
|
||||
- `:Scriptnames`: same as `:scriptnames`, but show results in quickfix list.
|
||||
- `:SourceCounter`: source counter for vim
|
||||
- `:Calendar`: open vim calendar
|
||||
- `:UnstackFromText`: Call unstack with text as input.
|
||||
|
||||
This layer also includes `vim-bookmarks`, the following key binding can be used:
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user