Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making filenames/line numbers linkable in Emacs gud buffer

I'm running pdb on my testcases in Python through the gud buffer. When I get a stacktrace/failure in my testcase, it looks like this:

FAIL: test_foo_function (__main__.TestFoo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test/testfoo.py", line 499, in test_foo_function
    self.assertEqual('foo', 'foo')

I'd love to be able to make the line(s) like:

File "test/testfoo.py", line 499, in test_foo_function

clickable and take be to line 499 in testfoo.py.

(edit) The folks on the python-mode list led me to pdbtrack and I was able to get it to work there. See answer below...

like image 488
matt harrison Avatar asked Jan 18 '10 18:01

matt harrison


2 Answers

Thanks to a hint by Gerard B I figured it out. I'm doing this from pdbtrack (shell) instead of pure pdb, but it should work in both I believe. You need to enable compilation-shell-minor-mode. And have the following code in your .emacs:

;; if compilation-shell-minor-mode is on, then these regexes
;; will make errors linkable
(defun matt-add-global-compilation-errors (list)
  (dolist (x list)
    (add-to-list 'compilation-error-regexp-alist (car x))
    (setq compilation-error-regexp-alist-alist
      (cons x
            (assq-delete-all (car x)
                             compilation-error-regexp-alist-alist)))))

(matt-add-global-compilation-errors
 `(
   (matt-python ,(concat "^ *File \\(\"?\\)\\([^,\" \n    <>]+\\)\\1"
                    ", lines? \\([0-9]+\\)-?\\([0-9]+\\)?")
           2 (3 . 4) nil 2 2)
   (matt-pdb-stack ,(concat "^>?[[:space:]]*\\(\\([-_./a-zA-Z0-9 ]+\\)"
                       "(\\([0-9]+\\))\\)"
                       "[_a-zA-Z0-9]+()[[:space:]]*->")
              2 3 nil 0 1)
   (matt-python-unittest-err "^  File \"\\([-_./a-zA-Z0-9 ]+\\)\", line \\([0-9]+\\).*" 1 2)
   )
 )

(defun matt-set-local-compilation-errors (errors)
  "Set the buffer local compilation errors.

Ensures than any symbols given are defined in
compilation-error-regexp-alist-alist."
  (dolist (e errors)
     (when (symbolp e)
      (unless (assoc e compilation-error-regexp-alist-alist)
        (error (concat "Error %s is not listed in "
                       "compilation-error-regexp-alist-alist")
               e))))
  (set (make-local-variable 'compilation-error-regexp-alist)
       errors))

Then you can use standard compile mode navigation to zip through the error stack trace.

like image 195
matt harrison Avatar answered Oct 14 '22 16:10

matt harrison


I think what you want to customize is compilation-parse-errors-filename-function, which is a function that takes a filename, and returns a modified version of the filename to be displayed. This is a buffer local variable, so you should set it in each buffer that will be displaying python errors (there is probably an appropriate hook to use, I do not have python mode installed so I cannot look it up). You would use propertize to return a version of the input filename that acts as a hyperlink to load the actual file. propertize is well documented in the elisp manual.

If compilation-parse-errors-filename-function is not getting called, then you want to add a list to compilation-error-regexp-alist-alist (that does say alist-alist, that is not a typo) which is a list of mode names followed by regular expressions to match errors, and numerical indexes of the matching line number, filename etc. info in the error regexp match.

like image 38
Justin Smith Avatar answered Oct 14 '22 16:10

Justin Smith