Можно ли создать временный файл flymake во временном каталоге системы?
В настоящее время я использую следующий код для подключения 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, но с другими символическими ссылками это не происходит.
Как я могу исправить эту проблему?
ОБНОВИТЬ
Я сделал некоторую отладку, и теперь я вижу, что он не передает правильный путь в качестве аргумента. Ему нужен еще один родительский каталог, вставленный в путь, чтобы заставить его работать, что заставляет меня думать, что он испорчен из-за символических ссылок.
Вот пример сеанса оболочки, чтобы показать, что я имею в виду. Я делаю это из правильного относительного каталога:
$ 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
от local-file
в temp-file
так как local-file
был сумасшедший относительный путь, который я не хотел. Почему автор этого фрагмента использовал local-file
на первом месте?
Спасибо Райан
4 ответа
Для меня я решил изменить пользовательский скрипт /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
У меня нет прямого решения вопроса о Пайфлейкс, но вот что-то похожее для вас.
Мне не понравилось, как 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))))
Документация вроде этого не совсем точна, но код - это документация, и, насколько я могу судить, подпрограмма init должна возвращать командную строку для запуска проверки синтаксиса. Он отформатирован как список из 2 элементов, команда - это команда для запуска, а cadr - это список аргументов. В моем примере возвращаемое значение выглядит так:
("csc.exe" ("/t:module" "/nologo" "nameOfFileToCheck.cs"))
Подпрограмма init, которая возвращает эту командную строку, копирует существующий буфер во временный файл, используя встроенную копию flymake fn, а затем использует имя временного файла для проверки. Таким образом, если имя файла буфера - "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.
В любом случае... То, что вы видите, это то, что init fn создает временный файл, а затем возвращает аргументы. Призыв к flymake-get-syntax-check-program-args
на самом деле сводится к вызову в get-cmdline-f
который в случае C# является csharp-flymake-get-cmdline
, Почему все это наслоение и косвенность? Я не знаю; Вот как мухи.
В специфичной для C# очистке fn я просто проверяю файлы "product" из проверки синтаксиса и удаляю их, а затем также чередую flymake-simple-cleanup
, чтобы удалить временный файл *_flymake.cs, который был создан.
Возможно, ваш вложенный путь к каталогу как-то связан с use-relative-base-dir
а также use-relative-source
аргументы, которые flymake использует в своей собственной процедуре инициализации по умолчанию, которая, я думаю, flymake-simple-make-init-impl
,
Функция make-temp-file
использует переменную temporary-file-directory
так что, возможно, вы можете попробовать установить temporary-file-directory
что-то еще, чтобы решить вашу проблему.
Это то, что я использую для PHP на Windows. Он использует make-temp-file
предложение от Трея. Он также явно устанавливает функции init и cleanup для 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))))))