我正在尝试使用自动加载功能填充quickfix列表,即:
function! myplugin#myfunc(msg)
" this doesn't work from *inside* an autoload function
let filename = fnamemodify(resolve(expand('<sfile>:p')))
" not sure if it's possible to get the line number from where
" a function was called
let linenum = '?#'
" create qf dict object
" set filename, line number, bufnr, text, etc
" add dict to qflist
" setqflist(qfdictlist)
endfunction!
我遇到的问题是我无法找到从调用自动加载功能的代码中获取文件名和行号的方法。有什么建议吗?
答案 0 :(得分:3)
开箱即用。这是不可能的。
但是,根据具体情况,这里有一些线索。
我发现在捕获异常时,我试图编写一个从v:throwpoint
解码callstack的函数。它仍然是实验性的。请参阅https://github.com/LucHermitte/lh-vim-lib/blob/master/autoload/lh/exception.vim
从我的test unit framework,我确切地知道哪个测试文件/行失败了。为此,我必须解析UT文件,以便将调用者的行号注入:Assert*
命令。
如您所见,这些解决方案都不是很好。但现在还没有其他人。除了在异常上下文中的v:throwpoint
之外,callstack不可用。唯一的解决方案是让调用者在调用时注入他们的引用(〜__FILE__
+〜__LINE__
)。自动执行此操作的唯一方法是将编译调用者脚本到另一个自动注入缺失信息的脚本中。
立即 ,了解上个月有关于vim-dev邮件列表的提案,以便允许访问调用堆栈,但唉,只有在调试会话期间:{ {3}} 如果这被接受,可以稍后扩展以提供将导出此信息的viml函数。
编辑:你的问题激励我为vim写一个https://github.com/vim/vim/pull/433:
" Function: lh#log#new(where, kind) {{{3
" - where: "vert"/""/...
" - kind: "qf"/"loc" for loclist
" NOTE: In order to obtain the name of the calling function, an exception is
" thrown and the backtrace is analysed.
" In order to work, this trick requires:
" - a reasonable callstack size (past a point, vim shortens the names returned
" by v:throwpoint
" - named functions ; i.e. functions defined on dictionaries (and not attached
" to them) will have their names mangled (actually it'll be a number) and
" lh#exception#callstack() won't be able to decode them.
" i.e.
" function s:foo() dict abort
" logger.log("here I am");
" endfunction
" let dict.foo = function('s:foo')
" will work correctly fill the quicklist/loclist, but
" function dict.foo() abort
" logger.log("here I am");
" endfunction
" won't
" TODO: add verbose levels
function! lh#log#new(where, kind) abort
let log = { 'winnr': bufwinnr('%'), 'kind': a:kind, 'where': a:where}
" open loc/qf window {{{4
function! s:open() abort dict
try
let buf = bufnr('%')
exe 'silent! '.(self.where). ' '.(self.kind == 'loc' ? 'l' : 'c').'open'
finally
call lh#buffer#find(buf)
endtry
endfunction
" add {{{4
function! s:add_loc(msg) abort dict
call setloclist(self.winnr, [a:msg], 'a')
endfunction
function! s:add_qf(msg) abort dict
call setqflist([a:msg], 'a')
endfunction
" clear {{{4
function! s:clear_loc() abort dict
call setloclist(self.winnr, [])
endfunction
function! s:clear_qf() abort dict
call setqflist([])
endfunction
" log {{{4
function! s:log(msg) abort dict
let data = { 'text': a:msg }
try
throw "dummy"
catch /.*/
let bt = lh#exception#callstack(v:throwpoint)
if len(bt) > 1
let data.filename = bt[1].script
let data.lnum = bt[1].pos
endif
endtry
call self._add(data)
endfunction
" reset {{{4
function! s:reset() dict abort
call self.clear()
call self.open()
return self
endfunction
" register methods {{{4
let log.open = function('s:open')
let log._add = function('s:add_'.a:kind)
let log.clear = function('s:clear_'.a:kind)
let log.log = function('s:log')
let log.reset = function('s:reset')
" open the window {{{4
call log.reset()
return log
endfunction
使用我的另一个解码callstack的函数。
答案 1 :(得分:1)
好吧,如果你无法从里面的自动加载功能中获取文件和行,你必须将传递给你的函数。
您可以通过自定义映射,命令或:autocmd
事件以某种方式调用自动加载的函数。从那里,您可以解析当前文件(expand('%')
和行号('line('.')
)并将其传入。
但为什么你需要那个吗?!对于正常的编辑任务,我无法想象为什么。如果您正在编写自定义Vim调试插件,那么这可能很有用。但是通过Vimscript进行调试很困难(正如你已经发现的那样),没有暴露出callstack。更好地坚持使用内置:debug
和:breakadd
;到目前为止,我发现它们足够了。