Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the backtrace of a function call

Tags:

vim

To make the <Fn> keys more customizable, I use a script (I called it fkeys.vim) which creates mappings threw the call of a function (let's call it Map()) : the call to this function replaces the use of the :map commands in many of my scripts.

It's very comfortable because it lets me add easily some nice features around my personnal mappings, but it brings me a new problem: when I want to know from where a certain mapping is defined, like this:

:verbose map ...

, then vim always says that the mapping was last defined in the fkeys.vim script, not in the real script where Map() is called. It's logical, but very frustrating, because the :verbose map command is very useful, and is the only way I know to find a mapping definition quickly.

One solution would be to add an argument to my Map() function, where the filename of the actual script would be passed (in order to store this information and get it back when i need it):

function! Map(lhs, rhs, [some other args...], caller)

But it would pollute my scripts readability, and it doesn't look very elegant.

Something better would be to be able to get the backtrace of the function call, like debug_backtrace() in php.

Is it possible with Vim?

like image 316
yolenoyer Avatar asked Feb 09 '23 20:02

yolenoyer


1 Answers

It isn't possible to get a true backtrace, but if you keep things clean you might be able to get away with parsing <sfile>. According to the manual:

              When executing a function, is replaced with:
              "function {function-name}[{lnum}]"
              function call nesting is indicated like this:
              "function {function-name1}[{lnum}]..{function-name2}[{lnum}]"

Thus something like this should do:

function! Backtrace(trace)
    return map(split(substitute(a:trace, '^function ', '', ''), '\.\.'), 'substitute(v:val, ''\m\[\d\+\]$'', "", "")')[:-2]
endfunction

You need to call it like this:

let callers = Backtrace(expand('<sfile>'))

Example:

function! F1()
    call Fn()
endfunction

function! F2()
    call F1()
endfunction

function! F3()
    call F2()
endfunction

function! Fn()
    echomsg expand('<sfile>')
    echomsg string(Backtrace(expand('<sfile>')))
endfunction

call F3()

Output:

function F3[1]..F2[1]..F1[1]..Fn
['F3', 'F2', 'F1']
like image 61
lcd047 Avatar answered Mar 06 '23 08:03

lcd047