【问题标题】:Making filenames/line numbers linkable in Emacs gud buffer在 Emacs gud 缓冲区中使文件名/行号可单击
【发布时间】:2010-01-18 18:35:03
【问题描述】:

我通过 gud 缓冲区在 Python 中的测试用例上运行 pdb。当我在测试用例中收到堆栈跟踪/失败时,它看起来像这样:

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')

我希望能够将以下行设为:

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

可点击并转到 testfoo.py 中的第 499 行。

(编辑)python-mode 列表中的人把我带到了 pdbtrack,我能够让它在那里工作。请参阅下面的答案...

【问题讨论】:

  • 那会很酷。我很想知道更多关于您在 gud 缓冲区中运行测试的设置。抱歉,我无法回答您的问题
  • 我的博客上有一篇关于我的旧设置的帖子 (panela.blog-city.com/python_and_emacs_5_pdb_and_emacs.htm)。我目前使用的是 shell-mode/python-mode(python.org 版本不是 emacs 版本)和 pdbtrack

标签: python emacs pdb gud


【解决方案1】:

感谢 Gerard B 的提示,我明白了。我是从 pdbtrack(shell)而不是纯 pdb 执行此操作的,但我相信它应该在两者中都有效。您需要启用编译外壳次要模式。并在您的 .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))

然后您可以使用标准编译模式导航来压缩错误堆栈跟踪。

【讨论】:

  • 请注意,这在文件/缓冲区首次打开时有效。随着时间的推移,似乎出现了一些“漂移”(即光标出现在实际行之后的一些行)
  • 谢谢!但我注意到,虽然长回溯顶部的行是可点击的,但更下方的行不可点击。
  • 还没来得及剖析代码以了解它“漂移”的原因。然而,禁用和重新启用compilation-shell-minor-mode 似乎可以纠正偏差。
【解决方案2】:

我认为您要自定义的是compilation-parse-errors-filename-function,这是一个接受文件名并返回要显示的文件名的修改版本的函数。这是一个缓冲区局部变量,因此您应该在每个将显示 python 错误的缓冲区中设置它(可能有一个合适的钩子可以使用,我没有安装 python 模式,所以我无法查找它)。您将使用propertize 返回输入文件名的版本,该版本充当加载实际文件的超链接。 elisp 手册中详细记录了propertize。

如果没有调用compilation-parse-errors-filename-function,那么您想将一个列表添加到compilation-error-regexp-alist-alist(确实是alist-alist,这不是错字),这是一个模式名称列表后跟正则表达式匹配错误,以及错误正则表达式匹配中匹配行号、文件名等信息的数字索引。

【讨论】:

    【解决方案3】:

    添加到贾斯汀的答案:

    我的 slime 配置中有以下内容,它应该从 clojure 堆栈跟踪跳转到文件和行。

    不幸的是,我必须承认它目前实际上对我不起作用 - 该函数无法找到正确的文件 - 但据我所知,这应该可以通过更改 project-root 的方式来解决被定义或通过更改我在文件系统上的项目结构(我只是没有时间或意愿去研究它)。

    虽然它确实提出了一个很好的观点,但在大多数这样的功能中,以通用和可移植的方式找出项目根有点棘手。在这种情况下,我们依赖于 src 目录,但这可能不适合您的 python 项目。

    因此,从 Justin 停止的地方开始,您应该能够从下面的函数中获取一些提示,并从测试用例错误中解析文件名和行号,创建指向行号的链接,并使用 @ 987654323@ 和 propertize 使 gud 缓冲区中的行成为链接。

    如果您确实可以使用它,请为您自己的问题添加答案。我想很多人会觉得它很有用。

      (defun slime-jump-to-trace (&optional on)
        "Jump to the file/line that the current stack trace line references.
        Only works with files in your project root's src/, not in dependencies."
        (interactive)
        (save-excursion
          (beginning-of-line)
          (search-forward-regexp "[0-9]: \\([^$(]+\\).*?\\([0-9]*\\))")
          (let ((line (string-to-number (match-string 2)))
                (ns-path (split-string (match-string 1) "\\."))
                (project-root (locate-dominating-file default-directory "src/")))
    
            (find-file (format "%s/src/%s.clj" project-root
                               (mapconcat 'identity ns-path "/")))
            (goto-line line))))
    

    我还应该提到我从网络上的某个地方复制了这个函数,但我不记得 URL。它似乎来自 Phil Hagelberg 的(技术专家)优秀的 Emacs 入门工具包。

    【讨论】:

      【解决方案4】:

      这是一个跳转到跟踪中指定的文件和行的函数。

      如果您将点放在回溯的“文件”行的任何位置, 该函数将找到该文件并将该点移动到另一个窗口中指定行的前面:

      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')
      
      (defun my-jump-to-file-from-python-error ()
        "Jump to line in file specified by a Python traceback."
        (interactive)
        (let* ((line (buffer-substring-no-properties (line-beginning-position) (line-end-position)))
               file
               number)
      
          (string-match "^ *File \\(\"?\\)\\([^,\" \n    <>]+\\)\\1, lines? \\([0-9]+\\)-?\\([0-9]+\\)?" line)
      
          (setq file (match-string 2 line))
          (setq number (match-string 3 line)) ; match is string, not numeric
      
          (cond ((and file number)
                 (find-file-other-window file)
                 (with-current-buffer (get-buffer (file-name-nondirectory file))
                   (goto-char (point-min))
                   (forward-line (1- (string-to-number number))))))))
      

      我刚刚从@matt harrison 的回复中复制了正则表达式。如果您更改它,我建议使用regexp-builder 并按C-c C-ereb-enter-subexp-mode。这使您可以循环遍历子表达式并知道文件和行号使用哪个匹配项。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多