I've taken the liberty to build on both @romainl and @LucHermite's answers. I define the Stacktrace
function, which can be called both manually and to get a trace for a specific error.
function! MyFunction(...)
" Stacktrace can be called to get a manual stacktrace
call Stacktrace()
" It can also be called to get stacktrace for an error
try
" ...
catch
call Stacktrace()
endtry
endfunction
function! Stacktrace()
"
" Get stack and exception
"
if empty(v:throwpoint)
try
throw 'dummy'
catch
let l:stack = reverse(split(v:throwpoint, '\.\.'))[1:]
let l:exception = 'Manual stacktrace'
endtry
else
let l:stack = reverse(split(v:throwpoint, '\.\.'))
let l:exception = v:exception
endif
"
" Build the quickfix entries
"
let l:qflist = []
let l:files = {}
for l:func in l:stack
let [l:name, l:offset] = (l:func =~# '\S\+\[\d')
\ ? matchlist(l:func, '\(\S\+\)\[\(\d\+\)\]')[1:2]
\ : matchlist(l:func, '\(\S\+\), line \(\d\+\)')[1:2]
if l:name =~# '\v(\<SNR\>|^)\d+_'
let l:sid = matchstr(l:name, '\v(\<SNR\>|^)\zs\d+\ze_')
let l:name = substitute(l:name, '\v(\<SNR\>|^)\d+_', 's:', '')
let l:filename = map(
\ Command('scriptnames'),
\ 'split(v:val, "\\v:=\\s+")[1]')[l:sid-1]
else
let l:name = l:name
let l:filename = matchstr(
\ Command('verbose function ' . l:name)[1],
\ '.\{-}\s\+\zs\f\+$')
endif
let l:filename = fnamemodify(l:filename, ':p')
if filereadable(l:filename)
if !has_key(l:files, l:filename)
let l:files[l:filename] = reverse(readfile(l:filename))
endif
let l:lnum = l:offset + len(l:files[l:filename])
\ - match(l:files[l:filename], '^\s*fu\%[nction]!\=\s\+' . l:name)
let l:text = len(l:qflist) == 0 ? l:exception : '#' . len(l:qflist)
call add(l:qflist, {
\ 'filename': l:filename,
\ 'lnum': l:lnum,
\ 'text': l:text,
\})
endif
endfor
call setqflist(l:qflist)
execute 'copen' len(l:qflist) + 2
wincmd p
endfunction
function! Command(cmd)
let l:a = @a
try
silent! redir @a
silent! execute a:cmd
redir END
finally
let l:res = @a
let @a = l:a
return split(l:res, "\n")
endtry
endfunction
:help error-file-format
. That's the solution that I would like the most. If one day I know how to do it, I'll post it here. Thank you for pointing me on the right direction ('errorformat'
) and confirming it's possible.