>From c7262056db33722bc84dd94fbadaa71ed8fbf5fc Mon Sep 17 00:00:00 2001 From: Phil Sainty Date: Sun, 11 Jun 2017 17:29:53 +1200 Subject: [PATCH] New commands for bulk tracing of elisp functions * lisp/emacs-lisp/trace.el (trace-package, untrace-package) (trace-regexp, untrace-regexp, trace-is-traceable-p): New functions. (trace--read-args): Use new trace-is-traceable-p predicate. (trace-is-traced, untrace-function, untrace-all): Doc updates/fixes. --- lisp/emacs-lisp/trace.el | 98 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 6 deletions(-) diff --git a/lisp/emacs-lisp/trace.el b/lisp/emacs-lisp/trace.el index 1c57d73..5dba151 100644 --- a/lisp/emacs-lisp/trace.el +++ b/lisp/emacs-lisp/trace.el @@ -257,7 +257,12 @@ trace-function-internal (or context (lambda () ""))) `((name . ,trace-advice-name) (depth . -100)))) +(defun trace-is-traceable-p (sym) + "Whether the given symbol is a traceable function." + (or (functionp sym) (macrop sym))) + (defun trace-is-traced (function) + "Whether FUNCTION is currently traced." (advice-member-p trace-advice-name function)) (defun trace--read-args (prompt) @@ -274,7 +279,7 @@ trace--read-args default (if beg (substring prompt beg) ": ")) prompt) - obarray 'fboundp t nil nil + obarray 'trace-is-traceable-p t nil nil (if default (symbol-name default))))) (when current-prefix-arg (list @@ -321,17 +326,98 @@ trace-function-background (defalias 'trace-function 'trace-function-foreground) (defun untrace-function (function) - "Untraces FUNCTION and possibly activates all remaining advice. -Activation is performed with `ad-update', hence remaining advice will get -activated only if the advice of FUNCTION is currently active. If FUNCTION -was not traced this is a noop." + "Remove trace from FUNCTION. If FUNCTION was not traced this is a noop." (interactive (list (intern (completing-read "Untrace function: " obarray #'trace-is-traced t)))) (advice-remove function trace-advice-name)) +;;;###autoload +(defun trace-package (prefix) + "Trace all functions with names starting with PREFIX. +For example, to trace all diff functions, do the following: + +\\[trace-package] RET diff- RET + +Background tracing is used. Switch to the trace output buffer to +view the results. + +See also `untrace-package'." + (interactive ;; derived from `elp-instrument-package'. + (list (completing-read "Prefix of package to trace: " + obarray #'trace-is-traceable-p))) + (when (zerop (length prefix)) + (error "Tracing all Emacs functions would render Emacs unusable")) + (mapc (lambda (name) + (trace-function-background (intern name))) + (all-completions prefix obarray #'trace-is-traceable-p)) + (message + "Tracing to %s. Use %s to untrace a package, or %s to remove all traces." + trace-buffer + (substitute-command-keys "\\[untrace-package]") + (substitute-command-keys "\\[untrace-all]"))) + +(defun untrace-package (prefix) + "Remove traces from all functions with names starting with PREFIX. + +See also `trace-package'." + (interactive + (list (completing-read "Prefix of package to untrace: " + obarray #'trace-is-traced))) + (if (and (zerop (length prefix)) + (y-or-n-p "Remove all function traces?")) + (untrace-all) + (mapc (lambda (name) + (untrace-function (intern name))) + (all-completions prefix obarray #'trace-is-traceable-p)))) + +;;;###autoload +(defun trace-regexp (regexp) + "Trace all functions with names matching REGEXP. +For example, to trace indentation-related functions, you could try: + +\\[trace-regexp] RET indent\\|offset RET + +Warning: Do not attempt to trace all functions. Tracing too many +functions at one time will render Emacs unusable. + +Background tracing is used. Switch to the trace output buffer to +view the results. + +See also `untrace-regexp'." + (interactive + (list (read-regexp "Regexp matching functions to trace: "))) + (when (member regexp '("" "." ".+" ".*")) + ;; Not comprehensive, but it catches the most likely attempts. + (error "Tracing all Emacs functions would render Emacs unusable")) + (mapatoms + (lambda (sym) + (and (trace-is-traceable-p sym) + (string-match-p regexp (symbol-name sym)) + (trace-function-background sym)))) + (message + "Tracing to %s. Use %s to untrace by regexp, or %s to remove all traces." + trace-buffer + (substitute-command-keys "\\[untrace-regexp]") + (substitute-command-keys "\\[untrace-all]"))) + +(defun untrace-regexp (regexp) + "Remove traces from all functions with names matching REGEXP. + +See also `trace-regexp'." + (interactive + (list (read-regexp "Regexp matching functions to untrace: "))) + (if (and (zerop (length regexp)) + (y-or-n-p "Remove all function traces?")) + (untrace-all) + (mapatoms + (lambda (sym) + (and (trace-is-traceable-p sym) + (string-match-p regexp (symbol-name sym)) + (untrace-function sym)))))) + (defun untrace-all () - "Untraces all currently traced functions." + "Remove traces from all currently traced functions." (interactive) (mapatoms #'untrace-function)) -- 2.8.3