我目前正在使用以下代码在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
?
谢谢, 莱恩
答案 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-dir
和use-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))))))