I'm looking for a solution that allows me to write native Emacs Lisp code and at compile time turns it into HTML, like Franz's htmlgen:
(html
((:div class "post")
(:h1 "Title")
(:p "Hello, World!")))
Of course I can write my own macros, but I'm interested if there are any projects around this problem.
Emacs Lisp is a dialect of the Lisp programming language used as a scripting language by Emacs (a text editor family most commonly associated with GNU Emacs and XEmacs). It is used for implementing most of the editing functionality built into Emacs, the remainder being written in C, as is the Lisp interpreter.
To load an Emacs Lisp file, type M-x load-file . This command reads a file name using the minibuffer, and executes the contents of that file as Emacs Lisp code.
Emacs Lisp has a compiler that translates functions written in Lisp into a special representation called byte-code that can be executed more efficiently.
#'... is short-hand for (function ...) which is simply a variant of '... / (quote ...) that also hints to the byte-compiler that it can compile the quoted form as a function.
As you found out, xmlgen
generates XML from a list structure. What I did find disappointing with the ``xmlgen` package that the format it supports is not quite the inverse of Emacs' xml parser.
I did add this to my copy of xmlgen:
;; this creates a routine to be the inverse of what xml-parse does
;;;###autoload
(defun xml-gen (form &optional in-elm level)
"Convert a sexp to xml:
'(p :class \"big\")) => \"<p class=\\\"big\\\" />\""
(let ((level (or level 0)))
(cond
((numberp form) (number-to-string form))
((stringp form) form)
((listp form)
(destructuring-bind (xml attrs) (xml-gen-extract-plist form)
(let ((el (car xml)))
(unless (symbolp el)
(error "Element must be a symbol (got '%S')." el))
(setq el (symbol-name el))
(concat "<" el (xml-gen-attr-to-string attrs)
(if (> (length xml) 1)
(concat ">" (mapconcat
(lambda (s) (xml-gen s el (1+ level)))
(cdr xml)
"")
"</" el ">")
"/>"))))))))
(defun xml-gen-attr-to-string (plist)
(reduce 'concat (mapcar (lambda (p) (concat " " (symbol-name (car p)) "=\"" (cdr p) "\"")) plist)))
(defun xml-gen-extract-plist (list)
(list (cons (car list) (let ((kids (xml-node-children list)))
(if (= 1 (length kids))
kids
(remove-if-not 'listp kids))))
(xml-node-attributes list)))
Note: the interface for this is xml-gen
(not xmlgen
which is the original parsing).
With this interface, the following holds:
(string-equal (xml-gen (car (xml-parse-region <some-region-of-xml>)))
<some-region-of-xml>)
and
(equal (car (xml-parse-region (insert (xml-gen <some-xml-form>))))
<some-xml-form>)
The new xml-gen
does not strive to preserve the whitespace around that the xml-parse-region
routine generates.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With