El-search 使用举例

El-search – Expression based incremental search for emacs-lisp-mode (Emacs 25+) 继续讨论:

1. 函数调用

想看看别人是怎么用一个函数的,比如 pcase

M-x el-search-emacs-elisp-sources `(pcase . ,_)

2. if 缺少 ELSE 分支

(if COND THEN) 应该改用 when,如何找出它们呢?

M-x el-search-pattern `(if ,_ ,_)

3. 缺少 Docstring 的命令

(elisp) Documentation Tips 建议用户命令都该用 Docstring,如何发现它们呢?假如不用 Checkdoc 的话。

M-x el-search-pattern `(defun ,_ ,_ (interactive . ,_) . ,_)

这个 Pattern 有点儿长,可以用 el-search-x 提供的 l 改短些:

M-x load-library el-search-x
M-x el-search-pattern (l ^ 'defun _ _ (l ^ 'interactive))

4. 缺少 Docstring 的 defvar

(elisp) Documentation Tips 建议那些用户需要了解的变量也应该有 Docstring,如何发现它们呢?

M-x el-search-pattern `(defvar ,(not (symbol "--")) ,_)

5. 按键绑定

Emacs 默认设置了 C-s (isearch-forward),怎么确认这一点呢?

M-x el-search-emacs-elisp-sources `(define-key ,_ ,(keys (kbd "C-s")) 'isearch-forward)

6. Function quote #'

参数是函数的应该用 #' ,如下面应该改用 #'time-stamp

(add-hook 'before-save-hook 'time-stamp)

怎么找出它们呢?

M-x el-search-pattern `(add-hook ,_ ',_)

怎么一次性改正呢?

M-x el-search-query-replace `(add-hook ,hook ',fun) -> `(add-hook ,hook #',fun)

7. 代码中 String

Pormpt、Mode Line、Echo Area 显示的信息,有时想知道是怎么来的。比如我的 Emacs 刚刚显示了

> Type "q" in help window to restore its previous buffer.

那么相应的代码在哪里呢?

M-x el-search-emacs-elisp-sources (string "in help window to restore its previous buffer")

注意我没有包括 "q",因为包含按键的字符串一般都不是 hard-coded 的,如

(message "%s" (substitute-command-keys "按 \\[save-buffer] 来保存文件"))
     => "按 C-x C-s 来保存"

8. 多余的 lambda

常常会看到有人用多余的 lambda,如

(add-hook 'lisp-mode-hook (lambda () (paredit-mode)))

怎么发现这样的问题呢?

M-x el-search-pattern `(lambda () (,_))

还有这种「多余」

(mapcar (lambda (n) (1+ n)) '(1 2 3))

如何发现呢?

M-x el-search-pattern `(lambda (,arg) (,_ ,arg))

9. 按键统一用 kbd 表示

Emacs 按键有三种写法:Vector、String 和 kbd,如:

  1. [?\C-x ?\C-f]
  2. "\C-x\C-f"
  3. (kbd "C-x C-f")

我的 Emacs 配置中混用了它们,我希望统一都用 kbd,应该怎么一次性改掉呢?

M-x el-search-query-replace

(define-key
  ,m
  ,(and k
        (or (pred vectorp) (pred stringp))
        (guard (not (eq (aref k 0) 'remap))))
  ,f)

->

`(define-key ,m (kbd ,(key-description k)) ,f)

10. define-key 改成 bind-key

bind-keydefine-key / global-set-key 更好用,我的 init.el 中混用了它们,我希望只用 bind-key,那么如何把 define-key 全改成 bind-key 呢?

M-x el-search-query-replace

`(define-key ,m ,k ,f)

->

`(bind-key
  ,(if (and (vectorp k) (eq (aref k 0) 'remap))
       k
     (key-description (eval k)))
  ,f
  ,m)

11. 分解 (setq a 1 b 2)(setq a 1)(setq b 2)

如果有一堆同类变量需要设置,怎么写比较好? 中提到有时会将一组相关的设置用一个 setq 设置,那么假如需要分解开该怎么办呢?

M-x el-search-query-replace

`(setq . ,(and r (guard (> (length r) 2))))

->

(mapcar
 (lambda (pair)
   (cons 'setq pair))
 (seq-partition r 2))
6 个赞

我靠,这个包挺高大上的。。。。

这个包应该叫 psearch

pcase 和 Racket 里的 pattern match 一样,还可以用它写解释器。Lisp 的代码(sexp)和数据(list)的形式是一样的,所以自己匹配自己也是正常操作 : p