Created
July 23, 2014 12:34
-
-
Save spacebat/136aac7e07b08862f60d to your computer and use it in GitHub Desktop.
Recursive template expansion in emacs lisp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (cl-defun template-expand (string data &key | |
| recur | |
| (notation "${\\([^}]+\\)}") | |
| (default (lambda (x) (error "No expansion found for '%s'" x)))) | |
| "Expand variables from the alist `DATA' into the string `STRING'. | |
| The `RECUR' parameter triggers expansion of variables found in | |
| the substituted text. | |
| The `NOTATION' parameter should be a regular expression that captures the variable name. By default it matches ${varname}. | |
| The `DEFAULT' parameter can be a function that will be called or some other value that is stringified when a variable expression was found but no expansion was found in `DATA'. By default an error is thrown." | |
| (cl-labels ((lookup-value (match &optional default) | |
| (let ((key (replace-regexp-in-string notation "\\1" match))) | |
| (format "%s" | |
| (or (assoc-default key data (lambda (elt key) | |
| (string= (format "%s" elt) key))) | |
| (cond | |
| ((functionp default) | |
| (funcall default key)) | |
| ((stringp default) | |
| default) | |
| (default | |
| (format "%s" default)) | |
| (t | |
| "")))))) | |
| (expand (string) | |
| (let (result) | |
| (setq result (replace-regexp-in-string notation | |
| (lambda (x) | |
| (if recur | |
| (expand (lookup-value x default)) | |
| (lookup-value x default))) | |
| string)) | |
| (message "result: %s" result) | |
| result))) | |
| (expand string))) | |
| ;; (let ((data '((name . "Newt") | |
| ;; (claim . "Game over!") | |
| ;; (who? . "${name}")))) | |
| ;; (list | |
| ;; (template-expand "${name} would not say ${claim}" data) | |
| ;; (template-expand "${who?} would not say ${claim}" data) | |
| ;; (template-expand "${who?} would not say ${claim}" data :recur t) | |
| ;; (template-expand "${someone} would not say ${claim}" data :default "Ripley") | |
| ;; )) | |
| ;; Gives: | |
| ;; ("Newt would not say Game over!" | |
| ;; "${name} would not say Game over!" | |
| ;; "Newt would not say Game over!" | |
| ;; "Ripley would not say Game over!") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment