4

我正在尝试定义一些辅助函数以从 emacs 中快速跳转到不同的项目。我首先定义了一个宏,如下所示

(defmacro project-alias (name path)
  `(defun ,name ()
     (interactive)
     (cd ,path)))

这很好用,我(project-alias foo "~/bar")没问题。当我尝试将此宏应用于元组列表时,问题就来了。

(setq projects '((foo . "~/foo")
                 (bar . "~/bar")))

(dolist (p projects)
  (project-alias (car p) (cdr p)))

上面的代码错误与

Debugger entered--Lisp error: (wrong-type-argument symbolp (car p))
  defalias((car p) (lambda nil (interactive) (cd (cdr p))))

我尝试将第一个参数作为字符串传递并调用intern以毫无乐趣地获取符号表示,并且我还尝试定义我的宏以接受字符串形式,但这也不起作用

我究竟做错了什么?

4

5 回答 5

5

如果您对宏的使用涉及评估sexps 以生成名称和路径,那么它需要评估 sexps:

(defmacro project-alias (name path)
  `(defun ,(eval name) () (interactive) (cd ,(eval path))))

或者,使用一个函数:

(defun project-alias (name path)
  (eval `(defun ,name () (interactive) (cd ,path))))
于 2013-11-06T16:40:38.423 回答
1

宏参数被传递un-evaluate。(宏不能做他们能做的事情。)

所以你的论点实际上是形式(car p)(cdr p)(与例如foo和相反"~/foo")。

于 2013-11-06T15:32:35.897 回答
1

你可以做

(defun project-alias-f (name path)
  (eval `(defun ,name ()
       (interactive)
       (cd ,path))))



(dolist (p projects)
  (project-alias-f (car p) (cdr p)))

或者

(dolist (p projects)
  (eval `(project-alias ,(car p) ,(cdr p))))
于 2013-11-06T16:37:43.797 回答
1

这是另一种看法,没有宏也没有 eval:

;; -*- lexical-binding:t -*-

(defun project-alias-f (name filename)
  (defalias name (lambda () (interactive) (cd filename)))

(dolist (p projects)
  (project-alias-f (car p) (cdr p)))
于 2013-11-06T21:25:26.807 回答
0

这不是对您的宏观问题的答案,而是您希望在项目之间跳转的替代解决方案。

在我的 init.el 文件中,我有(除其他外)

(set-register ?A '(file . "~/.aliases"))
(set-register ?E '(file . "~/.emacs.d/init.el"))
(set-register ?H '(file . "~/.hgrc"))
(set-register ?T '(file . "~/.TODO.org"))

然后,当我希望编辑文件(或对未列出的项目之一执行某些操作)时,我可以使用jump-to-register( ) 跳转到其中一个文件。C-x r j因为文件/文件夹存储在寄存器中(而不是窗口配置),emacs 将打开它在寄存器中找到的文件或文件夹。

于 2013-11-06T15:10:57.717 回答