虽然有 el-search 这样强大的包,但如果目标明确,不想进行过多的交互操作。其实可以用 pcase 来完成一些重构的工作。
例如,只想把光标下的 (set (make-local-variable 'foo) 1)
替换成 (setq-local foo 1)
,并不需要进行全文搜索、替换和回答 Yes / No:
(defun pcase-refactor-at-point (from-pattern to-expr)
"Refactor from FROM-PATTERN to TO-EXPR at point."
(let* ((func `(lambda (sexp)
(pcase sexp
(,from-pattern ,to-expr))))
(refc (funcall func (sexp-at-point))))
(when refc
(mark-sexp)
(delete-region (region-beginning) (region-end))
(insert (format "%S" refc)))))
(defun pcase-refactor-to-setq-local ()
"Refactor from (set (make-local-variable 'sym) val) to (setq-local sym val)."
(interactive)
(pcase-refactor-at-point '`(set (make-local-variable ',sym) ,val)
'`(setq-local ,sym ,val)))
测试:
(with-temp-buffer
(emacs-lisp-mode)
(insert "(set (make-local-variable 'foo) 1)")
(goto-char (point-min))
(call-interactively 'pcase-refactor-to-setq-local)
(buffer-string))
;; => "(setq-local foo 1)"
缺点:
- 替换后的 form 会变成一行,原先的排版格式丢失。
- 当定义了很多专门的
pcase-refactor-XXX
之后,每次按M-x pcase-refactor
之后选择困难。 这个问题可参考 emacs-refactor,该包提供一个emr-select-refactor
入口函数。每次只需调用这个入口函数,它会根据光标所处位置,过滤出适用于当前 form 的 refactor 函数,缩小选择范围。