Создание ссылок на имена файлов/номера строк в буфере Emacs gud

Я запускаю pdb на своих тестовых примерах в Python через буфер gud. Когда я получаю трассировку стека/сбой в своем тестовом примере, это выглядит так:

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

кликабельно и перейти к строке 499 в testfoo.py.

(редактировать) Люди из списка python-mode привели меня к pdbtrack, и я смог заставить его работать там. Смотрите ответ ниже...


person matt harrison    schedule 18.01.2010    source источник
comment
это было бы круто. Мне любопытно узнать больше о вашей настройке для запуска тестов в буфере gud. извините, я не могу ответить на ваш вопрос, хотя   -  person Tom Willis    schedule 19.01.2010
comment
В моем блоге есть сообщение о моей старой настройке (panela.blog-city.com/python_and_emacs_5_pdb_and_emacs .htm). В настоящее время я использую режим оболочки/режим python (версия python.org, а не версия emacs) и pdbtrack   -  person matt harrison    schedule 27.09.2010


Ответы (3)


Благодаря подсказке Джерарда Б я понял это. Я делаю это из pdbtrack (оболочки) вместо чистого 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))

Затем вы можете использовать стандартную навигацию в режиме компиляции, чтобы просмотреть трассировку стека ошибок.

person matt harrison    schedule 23.01.2010
comment
Обратите внимание, что это работает при первом открытии файла/буфера. Со временем появляется некоторый дрейф (т. е. курсор появляется через несколько строк после фактической строки) - person matt harrison; 27.09.2010
comment
Спасибо! Но я заметил, что хотя строки в верхней части длинной трассировки кликабельны, строки ниже — нет. - person nealmcb; 16.10.2017
comment
Не было времени анализировать код, чтобы понять, почему он дрейфует. Однако отключение и повторное включение compilation-shell-minor-mode, по-видимому, исправляет дрейф. - person Lorem Ipsum; 02.03.2021

Я думаю, что вы хотите настроить compilation-parse-errors-filename-function, функцию, которая принимает имя файла и возвращает измененную версию имени файла для отображения. Это локальная переменная буфера, поэтому вы должны установить ее в каждом буфере, который будет отображать ошибки python (вероятно, есть подходящий хук для использования, у меня не установлен режим python, поэтому я не могу его найти). Вы должны использовать propertize, чтобы вернуть версию входного имени файла, которая действует как гиперссылка для загрузки фактического файла. propertyize хорошо документирован в руководстве elisp.

Если функция компиляции-анализа-ошибок-имя-файла не вызывается, то вы хотите добавить список в compilation-error-regexp-alist-alist (который действительно говорит alist-alist, это не опечатка), который представляет собой список имен режимов, за которыми следуют регулярные выражения для ошибки совпадения и числовые индексы совпадающего номера строки, имени файла и т. д. Информация в регулярном выражении ошибки соответствует.

person Justin Smith    schedule 18.01.2010

Добавление к ответу Джастина:

У меня есть следующее в моей конфигурации слизи, которая должна перейти к файлу и строке из трассировки стека clojure.

К сожалению, я должен признать, что на данный момент это не работает для меня - функция не может найти правильный файл - но, насколько я могу судить, это можно исправить, изменив определение project-root или изменив структура моих проектов в файловой системе (у меня просто не было ни времени, ни желания разбираться в этом).

Тем не менее, это поднимает хороший вопрос: в большинстве подобных функций немного сложно определить корень проекта в универсальной и переносимой форме. В этом случае мы полагаемся на каталог src, но это, вероятно, не подходит для ваших проектов Python.

Таким образом, продолжая с того места, где остановился Джастин, вы сможете воспользоваться некоторыми советами из приведенной ниже функции и проанализировать имя файла и номера строк из ошибки тестового примера, создать ссылку на номер строки и использовать compilation-parse-errors-filename-function и 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-адрес. Кажется, это из превосходного стартового набора Emacs Фила Хагельберга (техномантия).

person liwp    schedule 19.01.2010