Skip to content

Instantly share code, notes, and snippets.

@spacebat
Created July 23, 2014 12:34
Show Gist options
  • Select an option

  • Save spacebat/136aac7e07b08862f60d to your computer and use it in GitHub Desktop.

Select an option

Save spacebat/136aac7e07b08862f60d to your computer and use it in GitHub Desktop.
Recursive template expansion in emacs lisp
(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