【问题标题】:Can flymake's temporary file be created in the system's temporary directory?flymake的临时文件可以在系统临时目录下创建吗?
【发布时间】:2011-04-26 17:06:26
【问题描述】:

我目前正在使用以下代码在 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 是我不想要的疯狂的相对路径。为什么那个 sn-p 的作者首先使用local-file

谢谢, 瑞恩

【问题讨论】:

    标签: python emacs flymake pyflakes


    【解决方案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 问题的方法,但这里有一些类似的东西适合你。

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

      (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 的调用实际上归结为对get-cmdline-f 的调用,在C# 的情况下是csharp-flymake-get-cmdline。为什么所有这些分层和间接?我不知道; flymake就是这样。

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

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

      【讨论】:

        【解决方案3】:

        函数make-temp-file 使用变量temporary-file-directory,所以也许您可以尝试将temporary-file-directory 设置为其他值来解决您的问题。

        【讨论】:

          【解决方案4】:

          这是我在 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))))))
          

          【讨论】:

          • 非常感谢。我现在正在度假,但当我回来时,我会试试看!
          猜你喜欢
          • 1970-01-01
          • 2013-02-02
          • 1970-01-01
          • 2012-03-31
          • 1970-01-01
          • 1970-01-01
          • 2018-02-24
          • 2010-11-10
          相关资源
          最近更新 更多