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

Rya*_*kel 5 python emacs flymake pyflakes

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

(defun flymake-create-temp-in-system-tempdir (filename prefix)
  (make-temp-file (or prefix "flymake")))
Run Code Online (Sandbox Code Playgroud)

然后我将此功能传递给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)
Run Code Online (Sandbox Code Playgroud)

为什么flymake会将看似错误的文件名传递给pyflakes?我希望它传递类似"/ tmp/efe234234"的东西,我没有修改任何tmp目录设置.

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

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

我该如何解决这个问题?

UPDATE

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

这是一个示例shell会话,以显示我的意思.我是从正确的相对目录中这样做的:

$ pyflakes ../../../../../tmp/flymake13382xHi 
../../../../../tmp/flymake13382xHi: No such file or directory
Run Code Online (Sandbox Code Playgroud)

这就是flymake试图运行的命令.如果我改变它:

$ pyflakes ../../../../../../tmp/flymake13382xHi
Run Code Online (Sandbox Code Playgroud)

我没有输出(如预期的那样).注意路径中的额外"..".

我如何让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)))))
Run Code Online (Sandbox Code Playgroud)

在最后一部分,我不得不参数来改变listlocal-filetemp-file,因为local-file是我不想疯狂的相对路径.为什么该片段的作者local-file首先使用?

谢谢,瑞恩

Che*_*eso 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))))
Run Code Online (Sandbox Code Playgroud)

文档在这些东西上有点参差不齐,但代码就是文档,据我所知,init 例程应该返回命令行以进行语法检查运行。它的格式为 2 元素列表,car 是要运行的命令,cadr 本身是参数列表。在我的例子中,返回值是这样的:

("csc.exe" ("/t:module" "/nologo" "nameOfFileToCheck.cs"))  
Run Code Online (Sandbox Code Playgroud)

返回此命令行的 init 例程使用 Flymake 的内置 copy fn 将现有缓冲区复制到临时文件中,然后使用临时文件的名称作为要检查的内容。因此,如果缓冲区文件名是“source.cs”,则从 init fn 返回的实际值是

("csc.exe" ("/t:module" "/nologo" "source_flymake.cs"))  
Run Code Online (Sandbox Code Playgroud)

代码如下所示:

(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))
Run Code Online (Sandbox Code Playgroud)

我用两个不同的函数实现了它,只是为了遵循我在 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-dir和参数有关,我认为是.use-relative-sourceflymake-simple-make-init-impl