Может ли временный файл flymake быть создан во временном каталоге системы?

#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. Большое спасибо за это. Сейчас я в отпуске, но когда вернусь, обязательно попробую!