;; -*- lexical-binding: t -*- (defun backtrace-1 (evald func args flags) "Print a trace of a single stack frame to `standard-output'. EVALD, FUNC, ARGS, FLAGS are as in `mapbacktrace'." (let ((print-level (or print-level 8))) (princ (if (plist-get flags :debug-on-exit) "* " " ")) (cond ((and evald (not debugger-stack-frame-as-list)) (prin1 func) (if args (prin1 args) (princ "()"))) (t (prin1 (cons func args)))) (princ "\n"))) (defun backtrace () "Print a trace of Lisp function calls currently active. Output stream used is value of `standard-output'." (mapbacktrace #'backtrace-1 'backtrace)) (backtrace) (defun backtrace-frames () "Collect all frames of current backtrace into a list." (let ((frames nil)) (mapbacktrace (lambda (&rest frame) (push frame frames)) 'backtrace-frames) (nreverse frames))) (backtrace-frames) (defun ~/backtrace-frame (nframes &optional base) "Return the function and arguments NFRAMES up from current execution point. If that frame has not evaluated the arguments yet (or is a special form), the value is (nil FUNCTION ARG-FORMS...). If that frame has evaluated its arguments and called its function already, the value is (t FUNCTION ARG-VALUES...). A &rest arg is represented as the tail of the list ARG-VALUES. FUNCTION is whatever was supplied as car of evaluated list, or a lambda expression for macro calls. If NFRAMES is more than the number of frames, the value is nil. If BASE is non-nil, it should be a function and NFRAMES counts from its nearest activation frame." (let ((frame nil)) (mapbacktrace (lambda (evald func args _) (when (and base (eq func base)) (setq base nil)) (unless base (when (eq nframes 0) (setq frame `(,evald ,func ,@args))) (setq nframes (1- nframes)))) '~/backtrace-frame) frame))