在我的 shell 环境中,我有别名和自定义函数。当我在 emacs 实例中(我总是使用emacs -nw
)并执行 shell 命令(M-!
)时,我无法使用它们。这是有道理的,因为我想它会启动它自己的子外壳来执行这些操作......但是有没有办法(可能在我的.emacs
)中让它工作?也许即使它涉及在执行任何给定的 shell 命令之前默认采购一个环境?
6 回答
以下是我对我认为是相关问题的评论:
我认为M-x shell-command和M-x compile都通过调用进程在劣质 shell 中执行命令。在您的 .emacs 中尝试以下操作(或仅评估):
(setq shell-file-name "bash")
(setq shell-command-switch "-ic")
我注意到,在对上述内容进行评估之后,会选择 .bashrc 别名供M-xshell-command 和M-xcompile 使用,即
M-x编译RET your_alias RET
然后应该工作。
我的环境:Emacs 24.1(预测试 rc1),OSX 10.7.3
阅读http://www.gnu.org/software/bash/manual/bashref.html#Bash-Startup-Files
对于非交互式 shell,唯一的来源文件是 BASH_ENV 环境变量的值。您调用 emacs 就像BASH_ENV=~/.bashrc emacs
emacs是否将 bash 用于 shell 命令一样——某些程序专门使用“/bin/sh”
要在按照https://stackoverflow.com/a/12228646/8869495中描述的技术执行命令之前shell-command
进行阅读,而不会由于为整个 Emacs 会话定义而产生潜在的副作用,请在您的(或)文件中尝试此操作:~/.bashrc
$BASH_ENV
~/.emacs.d/init.el
.emacs
;; I want M-! (shell-command) to pick up my aliases and so run .bashrc:
(setq shell-file-name "bash-for-emacs.sh") ; Does this: BASH_ENV="~/.bashrc" exec bash "$@"
(setq shell-command-switch "-c")
如第二行中的注释所述,还安装(在您的$PATH
)一个名为的脚本bash-for-emacs.sh
,其中包含:
#!/bin/bash
BASH_ENV="~/.bashrc" exec bash "$@"
请注意,您~/.bashrc
可能需要更改以定义非交互式别名,即使[ -z "$PS1" ]
是 true(这表示非交互式 shell)。这就是我为自己的环境(例如)采用的方法,位于https://github.com/jcburley/UnixHome。
此外,这假设您想像我一样使用 Bash 作为 Emacs 生成的 shell。
我们需要在非交互式 shell 中启用别名扩展,最好仅在从 emacs 调用它们时(以避免在我们运行其他 shell 时造成细微差异)。对我有用的是创建两个文件: ~/.alias 有我所有的别名,例如
alias python python27
和 ~/.aliasExpand 有
source ~/.alias
shopt -s expand_aliases
当然,我也将 .bashrc 中的所有别名替换为
source ~/.alias
最后,我将其添加到我的 .emacs 中:
(setenv "BASH_ENV" "~/.aliasExpand")
我尝试了 Keith Flower 的解决方案(使贝壳交互),我得到了
bash:无法设置终端进程组(-1):设备 bash 的 ioctl 不合适:此 shell 中没有作业控制
请注意,我是通过 Glenn Jackman 和 Nicholas Dudebout 的提示得到的。
如果您愿意冒险让所有 shell 都具有别名扩展,并且不介意为每个 emacs shell 运行所有 .bashrc,则可以将其简化为添加
shopt -s expand_aliases
到你的 .bashrc 和
(setenv "BASH_ENV" "~/.bashrc")
到你的 .emacs
直接设置shell-command-switch
会大大shell-command
增加速度(如果您使用许多(ba|z)sh
插件),它由各种非交互式函数调用,如shell-command-to-string
, eshell-remote-command
,... 以及其他函数对其的大量调用,所有这些都不需要.bashrc
或.zshrc
例如,在我的机器上(也可能是你的机器):
(benchmark-elapse (let ((shell-command-switch "-c")) (shell-command "")))
0.005170422
(benchmark-elapse (let ((shell-command-switch "-ic")) (shell-command "")))
0.242628824
;; Empty ~/.zshrc: 0.168341049
shell-command
因此,我们应该选择找到一种仅在交互调用时才使用交互 shell 的方法
;;;###autoload
(defun my-shell-command-interactive-a (fn &rest args)
"Use interactive shell for `shell-command' when invoked interactively.
Setting the \"-i\" switch all the time will significantly slow
down `shell-command' because there may too many files to source."
(let ((shell-command-switch (if (called-interactively-p 'interactive)
;; Replace the first "-"
(replace-regexp-in-string
"\\(-\\).*\\'"
"-i"
shell-command-switch
nil
nil
1)
shell-command-switch)))
(apply fn args)))
(dolist (cmd '(shell-command async-shell-command))
(advice-add cmd :around #'my-shell-command-interactive-a))
将别名和函数放在 中.bashrc
,而不是.bash_profile
. 后者仅在登录 shell 中执行,前者在所有 shell 中执行。