5

我目前正在使用以下代码在 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)))))

在最后一部分中,我不得不将参数更改为listfrom local-fileto,temp-file因为这local-file是我不想要的疯狂相对路径。为什么该片段的作者local-file首先使用该片段?

谢谢,瑞安

4

4 回答 4

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
于 2013-03-07T22:16:34.203 回答
0

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

于 2011-04-26T22:23:52.570 回答
0

这是我在 Windows 上用于 PHP 的。它使用了make-temp-fileTrey 的建议。它还明确地将 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))))))
于 2011-09-15T13:58:53.530 回答
0

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

我不喜欢在 flymake 中如何处理 C#,所以我修改了 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 元素列表,car 是要运行的命令,而 cadr 本身就是一个参数列表。在我的示例中,返回值是这样的:

("csc.exe" ("/t:module" "/nologo" "nameOfFileToCheck.cs"))  

返回此命令行的 init 例程使用 flymake 的内置 copy 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实际上归结为调用 into get-cmdline-f,在 C# 的情况下是csharp-flymake-get-cmdline. 为什么所有这些分层和间接?我不知道; flymake就是这样。

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

也许您的嵌套目录路径与flymake 在其自己的默认初始化例程中使用的use-relative-base-dir和参数有关,我认为是.use-relative-sourceflymake-simple-make-init-impl

于 2011-04-26T17:53:00.880 回答