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

问题描述:

我目前使用下面的代码挂钩flymake和Pyflakes在Emacs:可以在系统的临时目录中创建flymake的临时文件吗?

(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目录中的一个目录,但这不会发生在其他类似的符号链接中。

我该如何解决这个问题?

UPDATE

我做了一些调试,现在我看到它没有经过正确的路径作为参数。它需要在路径中插入另一个父目录才能使其工作,这使得我认为它由于符号链接而变得混乱。

下面是一个例子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))))) 

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

感谢, 瑞安

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

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

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

初始化子程序返回此命令行复制现有缓冲到一个临时文件,使用flymake的内置复制FN,然后使用临时文件的名称要检查的东西。因此,如果缓存文件名是“source.cs”,从初始化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在它自己的默认init例程中使用的use-relative-base-diruse-relative-source参数有关,我认为它是flymake-simple-make-init-impl

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

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

非常感谢。我现在正在度假,但是当我回来的时候我会尝试一下! – 2011-09-16 12:21:51

对于我来说,我已经通过修改用户脚本在/ 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