2011-01-10 38 views
6

創建DSL我想創建一個elisp的DSL看起來像這樣:如何elisp的

(install 
;; do install 
) 

(uninstall 
;; do uninstall 
) 

然而,由於elisp的有一個全局命名空間,這不是一個好主意。像這樣的功能前綴,是如此醜陋。

(package-install 
;; do install 
) 

(package-uninstall 
;; do uninstall 
) 

所以我想作爲一種折中的所有命令可以被包裹在一個命令調用是這樣的:

(commands 
(install 
    ;; do install 
) 

(uninstall 
    ;; do uninstall 
) 

;; ... 
) 

但因爲我不想安裝卸載在全局命名空間,我不知何故必須在命令宏中,用例如前綴名稱替換所有出現的命令,如下所示:

(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 
) 

;; ... 
) 

這似乎是這樣的黑客攻擊。另外,如果有嵌套命令,它將不起作用。

有沒有什麼好的解決方案,或者是黑客的路要走?

謝謝!

+0

YASnipper用`yas /`前綴他們的函數,所以你得到`yas/expand`等等。我根本不認爲這很醜陋。我採用了我寫的tfs集成的約定,所以有`tfs/checkout`,`tfs/add`等等。在沒有正式支持的情況下,這似乎是一種簡單易行的名稱範圍界定方法。 – Cheeso 2011-01-10 20:50:47

+0

只是一個文體註釋:我不會像在`command`宏的定義中那樣使用`setcar` /`setcdr`。創建一個新的`cons`(甚至可以使代碼更清潔)。如果宏擴展器以破壞性方式任意修改原始代碼樹,您不知道它會產生什麼效果。 – Dirk 2011-01-10 21:02:36

回答

8

如何在本地定義install和朋友?這不會隱藏標準函數,但它看起來並不像你真的那樣。

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

當然,您想要自動生成flet參數列表。您確實需要某個地方的軟件包元素列表,可能使用(feature-symbols 'package)