#python #emacs #flymake #pyflakes
#python #emacs #flymake #pyflakes
Вопрос:
В настоящее время я использую следующий код для подключения flymake и Pyflakes в emacs:
(defun flymake-create-temp-in-system-tempdir (filename prefix)
(make-temp-file (or prefix "flymake")))
и затем я передаю эту функцию flymake-init-create-temp-buffer-copy
. (Взято из http://hustoknow.blogspot.com/2010/09/emacs-and-pyflakes-using-tmp-directory.html ).
Этот код отлично работал до вчерашнего дня. При посещении определенных файлов Python я получаю следующую ошибку:
switched OFF Flymake mode for buffer admin.py due to fatal status
CFGERR, warning Configuration error has occured while running
(pyflakes ../../../../../../../tmp/flymake28459SVv)
Почему flymake передает pyflakes то, что кажется неправильным именем файла? Я ожидаю, что он передаст что-то вроде «/tmp /efe234234», и я не изменил ни один из параметров каталога tmp.
Я не помню, чтобы emacs недавно обновлялся для Ubuntu, и не могу придумать ничего, что могло бы привести к сбою (файлы.emacs имеют версию).
Единственная проблема, о которой я могу подумать, заключается в том, что это сильно вложенный каталог, символически связанный с каталогом в моем каталоге ~ / Dropbox, но этого не происходит с другими символьными ссылками аналогичным образом.
Как я могу решить эту проблему?
Обновить
Я выполнил некоторую отладку, и теперь я вижу, что он не передает правильный путь в качестве аргумента. Для его работы требуется вставить еще один родительский каталог в path, что заставляет меня думать, что он запутывается из-за символических ссылок.
Вот пример сеанса командной строки, чтобы показать, что я имею в виду. Я делаю это из правильного относительного каталога:
$ pyflakes ../../../../../tmp/flymake13382xHi
../../../../../tmp/flymake13382xHi: No such file or directory
Это команда, которую пытается выполнить flymake. Если я изменю его:
$ pyflakes ../../../../../../tmp/flymake13382xHi
Я не получаю выходных данных (как и ожидалось). Обратите внимание на лишний «..» в пути.
Как я могу заставить flymake передавать абсолютный путь вместо этих сумасшедших относительных путей?
ОБНОВЛЕНИЕ 2
Я заставил все работать. В принципе, есть такая функция:
(defun flymake-pyflakes-init ()
; Make sure it's not a remote buffer or flymake would not work
(when (not (subsetp (list (current-buffer)) (tramp-list-remote-buffers)))
(let* ((temp-file (flymake-init-create-temp-buffer-copy
'flymake-create-temp-in-system-tempdir))
(local-file (file-relative-name
temp-file
(file-name-directory buffer-file-name))))
(list "pyflakes" (list temp-file)))))
В последней части мне пришлось изменить аргумент на list
from local-file
на temp-file
потому local-file
что это был сумасшедший относительный путь, который мне не нужен. Почему автор этого фрагмента использовал local-file
в первую очередь?
Спасибо, Райан
Ответ №1:
Что касается меня, я решил, изменив пользовательский скрипт / usr / local /bin/ pyflakes, я проверяю, существует ли файл, если нет, я добавляю косую черту.
#!/bin/bash
FILE=$1
# Test if folder exist
if [ ! -e "$FILE" ]; then
FILE="/$1"
fi
epylint "$FILE" 2>/dev/null
pep8 --ignore=E221,E701,E202 --repeat "$FILE"
true
Ответ №2:
У меня нет прямого решения вопроса pyflakes, но вот что-то похожее для вас.
Мне не понравилось, как C # обрабатывался в flymake, поэтому я изменил запись C # в flymake-allowed-file-name-masks
, чтобы ссылаться на различные процедуры инициализации и очистки, с помощью этого кода:
(let ((csharpentry (assoc "\.cs\'" flymake-allowed-file-name-masks)))
(if csharpentry
(setcdr csharpentry '(csharp-flymake-init csharp-flymake-cleanup))
(add-to-list
'flymake-allowed-file-name-masks
(list key 'csharp-flymake-init 'csharp-flymake-cleanup))))
Документация по этому вопросу довольно неоднородна, но код — это документация, и, насколько я могу судить, процедура инициализации должна возвращать командную строку для выполнения проверки синтаксиса. Он отформатирован как список из двух элементов, car — это команда для запуска, а cadr сам по себе является списком аргументов. В моем примере возвращаемое значение выглядит следующим образом:
("csc.exe" ("/t:module" "/nologo" "nameOfFileToCheck.cs"))
Процедура инициализации, которая возвращает эту командную строку, копирует существующий буфер во временный файл, используя встроенную копию fn flymake, а затем использует имя временного файла для проверки. Итак, если имя файла буфера «source.cs», фактическое значение, возвращаемое из init fn, равно
("csc.exe" ("/t:module" "/nologo" "source_flymake.cs"))
Код выглядит следующим образом:
(defun csharp-flymake-init ()
(csharp-flymake-init-impl
'flymake-create-temp-inplace t t 'csharp-flymake-get-cmdline))
(defun csharp-flymake-init-impl (create-temp-f use-relative-base-dir use-relative-source get-cmdline-f)
"Create syntax check command line for a directly checked source file.
Use CREATE-TEMP-F for creating temp copy."
(let* ((args nil)
(temp-source-file-name (flymake-init-create-temp-buffer-copy create-temp-f)))
(setq args (flymake-get-syntax-check-program-args
temp-source-file-name "."
use-relative-base-dir use-relative-source
get-cmdline-f))
args))
Я реализовал его в двух разных функциях, только чтобы следовать шаблону, который я видел в flymake.el.
В любом случае…Вы можете видеть, что инициализация fn создает временный файл, а затем возвращает аргументы. Вызов flymake-get-syntax-check-program-args
фактически сводится к вызову into get-cmdline-f
, которым в случае C # является csharp-flymake-get-cmdline
. Зачем все это наслоение и косвенность? Я не знаю; вот как работает flymake.
В специфичной для C # функции очистки fn я просто проверяю наличие любых файлов «product» из проверки синтаксиса и удаляю их, а затем также подключаюсь к flymake-simple-cleanup
, чтобы удалить временный файл *_flymake.cs, который был создан.
Возможно, ваш вложенный путь к каталогу имеет какое-то отношение к аргументам use-relative-base-dir
и use-relative-source
, которые flymake использует в своей собственной процедуре инициализации по умолчанию, которая, я думаю, является flymake-simple-make-init-impl
.
Ответ №3:
Функция make-temp-file
использует переменную temporary-file-directory
, поэтому, возможно, вы могли бы попробовать установить temporary-file-directory
что-нибудь другое, чтобы решить вашу проблему.
Ответ №4:
Это то, что я использую для PHP в Windows. В нем используется make-temp-file
предложение Trey. Он также явно устанавливает функции инициализации и очистки для PHP в соответствии с тем, что я хочу. Вы могли бы использовать в основном то же самое для python.
(defun cheeso-flymake-create-temp-intemp (file-name prefix)
"Return file name in temporary directory for checking FILE-NAME.
This is a replacement for `flymake-create-temp-inplace'. The
difference is that it gives a file name in
`temporary-file-directory' instead of the same directory as
FILE-NAME.
For the use of PREFIX see that function.
This won't always work; it will fail if the source module
refers to relative paths.
"
(unless (stringp file-name)
(error "Invalid file-name"))
(or prefix
(setq prefix "flymake"))
(let* ((name (concat
(file-name-nondirectory
(file-name-sans-extension file-name))
"_" prefix))
(ext (concat "." (file-name-extension file-name)))
(temp-name (make-temp-file name nil ext))
)
(flymake-log 3 "create-temp-intemp: file=%s temp=%s" file-name temp-name)
temp-name))
(defun cheeso-php-flymake-get-cmdline (source base-dir)
"Gets the cmd line for running a flymake session in a PHP buffer.
This gets called by flymake itself."
(list "c:\Progra~2\PHP\v5.3\php.exe"
(list "-f" source "-l")))
(defun cheeso-php-flymake-init ()
"initialize flymake for php"
(let ((create-temp-f 'cheeso-flymake-create-temp-intemp)
;;(create-temp-f 'flymake-create-temp-inplace)
(use-relative-base-dir t)
(use-relative-source t)
(get-cmdline-f 'cheeso-php-flymake-get-cmdline)
args
temp-source-file-name)
(setq temp-source-file-name (flymake-init-create-temp-buffer-copy create-temp-f)
args (flymake-get-syntax-check-program-args
temp-source-file-name "."
use-relative-base-dir use-relative-source
get-cmdline-f))
args))
(defun cheeso-php-flymake-cleanup ()
)
(eval-after-load "flymake"
'(progn
;; 1. add a PHP entry to the flymake-allowed-file-name-masks
(let* ((key "\.php\'")
(phpentry (assoc key flymake-allowed-file-name-masks)))
(if phpentry
(setcdr phpentry '(cheeso-php-flymake-init cheeso-php-flymake-cleanup))
(add-to-list
'flymake-allowed-file-name-masks
(list key 'cheeso-php-flymake-init 'cheeso-php-flymake-cleanup))))))
Комментарии:
1. Большое спасибо за это. Сейчас я в отпуске, но когда вернусь, обязательно попробую!