可以在系统的临时目录中创建flymake的临时文件吗?

时间:2011-04-26 17:06:27

标签: python emacs flymake pyflakes

我目前正在使用以下代码在emacs中连接flymake和Pyflakes:

(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目录设置。

我不记得最近为Ubuntu更新了emacs,并且想不出任何可能导致这个问题陷入困境的事情(.emacs文件是版本化的)。

我能想到的唯一问题是,这是一个嵌套到目录中的嵌套目录,这个目录符合我〜/ Dropbox目录中的一个目录,但这种情况不会以类似的方式发生在其他符号链接中。

如何解决此问题?

更新

我已经做了一些调试,现在我发现它没有传递正确的路径作为参数。它需要在路径中插入一个更多的父目录才能使其工作,这让我觉得它因为符号链接而变得混乱。

这是一个示例shell会话来显示我的意思。我是从正确的相对目录中执行此操作的:

$ 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 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

我没有直接解决pyflakes问题,但这里有类似的东西。

我不喜欢在flymake中处理C#的方式,因此我修改了flymake-allowed-file-name-masks中的C#条目以引用不同的init和cleanup例程,使用以下代码:

(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元素列表,car是要运行的命令,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))

我在2个不同的函数中实现它,只是遵循我在flymake.el中看到的模式。

无论如何......你可以看到init fn创建临时文件然后返回参数。对flymake-get-syntax-check-program-args的调用实际上归结为对get-cmdline-f的调用,在C#的情况下调用csharp-flymake-get-cmdline。为什么所有这些分层和间接?我不知道;这就是flymake的方式。

在C#特定清理fn中,我只检查语法检查中的任何“产品”文件并删除它们,然后链接到flymake-simple-cleanup,删除* _flymake.cs临时文件创建。

也许你的嵌套dir路径与flymake在其自己的默认init例程中使用的use-relative-base-diruse-relative-source参数有关,我认为这是flymake-simple-make-init-impl

答案 2 :(得分:0)

函数make-temp-file使用变量temporary-file-directory,因此您可以尝试将temporary-file-directory设置为其他内容以解决问题。

答案 3 :(得分:0)

这是我在Windows上用于PHP的内容。它使用了Trey的make-temp-file建议。它还显式地为我想要的东西设置PHP的init和cleanup函数。对于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))))))