2011-01-10 16 views
6

Quiero crear una conexión DSL en Elisp buscando algo como esto:Cómo crear una conexión DSL en Elisp

(install 
;; do install 
) 

(uninstall 
;; do uninstall 
) 

Sin embargo, desde Elisp tiene un espacio de nombres global, esto no es una buena idea. Y prefijando las funciones de esta manera, es muy feo.

(package-install 
;; do install 
) 

(package-uninstall 
;; do uninstall 
) 

Así que pensé como un compromiso de todos los comandos pueden ser envueltos en un comando de llamar así:

(commands 
(install 
    ;; do install 
) 

(uninstall 
    ;; do uninstall 
) 

;; ... 
) 

Pero ya no quiero instalar y desinstalación en el espacio de nombres global , De alguna manera tengo que en el macro de comandos, reemplazar todas las instancias de los comandos con, tal vez, por ejemplo, los nombres de prefijo, como este:

(defmacro commands (&rest body) 
    (mapcar 
    (lambda (exp) 
    (setcar exp (intern (concat "package-" (symbol-name (car exp))))) 
    (setcdr exp (list (cons 'progn (cdr exp))))) 
    body) 
    `(progn ,@body)) 

(commands 
(install 
    ;; do install 
) 

(uninstall 
    ;; do uninstall 
) 

;; ... 
) 

Esto parece un hack. Además, no funcionará si hay comandos anidados.

¿Hay alguna buena solución para esto o hackear el camino a seguir?

Gracias!

+0

YASnipper prefije sus funciones con 'yas /', por lo que obtienes 'yas/expand', y así sucesivamente. No pensé que eso fuera feo en absoluto. Adopté la convención para la integración tfs que escribí, por lo que hay 'tfs/checkout',' tfs/add', y así sucesivamente. Esta parece una forma barata y fácil de hacer un scoping de nombres, en ausencia de un soporte formal para ello. – Cheeso

+0

Simplemente una anotación estilística: no usaría 'setcar' /' setcdr' como lo hace en la definición de la macro 'command'. Crea un nuevo 'contras' (que incluso haría el código más limpio). No sabe qué efectos podría tener si su macroextensor modifica arbitrariamente el árbol de códigos original de forma destructiva. – Dirk

Respuesta

8

¿Qué tal la definición local de install y amigos? Esto no ocultará las funciones estándar, pero no parece que eso es lo que realmente buscas.

(defmacro commands (&rest body) 
    `(flet ((install (&rest args) (apply 'package-install args)) 
      (uninstall (&rest args) (apply 'package-uninstall args))) 
    ,@body)) 

Por supuesto que te gustaría para generar esa lista de argumentos flet automáticamente. Necesitas una lista de los elementos de tu paquete en algún lugar, posiblemente usando (feature-symbols 'package).

+1

¡Esto es exactamente lo que estoy buscando! ¡Muchas gracias! – rejeep

Cuestiones relacionadas