diff options
author | Chris Done <chrisdone@gmail.com> | 2009-11-07 09:37:06 +0000 |
---|---|---|
committer | Chris Done <chrisdone@gmail.com> | 2009-11-07 09:37:06 +0000 |
commit | f25237af8c869a4f44a48858379e1d73dc66e6a8 (patch) | |
tree | df5b2c14b3d53f15ea869050d20bf87a44c91f07 | |
parent | d803bf2edc95cd7001486c28d7a496f1a240dbbe (diff) | |
download | emmet-mode-f25237af8c869a4f44a48858379e1d73dc66e6a8.tar.lz emmet-mode-f25237af8c869a4f44a48858379e1d73dc66e6a8.tar.xz emmet-mode-f25237af8c869a4f44a48858379e1d73dc66e6a8.zip |
added proper tags with properties - ids, classes
-rw-r--r-- | zencoding.el | 165 |
1 files changed, 116 insertions, 49 deletions
diff --git a/zencoding.el b/zencoding.el index 6b0efb7..9737dad 100644 --- a/zencoding.el +++ b/zencoding.el @@ -1,26 +1,3 @@ -;; Demo - -;; (transform (car (expr "a>b>c+d+e"))) -;; => <a><b><c></c><d></d><e></e></b></a> - -;; (transform (car (expr "html>head+(body>p)"))) -;; => <html><head></head><body><p></p></body></html> - -;; (transform (car (expr "html>head+(body>p+(ul>li))"))) -;; => [indentation added with xml-mode] -;; <html> -;; <head> -;; </head> -;; <body> -;; <p> -;; </p> -;; <ul> -;; <li> -;; </li> -;; </ul> -;; </body> -;; </html> - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Generic parsing macros and utilities @@ -74,20 +51,42 @@ (defun expr (input) "Parse a zen coding expression." - (pif (siblings input) + (run siblings it - (pif (parent-child input) + (run parent-child it - (pif (pexpr input) + (run pexpr it - (pif (atom input) + (run tag it '(error "no match, expecting ( or a-zA-Z0-9")))))) -(defun atom (input) - "Parse a simple a-zA-Z0-9 atom (e.g. html/head/xsl:if/br)." - (parse "\\([a-zA-Z0-9]+\\)" 2 "atom, a-zA-Z0-9" - `((atom . ,(elt it 1)) . ,input))) +(defun tag (input) + "Parse a tag." + (run tagname + (let ((result it) + (tagname (cdr expr))) + (run identifier + (tag-classes `(tag ,tagname ((id ,(cddr expr)))) input) + (tag-classes `(tag ,tagname ()) input))) + '(error "expected tagname"))) + +(defun tag-classes (tag input) + (run classes + (let ((tagname (cadr tag)) + (props (caddr tag)) + (classes `(class ,(mapconcat + (lambda (prop) + (cdadr prop)) + (cdr expr) + " ")))) + `((tag ,tagname ,(append props (list classes))) . ,input)) + `(,tag . ,input))) + +(defun tagname (input) + "Parse a tagname a-zA-Z0-9 tagname (e.g. html/head/xsl:if/br)." + (parse "\\([a-zA-Z0-9:-]+\\)" 2 "tagname, a-zA-Z0-9" + `((tagname . ,(elt it 1)) . ,input))) (defun pexpr (input) "A zen coding expression with parentheses around it." @@ -98,9 +97,9 @@ '(error "expecting `)'"))))) (defun parent-child (input) - "Parse an atom>e expression, where `n' is an atom and `e' is any + "Parse an tag>e expression, where `n' is an tag and `e' is any expression." - (run atom + (run tag (let ((parent expr)) (parse ">" 1 ">" (run expr @@ -110,35 +109,103 @@ '(error "expected parent"))) (defun sibling (input) - (por pexpr atom + (por pexpr tag it '(error "expected sibling"))) (defun siblings (input) - "Parse an e+e expression, where e is an atom." - (por pexpr atom + "Parse an e+e expression, where e is an tag or a pexpr." + (por pexpr tag (let ((parent expr)) - (parse "+" 1 "+" + (parse "\\+" 1 "+" (por siblings sibling (let ((child expr)) `((siblings ,parent ,child) . ,input)) '(error "expected second sibling")))) '(error "expected first sibling"))) +(defun name (input) + "Parse a class or identifier name, e.g. news, footer, mainimage" + (parse "\\([a-zA-Z][a-zA-Z0-9-_]*\\)" 2 "class or identifer name" + `((name . ,(elt it 1)) . ,input))) + +(defun class (input) + "Parse a classname expression, e.g. .foo" + (parse "\\." 1 "." + (run name + `((class ,expr) . ,input) + '(error "expected class name")))) + +(defun identifier (input) + "Parse an identifier expression, e.g. #foo" + (parse "#" 1 "#" + (run name `((identifier . ,expr) . ,input)))) + +(defun classes (input) + "Parse many classes." + (run class + (pif (classes input) + `((classes . ,(cons expr (cdar it))) . ,(cdr it)) + `((classes . ,(list expr)) . ,input)) + '(error "expected class"))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Zen coding transformer from AST to HTML -(defun make-tag (name &optional content) - (concat "<" name ">\n" (if content content "") "</" name ">\n")) +(defun make-tag (tag &optional content) + (let ((name (car tag)) + (props (apply 'concat (mapcar + (lambda (prop) + (concat " " (symbol-name (car prop)) + "=\"" (cadr prop) "\"")) + (cadr tag))))) + (concat "<" name props ">\n" + (if content content "") + "</" name ">\n"))) (defun transform (ast) - (cond - ((eq (car ast) 'atom) (make-tag (cdr ast))) - ((eq (car ast) 'parent-child) - (let ((parent (cdadr ast)) - (children (transform (caddr ast)))) - (make-tag parent children))) - ((eq (car ast) 'siblings) - (let ((sib1 (transform (cadr ast))) - (sib2 (transform (caddr ast)))) - (concat sib1 sib2)))))
\ No newline at end of file + (let ((type (car ast))) + (cond + ((eq type 'tag) + (make-tag (cdr ast))) + ((eq type 'tagname) (make-tag (cdr ast))) + ((eq type 'parent-child) + (let ((parent (cdadr ast)) + (children (transform (caddr ast)))) + (make-tag parent children))) + ((eq type 'siblings) + (let ((sib1 (transform (cadr ast))) + (sib2 (transform (caddr ast)))) + (concat sib1 sib2)))))) + +;; Demo + +;; (transform (car (expr "a>b>c+d+e"))) +;; => <a><b><c></c><d></d><e></e></b></a> + +;; (transform (car (expr "html>head+(body>p)"))) +;; => <html><head></head><body><p></p></body></html> + +;; (transform (car (expr "html>head+(body>p+(ul>li))"))) +;; => [indentation added with xml-mode] +;; <html> +;; <head> +;; </head> +;; <body> +;; <p> +;; </p> +;; <ul> +;; <li> +;; </li> +;; </ul> +;; </body> +;; </html> + +;; (transform (car (expr "body.sub-page>div#news.content.a+div#news.content.a"))) +;; => [indentation added with xml-mode] +;; <body class="sub-page"> +;; <div id="news" class="content a"> +;; </div> +;; <div id="news" class="content a"> +;; </div> +;; </body> |