eshell 并不是一个真正的 shell,它只能在 emacs 上运行。尽管和 bash、zsh 相比,它的功能很有限,但对大多数人来说已经足够了。此外,由于 eshell 是 由 elisp 编写的,所以它还有其他 shell 所没有的一些特点,比如更强的扩展性和可以使用 emacs 函数。
1. alias
eshell 添加 alias 的方法和 bash 几乎是相同的,并且默认保存在 ~/.eshell/alias。不同的是,eshell 中既可以使用外部命令,也可以使用 emacs 函数,比如:
alias ll ls -al $*
alias dl dpkg -l $1
alias e find-file $1
alias v view-file $1
alias sai sudo aptitude install $1
2. histroy
bash 中有很多变量控制命令历史,比如: HISTCONTROL、HISTIGNORE 和 HISTFILESIZE。和它们相对应的 eshell 变量是 eshell-hist-ignoredups、eshell-input-filter和 eshell-history-size。eshell-hist-ignoredups 决定是否忽视重复的命令,eshell-history-size 控制历史文件的大小。 eshell-input-filter 的值其实是一个函数,我们每输入一条命令,这条命令会 作为参数传递给 eshell-input-filter,如果返回 t,这条命令才会被保存到历史中。它默认只过滤空白命令,如果要过滤 ls、cd、clear,可以这样修改:
(defvar eshell-histignore
'("\\`\\(ls\\|ll\\|cd\\|clear\\)\\'"
"\\`\\s-*\\'"))
(setq eshell-input-filter
#'(lambda (str)
(let ((regex eshell-histignore))
(not
(catch 'break
(while regex
(if (string-match (pop regex) str)
(throw 'break t))))))))
3. completion
zsh 的补全据说非常强大,安装 bash-completion 后 bash 的补全也变得不错。eshell 的补全虽然没有前两者丰富,但却很灵活,自定义也很简单。eshell 的补全依靠 pcomplete,以定义上面的 sai 的补全函数为例。
首先获取当前符合名称的软件包的列表:
(defun pcmpl-package-cache (name)
"return a list of packages in cache"
(unless (equal name "")
(split-string (shell-command-to-string
(concat "apt-cache pkgnames " name " 2> /dev/null")))))
其次定义 sai 的补全函数:
(defun pcomplete/sai ()
"completion for `sai'"
(while
(pcomplete-here
(pcmpl-package-cache (pcomplete-arg 'last)))))
现在在 eshell 里就可以按 TAB 对 sai 进行软件包名字的补全了。
eshell 的一些补全选项:
(setq eshell-cmpl-ignore-case t ; 补全时忽略大小写
eshell-cmpl-cycle-completions nil) ; 不要循环补全
4. cd path
在 bash 里我们可以通过 cd - 回到上一个目录,eshell 同样可以。不仅如此,cd -<number>会回到倒数第 number个目录。cd =<REGEXP> 会回到上一个满足 REGEXP 的目录。zsh 中有对路径的别名,cd~X可以进入 ~X 所指代的目录,当目录比较深或很常用时非常方便。这在 eshell 也可以方便地实现。
首先定义一个别名与路径的关联表:
(defvar eshell-path-alist
`(("e" . ,user-emacs-directory)
("t" . "/tmp/")
("document" . "~/Documents/")
("download" . "~/Downloads/")
("v" . "~/video/")
("p" . "~/Pictures/")))
现在直接修改ehsell/cd是可行的,但另外定义一个函数更方便:
(defun eshell/d (arg)
(let ((path (cdr (assoc arg eshell-path-alist))))
(eshell/cd path)))
eshell /d 的补全函数也很容易:
(defun pcomplete/d ()
(pcomplete-here
(mapcar #'car eshell-path-alist)))
现在直接输入 d t 就可以进入 /tmp
来源:这里