HOME

Eshell - The Emacs Shell

Table of Contents

1 命令 (Commands)

Eshell 命令大致分成两类

  • 外部命令,如 curl 和 git
  • Elisp 函数,可以分为
    • 专门为 Eshell 开发的命令,如 eshell/ls ,在 Eshell 中可以简单地以 ls 调用(在 Eshell 的手册中称为 "Built-ins commands",但其实也可以自己实现 eshell/foo )。
    • 其它的一般的 Elisp 函数,如 buffer-name ,在 Eshell 中以 buffer-name 调用

它们的执行顺序是

  1. Alias
  2. Eshell 命令
  3. Elisp 函数
  4. 外部命令

; && ||| (Pipe) 等也可正常使用。

2 展开 (Expansion)

2.1 Dollars Expansion

$var 变量 var 的值
$#var 变量 var 的值是的长度(先假设是序列)
$(lisp) (lisp) 代码的执行结果
${command} Eshell command 的执行输出
$var[hello] 变量 var 的值是一个 alist,键为 "hello" 的值

注 $() 和 ${} 也可以省去 $ 写出 () 和 {}

$ echo $(+ 1 2)
3

$ echo (+ 1 2)
3

但不省去的好处是可以嵌在 String 中使用

$ echo "1 + 2 = $(+ 1 2)"
1 + 2 = 3

$ echo "1 + 2 = (+ 1 2)"
1 + 2 = (+ 1 2)

2.1.1 TODO 扩展 $var[i] 有问题,需要问下

2.2 TODO 通配符 (Globbing)

通配符用于匹配文件的,Eshell 的使用类似于 Zsh 的。

Predicates 用来过滤文件,Modifiers 用来修改变量的值。

$ eshell-display-predicate-help
$ eshell-display-modifier-help

参考 Eschewing Zshell for Emacs Shell

ls ()
可执行文件
ls *(^/)
文件(排除目录)
for f in * { mv -v $f $f(:r) }
去掉所有文件的扩展名

3 重定向

除了用 >>> 重定向至文件外,Eshell 还支持重定向至 Emacs Buffer (#<buffer-name>)、Emacs Kill ring (/dev/kill) 和 clipboard (/dev/clip)。当从从定向至 Buffer 时,还可以使用 >>> ,它会把内容插入在 Point 处,而不是像 >> 那样插在 Buffer 的结尾处。

Eshell 不支持 < (Input Redirection)。

4 For 循环 (Loop)

$ for f in *(^/) { echo $f }

5 写 Eshell 命令

写一个 Eshell 命令就是写一个 Lisp 函数,比如 Eshell 命令 hello 对应于 Lisp 函数 eshell/hello

(defun eshell/hello ()
  "Hello World in Eshell."
  (eshell-print "Hello world")
  ;; Eshell also prints return value expect for nil
  nil)

5.1 解析命令行选项和参数

手动解析

(defun eshell/hello (&rest args)
  "Hello World in Eshell."
  ;; (eshell-printn (format "[Debug] args = %S" args))
  (let ((usage "Usage: hello [--help] [--version] [your-name]")
        (version "Hello 2017-03-19 for Eshell"))
    (cond ((-contains-p args "--help") (eshell-print usage))
          ((-contains-p args "--version") (eshell-print version))
          (t (eshell-print (format "Hello %s" (or (car args) "world"))))))
  ;; Eshell also prints return value expect for nil
  nil)

eshell-eval-using-options

(defun eshell/hello (&rest args)
  (eshell-eval-using-options
   "hello" args
   '((?h "help" nil nil "show usage")
     (?v "version" nil version "show version")
     :usage "[-h/--help] [-v/--version] [your-name]")
   ;; (eshell-printn (format "[Debug] %S" args))
   (if version
       (eshell-print "Hello 2017-03-19 for Eshell")
     (eshell-print (format "Hello %s" (or (car args) "world"))))
   nil))

5.2 补全命令行选项和参数

如补全上面的 hello 命令

(defun pcomplete/hello ()
  "Completion for the `hello' command."
  (while t
    (if (pcomplete-match "^-" 0)
        (cond
         ;; Long options
         ((pcomplete-match "^--" 0)
          (pcomplete-here* '("--help" "--version")))
         ;; Short options
         (t (pcomplete-opt "hv"))))))

6 Eshell Script

如其它的 Shell Script,Eshell Script 也是由一系列命令组成。Eshell Script 需要在 Eshell 中利用 source. 运行,这两个的不同之处在于, source 会在一个 subshell 中执行,而 . 会在当前的 shell 中执行。

# Filename: about-this-emacs.eshell
# Description: Print various information about this running Emacs
# Filetype: This is an Eshell (Emacs Shell) Script
# Usage: From Eshell, type 'source about-this-emacs.eshell'

# Note 0: Comments begin with `#' like other shells

setq VERSION 2017-03-10

concat (make-string 40 ?\s) 'About this Emacs'
(identity "\n")                 # Print an extra newline

echo "The version of your Emacs is $(emacs-version)"
echo "It has been running for $(emacs-uptime)"
echo "You have $(length package-selected-packages) packages installed by yourself, i.e., via 'M-x package-install'"

(identity "\n")                 # Print an extra newline
echo "Created by about-this-emacs-$VERSION on ${date}"

7 参考链接

Created: 2017-03-11 | Modified: 2017-03-19 | Org source | History

Author: Chunyang Xu <mail@xuchunyang.me>

Proudly Powered by Emacs & Org mode

Validate XHTML 1.0