Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an Emacs Lisp library for generating HTML?

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.

like image 352
viam0Zah Avatar asked Apr 28 '09 11:04

viam0Zah


People also ask

What is Emacs Lisp used for?

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.

How do I run a Lisp in emacs?

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.

Is Emacs Lisp compiled or interpreted?

Emacs Lisp has a compiler that translates functions written in Lisp into a special representation called byte-code that can be executed more efficiently.

What does #' mean in Elisp?

#'... 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.


1 Answers

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.

like image 57
Trey Jackson Avatar answered Oct 12 '22 01:10

Trey Jackson