在远程主机上评估Emacs Python模式中的缓冲区
我正在使用emacs23和tramp来修改远程主机上的python脚本。 我发现当我在emacs中启动python解释器时,它实际上是在远程主机上启动python。
我的问题是,当我尝试通过按C-c C-c来调用python-send-buffer时,出现了错误:
追踪信息(最近的调用在最前面): 文件 "", 第 1 行, 在 ? 导入错误:没有名为emacs的模块
追踪信息(最近的调用在最前面): 文件 "", 第 1 行, 在 ? 名称错误:'emacs'没有定义
老实说,我不太明白这里发生了什么。有没有办法让我配置emacs,以便我可以在远程主机上执行这个缓冲区的内容?
非常感谢。
编辑:我按照eichin的建议重新实现了python-send-region。请看我下面的回答。
2 个回答
我现在正在尝试把我未注册的问题和这个账户合并,合并后我就可以接受eichin的回答,并编辑我的帖子,把我的解决方案加进去。
我按照eichin的建议,把emacs2.py、emacs3.py和emacs.py这几个文件复制到了远程主机上,并把它们的目录添加到了tramp-remote-process-environment变量中的PYTHONPATH里。
接着,我在我的.emacs文件里重新实现了python-send-buffer这个功能。
(require 'python)
(defun python-send-region (start end)
"Send the region to the inferior Python process."
(interactive "r")
(let* ((loc_name)
(f (if (file-remote-p default-directory)
(let* ((con (tramp-dissect-file-name default-directory)))
(setq loc_name (tramp-make-tramp-temp-file con))
(concat "/"
(tramp-file-name-method con) ":"
(tramp-file-name-user con) "@"
(tramp-file-name-host con) ":"
loc_name
))
(setq loc_name (make-temp-file "py"))))
(command (format "emacs.eexecfile(%S)" loc_name))
(orig-start (copy-marker start)))
(save-excursion
(let ((curbuf (current-buffer))
(tempbuf (get-buffer-create "*python_temp*")))
(set-buffer tempbuf)
(delete-region (point-min) (point-max))
(insert-buffer-substring curbuf start end)
(python-mode)
(when (save-excursion
(goto-char (point-min))
(/= 0 (current-indentation)))
(python-shift-left (point-min) (point-max)))
(write-region nil nil f nil 'nomsg))
(python-send-command command)
(with-current-buffer (process-buffer (python-proc))
;; Tell compile.el to redirect error locations in file `f' to
;; positions past marker `orig-start'. It has to be done *after*
;; `python-send-command''s call to `compilation-forget-errors'.
(compilation-fake-loc orig-start f)))
))
基本上,我是把选中的部分复制到一个新的缓冲区,调整一下缩进,然后把它写入一个临时文件,这个临时文件是用tramp-make-tramp-temp-file或者make-temp-file创建的,具体用哪个取决于访问的文件是远程的还是本地的。
我在使用tramp-handle-write-region的时候遇到了一些问题,它似乎不接受字符串作为第一个参数,所以我先在一个单独的缓冲区里完成了所有的格式调整。
如果代码还有其他问题,请告诉我,不过这是我第一次尝试elisp编程,所以请多多包涵。
简短回答:没有写一些缺失的elisp代码是做不到的。
详细说说:在 python.el
文件中,run-python
会把 data-directory
(在我的Ubuntu 10.10系统上是 /usr/share/emacs/23.1/etc/
)添加到 $PYTHONPATH
中,这样它就能找到 emacs.py
(这是本地emacs版本提供的)。然后它会执行 (python-send-string "import emacs")
,希望能正常工作……
看起来 tramp
使用的 defadvice
包装器实际上并没有传递 PYTHONPATH
,所以即使你在远程系统上有匹配的emacs版本,这也不起作用。
如果你输入 M-x customize-variable RET tramp-remote-process-environment RET
,然后点击其中一个 INS
按钮,添加 PYTHONPATH=/usr/share/emacs/23.1/etc
,再点击 STATE
并设置为“当前会话”(只是为了测试,或者如果对你有效就选择“保存为未来会话”),那么它就 差不多 能工作了——抱怨消失了,因为远程的python现在可以找到远程的 emacs.py
。如果你现在回到最初的问题,使用 python-send-buffer
,你会遇到另一个错误:No such file or directory: '/tmp/py24574XdA'
,因为 python-mode
会把内容放到一个临时文件中,然后告诉python子进程去加载这个文件。
你需要修改 python-send-region
(其他函数会调用它),特别是它使用 make-temp-file
的方式,让它能识别tramp——实际上还有一个 tramp-make-tramp-temp-file
,你可以在这个基础上进行修改。(如果你做到了,请务必分享一下……)