从Emacs运行交互式Python脚本
我对vim还算熟练,但我的朋友们跟我说了很多关于emacs的好处,所以我决定试试这个编辑器,尤其是在听说了它的“evil模式”之后……
现在,我正在写一个需要用户输入的python脚本(这是cmd.Cmd的一个子类)。在vim里,如果我想试一下这个脚本,我可以简单地输入 :!python %
,然后就可以和我的脚本互动,直到它退出为止。在emacs里,我试着用 M-! python script.py
,这确实会在一个新的窗口中运行脚本,但按下回车键似乎没有传回脚本,而是被emacs的窗口捕获了。我还试着查看python-mode的 C-c C-c
,但这个命令会在一个临时目录中运行脚本,而我只是想在 (pwd)
这个目录下运行它。
那么,有没有什么标准的方法可以做到这一点呢?
6 个回答
我现在使用这些钩子来定义我的编译命令:
(defun convert-filename-to-executable (file)
(if (eq system-type 'windows-nt)
(concat (file-name-sans-extension file) ".exe")
;; linux
(concat "./" (file-name-sans-extension file))))
(add-hook 'c++-mode-hook
(lambda ()
(unless (file-exists-p "Makefile")
(set (make-local-variable 'compile-command)
(let* ((file (file-name-nondirectory buffer- file-name))
(executable (convert-filename-to-executable file)))
(concat "g++ -g -Wall -o "
(file-name-sans-extension file)
" "
file
" && "
executable))))))
(add-hook 'c-mode-hook
(lambda ()
(unless (file-exists-p "Makefile")
(set (make-local-variable 'compile-command)
(let* ((file (file-name-nondirectory buffer-file-name))
(executable (convert-filename-to-executable file)))
(concat "gcc -g -ansi -Wall -Wpedantic -Wextra -Wc++-compat -Wconversion -o "
(file-name-sans-extension file)
" "
file
" && "
executable))))))
(add-hook 'python-mode-hook
(lambda ()
(set (make-local-variable 'compile-command)
(concat "python " buffer-file-name))))
(add-hook 'perl-mode-hook
(lambda ()
(set (make-local-variable 'compile-command)
(concat "python " buffer-file-name))))
还有这个 lambda 函数,用来互动地调用编译功能:
(global-set-key (kbd "<f4>") (lambda () (interactive) (setq current-prefix-arg '(4)) (call-interactively 'compile)))
一个按钮统治所有!
如果你按下 F4(在我的情况下,你可以在 lambda 中为 global-set-key
设置这个按键),那么在 C++ 或 C 模式下打开的文件会被编译,而在 Python 或 Perl 模式下的文件会被运行(以互动方式)
我喜欢用Emacs里的“编译”命令来测试或运行我的Python脚本。你可以按 M
-X
然后输入 compileRET
,这时会出现默认的“make -k”命令。如果你把这个命令删掉,换成你自己脚本的命令(包括选项),那么之后每次再用“编译”时,它会自动记住你输入的新命令。你脚本的所有输出都会显示在编译缓冲区里。这样比在终端里运行要好,因为每次调用时都有一个干净的界面,方便查找信息。如果你在运行之前忘记保存脚本,编译命令会问你是否要保存文件。
不过,当你重启Emacs时,你之前输入的命令会丢失。但是你可以在Python脚本的底部加上一段代码(其实是Python的注释),让Emacs为这个脚本的缓冲区设置编译命令:
# Trigger emacs to run this script using the "compile" command
# ;;; Local Variables: ***
# ;;; compile-command: "my_cool_script.py --complicated_option some_filename.txt" ***
# ;;; end: ***
这样对于那些调用比较复杂的脚本来说就很方便了。注意:Python的注释符号‘#’可以让这段代码不被Python解释器执行,而Emacs会在打开文件时查看每个文件的底部,从而知道设置这些变量。
我希望能像编译C代码时那样,直接跳到Python脚本中的“编译错误”位置,但我懒得去写Emacs的正则表达式来实现这个功能。也许这可以成为Stack Overflow上的另一个好问题!
我对canonical不太了解,但如果我需要和一个脚本互动,我会按下 M-x,然后输入 shell
,再按 RET,这样就可以从那里运行脚本了。
还有一个更强大的功能叫 M-x terminal-emulator
,它可以模拟终端,不仅仅是处理一些简单的命令。