我正在尝试定义一些辅助函数,以便从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
以获得符号表示而没有任何快乐,我也尝试定义我的宏来接受字符串形式而不是工作
我做错了什么?
答案 0 :(得分:5)
如果你使用宏涉及 评估 sexps来生成名称和路径,那么它需要评估性别:
(defmacro project-alias (name path)
`(defun ,(eval name) () (interactive) (cd ,(eval path))))
或者,使用函数:
(defun project-alias (name path)
(eval `(defun ,name () (interactive) (cd ,path))))
答案 1 :(得分:1)
宏参数传递未评估。 (宏不能做他们能做的事情。)
因此,您的论据实际上是表单(car p)
和(cdr p)
(例如,foo
和"~/foo"
)。
答案 2 :(得分: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)))
答案 3 :(得分: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将打开它在寄存器中找到的文件或文件夹。
答案 4 :(得分:0)
你可以做任何一件事
(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))))