aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Done <chrisdone@gmail.com>2009-11-07 09:37:06 +0000
committerChris Done <chrisdone@gmail.com>2009-11-07 09:37:06 +0000
commitf25237af8c869a4f44a48858379e1d73dc66e6a8 (patch)
treedf5b2c14b3d53f15ea869050d20bf87a44c91f07
parentd803bf2edc95cd7001486c28d7a496f1a240dbbe (diff)
downloademmet-mode-f25237af8c869a4f44a48858379e1d73dc66e6a8.tar.lz
emmet-mode-f25237af8c869a4f44a48858379e1d73dc66e6a8.tar.xz
emmet-mode-f25237af8c869a4f44a48858379e1d73dc66e6a8.zip
added proper tags with properties - ids, classes
-rw-r--r--zencoding.el165
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>