昨天在翻the art of command line 的时候偶然看到贡献者里面有熟悉的@xuchunyang 同学的头像,就点进去翻了一下,发现了这篇博客 ,通过emacsclinet --eval
来把当前shell的上下文放到emacs中继续浏览。
问题是:博主是通过mac下的open
切换到emacs的,我实验后发现博客里的magit
是会直接跳到emacs的,dired
则不能(windows+cygwin),这个区别是什么原因呢?(虽然我通过autohotkey实现了切换的功能,但是能修改eval的elisp来切换的话更好)
附上我自己加入的两段脚本,很简单,如果有和我一样shell和emacs刚入门的同学可以参考:
windows下使用autohotkey实现切换窗口(在autohotkey安装目录下生成一个switch-to-emacs.ahk文件,然后执行它。我翻了好久没找到AutoHotkey.exe怎么执行inline的脚本,也没找到怎么在shell下不生成文件就把stdin给AutoHotkey这样只接受文件名的命令):
open-emacs() {
local exepath=`which AutoHotkey`
# must quote exepath in case there's space in it
local ahkpath=$(cygpath -m '"'exepath'"' | sed 's/AutoHotkey\(\\.exe\)\?//g')
echo 'WinActivate, ahk_class Emacs' > $ahkpath'switch-to-emacs.ahk'
AutoHotkey $ahkpath'switch-to-emacs.ahk'
}
在emacs中生成一条cd命令给shell,末尾带个换行符,抄袭自spacemacs/show-and-copy-buffer-filename
:
(defun make-cd-for-terminal ()
"make a cd command for terminal, targeting current buffer file's dir"
(interactive)
(let ((file-name (buffer-file-name)))
(if file-name
(message (kill-new (format "cd %s \n" (file-name-directory file-name))))
(error "Buffer not visiting a file"))))
1 个赞
听起来确实挺奇怪的,dired 和 magit 并没有什么不同,都只是让 Emacs 执行的命令而已,或许这不是问题的根源,你可以试试随便别的什么命令,比如 (emacs-version)
等,看看是否正常。
从 Shell 中(终端中)切换到 Emacs 窗口,Mac 下最简单,Windows 下楼主也提了,Linux 下,我是用 xdotool
实现的,在 Ubuntu 16.04 默认的 Unity 下有效,但有可能不适用于其它的发行版/窗口管理器
xdotool windowactivate --sync $( xdotool search --class Emacs | tail -1 )
目前我把相关的设置都放到了一个单独的文件里了,有些命令直接用的是 emacs --eval
其中的有些命令虽然不常用,但是第一次想到感觉挺有意思的
# calc 支持任意大的数(?)比如 2**10000
calc ()
{
emacs -Q --batch --eval "(message \"%s\" (calc-eval \"$1\"))"
}
elisp_repl ()
{
emacs --batch --eval '(while t (message "%s" (eval (read (read-string "> ")))))'
}
随便(emacs-version)
或者(message ...)
一下是不会切换窗口的,emacsclient打开文件是会切换窗口的,似乎跟它认为你需要在哪里观察命令结果有关。dired和magit的区别是,执行前emacs里有一个window的话,dired会在这个window里打开,magit会开第二个window。。
哦,我明白你什么意思了。其实原来
emacsclient --eval '(magit-status)'
是不会切换到 Emacs 窗口的,不然我压根就用不着用 open
了,刚刚我试了下,现在是可以直接就切换了。不过我也不清楚 magit-status
是如何做到的,有时间再看看它的代码。
找到了,是用 select-frame-set-input-focus
实现了
Display the buffer using `magit-display-buffer-function' and
then, unless `magit-display-buffer-noselect' is non-nil, select
the window which was used to display the buffer.
Also run the hooks `magit-pre-display-buffer-hook'
and `magit-post-display-buffer-hook'."
(with-current-buffer buffer
(run-hooks 'magit-pre-display-buffer-hook))
(let ((window (funcall magit-display-buffer-function buffer)))
(unless magit-display-buffer-noselect
(select-frame-set-input-focus
(window-frame
(select-window window)))))
(with-current-buffer buffer
(run-hooks 'magit-post-display-buffer-hook)))
(defun magit-display-buffer-traditional (buffer)
"Display BUFFER the way this has traditionally been done."
(display-buffer
buffer (if (and (derived-mode-p 'magit-mode)
(not (memq (with-current-buffer buffer major-mode)
这样的话,就用不着自己想办法用外部程序打开 Emacs 窗口了
(defun open-emacs-window ()
"打开 Emacs 窗口."
(select-frame-set-input-focus (selected-frame)))
~$ emacsclient --eval '(dired ".")' --eval '(open-emacs-window)'
~$ emacsclient --eval '(org-agenda-list)' --eval '(open-emacs-window)'
2 个赞