我想要运行一个c++程序,因为需要输入,所以不能后台执行。因此我需要暂时切换到shell里面去运行这个程序。 那么我可以在二者间快速切换吗?如下面这个流程:
按下快捷键切换到shell并自动编译运行程序 -> 手动输入数据 -> 程序运行完输出结果 -> 按下空格(或者其他键)自动返回
这套操作在vim中可以借助 ! 轻松完成,在emacs中可以做到吗?
我想要运行一个c++程序,因为需要输入,所以不能后台执行。因此我需要暂时切换到shell里面去运行这个程序。 那么我可以在二者间快速切换吗?如下面这个流程:
按下快捷键切换到shell并自动编译运行程序 -> 手动输入数据 -> 程序运行完输出结果 -> 按下空格(或者其他键)自动返回
这套操作在vim中可以借助 ! 轻松完成,在emacs中可以做到吗?
貌似可以通过M-&实现 但是这个会弹出一个新的buffer,自动切换到这个bufferne?
你好像用的是spacemacs? 自带的有两个函数SPC ! (shell-command)
and SPC ' (spacemacs/default-pop-shell)
。基本能满足我的需求了。虽然我还是用iterm的多,支持比较全,bug比较少。
这个函数copy过来的你也可以考虑。
;; "http://xuchunyang.me/Opening-iTerm-From-an-Emacs-Buffer/"
(defuniterm-shell-command (command &optional prefix)
"cd to `default-directory' then run COMMAND in iTerm.
With PREFIX, cd to project root."
(interactive (list (read-shell-command
"iTerm Shell Command: ")
current-prefix-arg))
(let* ((dir (if prefix (ztlevi/git-project-root)
default-directory))
;; if COMMAND is empty, just change directory
(cmd (format "cd %s ;%s" dir command)))
(do-applescript
(format
"
tell application \"iTerm2\"
activate
set _session to current session of current window
tell _session
set command to get the clipboard
write text \"%s\"
end tell
end tell
" cmd))))
这两个也是,切换的话直接Alt(command)-tab不也可以么。
(defun ztlevi/open-terminal-in-project-root ()
(interactive)
(setq-local projectile-project-root-path (if (ignore-errors (projectile-project-root))
(projectile-project-root) "."))
(cond
((string-equal system-type "darwin") (shell-command (concat "open -a iTerm " projectile-project-root-path)))
((string-equal system-type "gnu/linux")
(let (
(process-connection-type nil)
(openFileProgram (if (file-exists-p "/usr/bin/konsole")
"/usr/bin/konsole"
"/usr/bin/gnome-terminal")))
(start-process "" nil openFileProgram (projectile-project-root))))))
(defun ztlevi/open-terminal-in-current-dir ()
(interactive)
(cond
((string-equal system-type "darwin") (shell-command (concat "open -a iTerm .")))
((string-equal system-type "gnu/linux")
(let (
(process-connection-type nil)
(openFileProgram (if (file-exists-p "/usr/bin/konsole")
"/usr/bin/konsole"
"/usr/bin/gnome-terminal")))
(start-process "" nil openFileProgram ".")))))
shell里加个key或者命令,执行emacsclient -n
之类的(我发现这个后面不加文件名不让执行……)
multi term? c-z fg?
能,但 Emacs 的 Terminal Emulator 体验不好,没法与 Vim 的相提并论,更没法跟真正的终端模拟器相比。
下面介绍一个用 Term 解决的思路,灵感来自于 Eshell 的 eshell-visual-commands
。
示例程序:
/* foo.c */
#include <stdio.h>
int main(void) {
puts("Enter a char:");
putchar(getchar());
return 0;
}
在 Term 里运行一个 Shell 命令(如果只想运行一个程序,如 Vim,用 M-x term vim
也行):
(defun term-shell-command (command)
(interactive
(list (read-shell-command "Terminal Shell command: ")))
(let ((buffer (generate-new-buffer "*Terminal Shell Command*")))
(switch-to-buffer buffer)
(term-mode)
(term-exec buffer "bash" "bash" nil nil)
(term-send-string (get-buffer-process buffer) (concat command "\n"))
(term-char-mode)))
编译、运行这只示例程序:
M-x term-shell-command cc foo.c && ./a.out ; exit
至于「结束后自动返回」很容易实现,可参考 Eshell 的 eshell-destroy-buffer-when-process-dies
。
(假设 Emacs 运行在终端里)一个方法是:
M-: (suspend-emacs "cc foo.c && ./a.out ; read ; fg")
我写了一个这样的函数,差不多能解决我的问题了
(defun my/run ()
(interactive)
(let ((file (file-name-nondirectory buffer-file-name)))
(async-shell-command
(concat "time ./" (file-name-sans-extension file)))
(switch-to-buffer-other-window "*Async Shell Command*")
)
)
这个不错
我用的不是 Spacemacs
对于(spacemacs/default-pop-shell)
我有点感兴趣
用shell-pop
这个包实现了
长见识了,我都不知道有这个东西!
You can try eshell-exec-visual. as below.
(setq eshell-destroy-buffer-when-process-dies t)
(eshell-exec-visual "top")
(eshell-exec-visual "/bin/sh" "-c" "{ ls -l ; sleep 2 ; }")
感谢 @amosbird 又查了一下,我还找到了这个东西:
文档中对于compile
命令的展示是(compile COMMAND &optional COMINT)
只要按C-u M-x compile RET
即可进入 compilation 的 comint-mode
或者调用函数时使用 (compile "COMMAND" t)
注意compile的命令要更改,加上运行程序的部分
附上最后的代码,我将其绑定到了super-r
上
(defun roife/compile()
"Compile codes"
(interactive)
(if (file-exists-p "Makefile")
(compile "make -k")
(when (string= (file-name-extension (file-name-nondirectory buffer-file-name)) "cpp")
(compile
(let ((file (file-name-nondirectory buffer-file-name)))
(format "clang++ %s -Wall -g -o %s && time ./%s"
file
(file-name-sans-extension file)
(file-name-sans-extension file))) t)
(switch-to-buffer-other-window "*compilation*")
(end-of-buffer)
)))
这段代码在我这里报错了Symbol’s function definition is void: eshell-exec-visual Mark set
You should enable eshell first.
(require 'eshell)
加上了,仍然是这个错误