Emacs元编程,动态定义方法

时间:2013-11-06 15:04:17

标签: emacs macros elisp metaprogramming

我正在尝试定义一些辅助函数,以便从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以获得符号表示而没有任何快乐,我也尝试定义我的宏来接受字符串形式而不是工作

我做错了什么?

5 个答案:

答案 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-registerC-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))))