Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 1088 lines (910 sloc) 34.827 kb
aa064c9 @rstacruz Initial commit.
rstacruz authored
1 #!/usr/bin/env python
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
2 # -*- coding: utf-8 -*-
0d759ac @rstacruz Version bump; updated Makefile to create ZIP distribution file
rstacruz authored
3 version = "0.1.3"
aa064c9 @rstacruz Initial commit.
rstacruz authored
4
5 import os
6 import fileinput
7 import getopt
8 import sys
9 import re
10
11 # ===============================================================================
12
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
13 class Dialect:
14 shortcuts = {}
15 synonyms = {}
16 required = {}
17 short_tags = ()
18
19 class HtmlDialect(Dialect):
20 shortcuts = {
21 'cc:ie': {
22 'opening_tag': '<!--[if IE]>',
23 'closing_tag': '<![endif]-->'},
24 'cc:ie6': {
25 'opening_tag': '<!--[if lte IE 6]>',
26 'closing_tag': '<![endif]-->'},
27 'cc:ie7': {
28 'opening_tag': '<!--[if lte IE 7]>',
29 'closing_tag': '<![endif]-->'},
30 'cc:noie': {
31 'opening_tag': '<!--[if !IE]><!-->',
32 'closing_tag': '<!--<![endif]-->'},
33 'html:4t': {
34 'expand': True,
35 'opening_tag':
36 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">\n' +
37 '<html lang="en">\n' +
38 '<head>\n' +
39 ' ' + '<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />\n' +
40 ' ' + '<title></title>\n' +
41 '</head>\n' +
42 '<body>',
43 'closing_tag':
44 '</body>\n' +
45 '</html>'},
46 'html:4s': {
47 'expand': True,
48 'opening_tag':
49 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">\n' +
50 '<html lang="en">\n' +
51 '<head>\n' +
52 ' ' + '<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />\n' +
53 ' ' + '<title></title>\n' +
54 '</head>\n' +
55 '<body>',
56 'closing_tag':
57 '</body>\n' +
58 '</html>'},
59 'html:xt': {
60 'expand': True,
61 'opening_tag':
62 '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n' +
63 '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\n' +
64 '<head>\n' +
65 ' ' + '<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />\n' +
66 ' ' + '<title></title>\n' +
67 '</head>\n' +
68 '<body>',
69 'closing_tag':
70 '</body>\n' +
71 '</html>'},
72 'html:xs': {
73 'expand': True,
74 'opening_tag':
75 '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n' +
76 '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\n' +
77 '<head>\n' +
78 ' ' + '<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />\n' +
79 ' ' + '<title></title>\n' +
80 '</head>\n' +
81 '<body>',
82 'closing_tag':
83 '</body>\n' +
84 '</html>'},
85 'html:xxs': {
86 'expand': True,
87 'opening_tag':
88 '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\n' +
89 '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\n' +
90 '<head>\n' +
91 ' ' + '<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />\n' +
92 ' ' + '<title></title>\n' +
93 '</head>\n' +
94 '<body>',
95 'closing_tag':
96 '</body>\n' +
97 '</html>'},
98 'html:5': {
99 'expand': True,
100 'opening_tag':
101 '<!DOCTYPE html>\n' +
102 '<html lang="en">\n' +
103 '<head>\n' +
104 ' ' + '<meta charset="UTF-8" />\n' +
105 ' ' + '<title></title>\n' +
106 '</head>\n' +
107 '<body>',
108 'closing_tag':
109 '</body>\n' +
110 '</html>'},
111 'input:button': {
112 'name': 'input',
113 'attributes': { 'class': 'button', 'type': 'button', 'name': '', 'value': '' }
114 },
115 'input:password': {
116 'name': 'input',
117 'attributes': { 'class': 'text password', 'type': 'password', 'name': '', 'value': '' }
118 },
119 'input:radio': {
120 'name': 'input',
121 'attributes': { 'class': 'radio', 'type': 'radio', 'name': '', 'value': '' }
122 },
123 'input:checkbox': {
124 'name': 'input',
125 'attributes': { 'class': 'checkbox', 'type': 'checkbox', 'name': '', 'value': '' }
126 },
127 'input:file': {
128 'name': 'input',
129 'attributes': { 'class': 'file', 'type': 'file', 'name': '', 'value': '' }
130 },
131 'input:text': {
132 'name': 'input',
133 'attributes': { 'class': 'text', 'type': 'text', 'name': '', 'value': '' }
134 },
135 'input:submit': {
136 'name': 'input',
137 'attributes': { 'class': 'submit', 'type': 'submit', 'value': '' }
138 },
139 'input:hidden': {
140 'name': 'input',
141 'attributes': { 'type': 'hidden', 'name': '', 'value': '' }
142 },
143 'script:src': {
144 'name': 'script',
145 'attributes': { 'src': '' }
146 },
0b7817d @rstacruz Added 'jquery' shortcut, and 'jsapi' too
rstacruz authored
147 'script:jquery': {
148 'name': 'script',
149 'attributes': { 'src': 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js' }
150 },
151 'script:jsapi': {
152 'name': 'script',
153 'attributes': { 'src': 'http://www.google.com/jsapi' }
154 },
155 'script:jsapix': {
156 'name': 'script',
157 'text': '\n google.load("jquery", "1.3.2");\n google.setOnLoadCallback(function() {\n \n });\n'
158 },
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
159 'link:css': {
160 'name': 'link',
161 'attributes': { 'rel': 'stylesheet', 'type': 'text/css', 'href': '', 'media': 'all' },
162 },
163 'link:print': {
164 'name': 'link',
165 'attributes': { 'rel': 'stylesheet', 'type': 'text/css', 'href': '', 'media': 'print' },
166 },
167 'link:favicon': {
168 'name': 'link',
169 'attributes': { 'rel': 'shortcut icon', 'type': 'image/x-icon', 'href': '' },
170 },
171 'link:touch': {
172 'name': 'link',
173 'attributes': { 'rel': 'apple-touch-icon', 'href': '' },
174 },
175 'link:rss': {
176 'name': 'link',
177 'attributes': { 'rel': 'alternate', 'type': 'application/rss+xml', 'title': 'RSS', 'href': '' },
178 },
179 'link:atom': {
180 'name': 'link',
181 'attributes': { 'rel': 'alternate', 'type': 'application/atom+xml', 'title': 'Atom', 'href': '' },
182 },
183 'meta:ie7': {
184 'name': 'meta',
185 'attributes': { 'http-equiv': 'X-UA-Compatible', 'content': 'IE=7' },
186 },
187 'meta:ie8': {
188 'name': 'meta',
189 'attributes': { 'http-equiv': 'X-UA-Compatible', 'content': 'IE=8' },
190 },
191 'form:get': {
192 'name': 'form',
193 'attributes': { 'method': 'get' },
194 },
195 'form:g': {
196 'name': 'form',
197 'attributes': { 'method': 'get' },
198 },
199 'form:post': {
200 'name': 'form',
201 'attributes': { 'method': 'post' },
202 },
203 'form:p': {
204 'name': 'form',
205 'attributes': { 'method': 'post' },
206 },
207 }
208 synonyms = {
209 'checkbox': 'input:checkbox',
210 'check': 'input:checkbox',
211 'input:c': 'input:checkbox',
212 'button': 'input:button',
213 'input:b': 'input:button',
0b7817d @rstacruz Added 'jquery' shortcut, and 'jsapi' too
rstacruz authored
214 'input:h': 'input:hidden',
215 'hidden': 'input:hidden',
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
216 'submit': 'input:submit',
217 'input:s': 'input:submit',
218 'radio': 'input:radio',
219 'input:r': 'input:radio',
220 'text': 'input:text',
0b7817d @rstacruz Added 'jquery' shortcut, and 'jsapi' too
rstacruz authored
221 'passwd': 'input:password',
222 'password': 'input:password',
223 'pw': 'input:password',
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
224 'input:t': 'input:text',
225 'linkcss': 'link:css',
226 'scriptsrc': 'script:src',
0b7817d @rstacruz Added 'jquery' shortcut, and 'jsapi' too
rstacruz authored
227 'jquery': 'script:jquery',
228 'jsapi': 'script:jsapi',
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
229 'html5': 'html:5',
230 'html4': 'html:4s',
231 'html4s': 'html:4s',
0b7817d @rstacruz Added 'jquery' shortcut, and 'jsapi' too
rstacruz authored
232 'html4t': 'html:4t',
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
233 'xhtml': 'html:xxs',
234 'xhtmlt': 'html:xt',
235 'xhtmls': 'html:xs',
236 'xhtml11': 'html:xxs',
0b7817d @rstacruz Added 'jquery' shortcut, and 'jsapi' too
rstacruz authored
237 'opt': 'option',
238 'st': 'strong',
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
239 'css': 'style',
0b7817d @rstacruz Added 'jquery' shortcut, and 'jsapi' too
rstacruz authored
240 'csss': 'link:css',
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
241 'css:src': 'link:css',
242 'csssrc': 'link:css',
243 'js': 'script',
0b7817d @rstacruz Added 'jquery' shortcut, and 'jsapi' too
rstacruz authored
244 'jss': 'script:src',
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
245 'js:src': 'script:src',
246 'jssrc': 'script:src',
247 }
248 short_tags = (
249 'area', 'base', 'basefont', 'br', 'embed', 'hr', \
250 'input', 'img', 'link', 'param', 'meta')
251 required = {
252 'a': {'href':''},
253 'base': {'href':''},
254 'abbr': {'title': ''},
255 'acronym':{'title': ''},
256 'bdo': {'dir': ''},
257 'link': {'rel': 'stylesheet', 'href': ''},
258 'style': {'type': 'text/css'},
259 'script': {'type': 'text/javascript'},
260 'img': {'src':'', 'alt':''},
261 'iframe': {'src': '', 'frameborder': '0'},
262 'embed': {'src': '', 'type': ''},
263 'object': {'data': '', 'type': ''},
264 'param': {'name': '', 'value': ''},
265 'form': {'action': '', 'method': 'post'},
266 'table': {'cellspacing': '0'},
267 'input': {'type': '', 'name': '', 'value': ''},
268 'base': {'href': ''},
269 'area': {'shape': '', 'coords': '', 'href': '', 'alt': ''},
270 'select': {'name': ''},
271 'option': {'value': ''},
272 'textarea':{'name': ''},
273 'meta': {'content': ''},
274 }
275
aa064c9 @rstacruz Initial commit.
rstacruz authored
276 class Parser:
277 """The parser.
278 """
279
280 # Constructor
281 # ---------------------------------------------------------------------------
282
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
283 def __init__(self, options=None, str='', dialect=HtmlDialect()):
aa064c9 @rstacruz Initial commit.
rstacruz authored
284 """Constructor.
285 """
286
c813071 @rstacruz Added a simple unit test
rstacruz authored
287 self.tokens = []
aa064c9 @rstacruz Initial commit.
rstacruz authored
288 self.str = str
289 self.options = options
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
290 self.dialect = dialect
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
291 self.root = Element(parser=self)
aa064c9 @rstacruz Initial commit.
rstacruz authored
292 self.caret = []
293 self.caret.append(self.root)
294 self._last = []
295
296 # Methods
297 # ---------------------------------------------------------------------------
298
299 def load_string(self, str):
300 """Loads a string to parse.
301 """
302
303 self.str = str
304 self._tokenize()
305 self._parse()
306
307 def render(self):
308 """Renders.
309 Called by [[Router]].
310 """
311
312 # Get the initial render of the root node
313 output = self.root.render()
314
315 # Indent by whatever the input is indented with
316 indent = re.findall("^[\r\n]*(\s*)", self.str)[0]
317 output = indent + output.replace("\n", "\n" + indent)
318
3ab3c2e @rstacruz Fixed --no-last-newline
rstacruz authored
319 # Strip newline if not needed
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
320 if self.options.has("no-last-newline") \
321 or self.prefix or self.suffix:
afd433e @rstacruz Fixed --no-last-newline with --textmate
rstacruz authored
322 output = re.sub(r'\n\s*$', '', output)
3ab3c2e @rstacruz Fixed --no-last-newline
rstacruz authored
323
813772f @rstacruz TextMate support; added --no-last-newline and --textmate arguments
rstacruz authored
324 # TextMate mode
325 if self.options.has("textmate"):
326 output = self._textmatify(output)
327
aa064c9 @rstacruz Initial commit.
rstacruz authored
328 return output
329
330 # Protected methods
331 # ---------------------------------------------------------------------------
332
813772f @rstacruz TextMate support; added --no-last-newline and --textmate arguments
rstacruz authored
333 def _textmatify(self, output):
334 """Returns a version of the output with TextMate placeholders in it.
335 """
336
aa262d1 @rstacruz Made tabstops for quotes in TextMate mode (e.g., <a href="">)
rstacruz authored
337 matches = re.findall(r'(></)|("")|(\n\s+)\n|(.|\s)', output)
813772f @rstacruz TextMate support; added --no-last-newline and --textmate arguments
rstacruz authored
338 output = ''
339 n = 1
340 for i in matches:
341 if i[0]:
342 output += '>$%i</' % n
343 n += 1
344 elif i[1]:
aa262d1 @rstacruz Made tabstops for quotes in TextMate mode (e.g., <a href="">)
rstacruz authored
345 output += '"$%i"' % n
813772f @rstacruz TextMate support; added --no-last-newline and --textmate arguments
rstacruz authored
346 n += 1
347 elif i[2]:
aa262d1 @rstacruz Made tabstops for quotes in TextMate mode (e.g., <a href="">)
rstacruz authored
348 output += i[2] + '$%i\n' % n
349 n += 1
350 elif i[3]:
351 output += i[3]
813772f @rstacruz TextMate support; added --no-last-newline and --textmate arguments
rstacruz authored
352 output += "$0"
353 return output
354
aa064c9 @rstacruz Initial commit.
rstacruz authored
355 def _tokenize(self):
356 """Tokenizes.
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
357 Initializes [[self.tokens]].
aa064c9 @rstacruz Initial commit.
rstacruz authored
358 """
359
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
360 str = self.str.strip()
361
362 # Find prefix/suffix
363 while True:
364 match = re.match(r"^(\s*<[^>]+>\s*)", str)
365 if match is None: break
366 if self.prefix is None: self.prefix = ''
367 self.prefix += match.group(0)
e17d92b @rstacruz Fixed prefixes and suffixes with complex surrounding HTML tags
rstacruz authored
368 str = str[len(match.group(0)):]
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
369
370 while True:
371 match = re.findall(r"(\s*<[^>]+>[\s\n\r]*)$", str)
372 if not match: break
373 if self.suffix is None: self.suffix = ''
e17d92b @rstacruz Fixed prefixes and suffixes with complex surrounding HTML tags
rstacruz authored
374 self.suffix = match[0] + self.suffix
375 str = str[:-len(match[0])]
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
376
aa064c9 @rstacruz Initial commit.
rstacruz authored
377 # Split by the element separators
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
378 for token in re.split('(<|>|\+(?!\\s*\+|$))', str):
aa064c9 @rstacruz Initial commit.
rstacruz authored
379 if token.strip() != '':
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
380 self.tokens.append(Token(token, parser=self))
aa064c9 @rstacruz Initial commit.
rstacruz authored
381
382 def _parse(self):
383 """Takes the tokens and does its thing.
384 Populates [[self.root]].
385 """
386
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
387 # Carry it over to the root node.
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
388 if self.prefix or self.suffix:
389 self.root.prefix = self.prefix
390 self.root.suffix = self.suffix
391 self.root.depth += 1
392
aa064c9 @rstacruz Initial commit.
rstacruz authored
393 for token in self.tokens:
394 if token.type == Token.ELEMENT:
395 # Reset the "last elements added" list. We will
396 # repopulate this with the new elements added now.
397 self._last[:] = []
398
399 # Create [[Element]]s from a [[Token]].
400 # They will be created as many as the multiplier specifies,
401 # multiplied by how many carets we have
402 count = 0
403 for caret in self.caret:
404 local_count = 0
405 for i in range(token.multiplier):
406 count += 1
407 local_count += 1
408 new = Element(token, caret,
409 count = count,
410 local_count = local_count,
411 parser = self)
412 self._last.append(new)
413 caret.append(new)
414
415 # For >
416 elif token.type == Token.CHILD:
417 # The last children added.
418 self.caret[:] = self._last
419
420 # For <
421 elif token.type == Token.PARENT:
422 # If we're the root node, don't do anything
423 parent = self.caret[0].parent
424 if parent is not None:
425 self.caret[:] = [parent]
426 return
427
428 # Properties
429 # ---------------------------------------------------------------------------
430
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
431 # Property: dialect
432 # The dialect of XML
433 dialect = None
434
aa064c9 @rstacruz Initial commit.
rstacruz authored
435 # Property: str
436 # The string
437 str = ''
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
438
439 # Property: tokens
440 # The list of tokens
aa064c9 @rstacruz Initial commit.
rstacruz authored
441 tokens = []
442
443 # Property: options
444 # Reference to the [[Options]] instance
445 options = None
446
447 # Property: root
448 # The root [[Element]] node.
449 root = None
450
451 # Property: caret
452 # The current insertion point.
453 caret = None
454
455 # Property: _last
456 # List of the last appended stuff
457 _last = None
458
459 # Property: indent
460 # Yeah
461 indent = ''
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
462
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
463 # Property: prefix
464 # (String) The trailing tag in the beginning.
465 #
466 # Description:
467 # For instance, in `<div>ul>li</div>`, the `prefix` is `<div>`.
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
468 prefix = ''
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
469
470 # Property: suffix
471 # (string) The trailing tag at the end.
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
472 suffix = ''
aa064c9 @rstacruz Initial commit.
rstacruz authored
473 pass
474
475 # ===============================================================================
476
477 class Element:
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
478 """An element.
479 """
480
481 def __init__(self, token=None, parent=None, count=None, local_count=None, \
482 parser=None, opening_tag=None, closing_tag=None, \
483 attributes=None, name=None, text=None):
484 """Constructor.
485
486 This is called by ???.
487
488 Description:
489 All parameters are optional.
490
491 token - (Token) The token (required)
492 parent - (Element) Parent element; `None` if root
493 count - (Int) The number to substitute for `&` (e.g., in `li.item-$`)
494 local_count - (Int) The number to substitute for `$` (e.g., in `li.item-&`)
495 parser - (Parser) The parser
496
497 attributes - ...
498 name - ...
499 text - ...
500 """
501
aa064c9 @rstacruz Initial commit.
rstacruz authored
502 self.children = []
503 self.attributes = {}
504 self.parser = parser
505
506 if token is not None:
507 # Assumption is that token is of type [[Token]] and is
508 # a [[Token.ELEMENT]].
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
509 self.name = token.name
510 self.attributes = token.attributes.copy()
511 self.text = token.text
512 self.populate = token.populate
513 self.expand = token.expand
514 self.opening_tag = token.opening_tag
515 self.closing_tag = token.closing_tag
aa064c9 @rstacruz Initial commit.
rstacruz authored
516
517 # `count` can be given. This will substitude & in classname and ID
518 if count is not None:
519 for key in self.attributes:
520 attrib = self.attributes[key]
521 attrib = attrib.replace('&', ("%i" % count))
522 if local_count is not None:
523 attrib = attrib.replace('$', ("%i" % local_count))
524 self.attributes[key] = attrib
525
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
526 # Copy over from parameters
527 if attributes: self.attributes = attribues
528 if name: self.name = name
529 if text: self.text = text
530
aa064c9 @rstacruz Initial commit.
rstacruz authored
531 self._fill_attributes()
532
533 self.parent = parent
534 if parent is not None:
535 self.depth = parent.depth + 1
536
537 if self.populate: self._populate()
538
539 def render(self):
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
540 """Renders the element, along with it's subelements, into HTML code.
541
542 [Grouped under "Rendering methods"]
543 """
544
aa064c9 @rstacruz Initial commit.
rstacruz authored
545 output = ""
546 try: spaces_count = int(self.parser.options.options['indent-spaces'])
547 except: spaces_count = 4
548 spaces = ' ' * spaces_count
549 indent = self.depth * spaces
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
550
551 prefix, suffix = ('', '')
552 if self.prefix: prefix = self.prefix + "\n"
553 if self.suffix: suffix = self.suffix
aa064c9 @rstacruz Initial commit.
rstacruz authored
554
6f969fb @rstacruz Added support for --start-guide-format and --end-guide-format (experimen...
rstacruz authored
555 # Make the guide from the ID (/#header), or the class if there's no ID (/.item)
556 # This is for the start-guide, end-guide and post-tag-guides
557 guide_str = ''
558 if 'id' in self.attributes:
559 guide_str += "#%s" % self.attributes['id']
560 elif 'class' in self.attributes:
561 guide_str += ".%s" % self.attributes['class'].replace(' ', '.')
562
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
563 # Build the post-tag guide (e.g., </div><!-- /#header -->),
564 # the start guide, and the end guide.
aa064c9 @rstacruz Initial commit.
rstacruz authored
565 guide = ''
6f969fb @rstacruz Added support for --start-guide-format and --end-guide-format (experimen...
rstacruz authored
566 start_guide = ''
567 end_guide = ''
568 if ((self.name == 'div') and \
aa064c9 @rstacruz Initial commit.
rstacruz authored
569 (('id' in self.attributes) or ('class' in self.attributes))):
570
6f969fb @rstacruz Added support for --start-guide-format and --end-guide-format (experimen...
rstacruz authored
571 if (self.parser.options.has('post-tag-guides')):
572 guide = "<!-- /%s -->" % guide_str
573
574 if (self.parser.options.has('start-guide-format')):
575 format = self.parser.options.get('start-guide-format')
576 try: start_guide = format % guide_str
577 except: start_guide = (format + " " + guide_str).strip()
578 start_guide = "%s<!-- %s -->\n" % (indent, start_guide)
579
580 if (self.parser.options.has('end-guide-format')):
581 format = self.parser.options.get('end-guide-format')
582 try: end_guide = format % guide_str
583 except: end_guide = (format + " " + guide_str).strip()
584 end_guide = "\n%s<!-- %s -->" % (indent, end_guide)
aa064c9 @rstacruz Initial commit.
rstacruz authored
585
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
586 # Short, self-closing tags (<br />)
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
587 short_tags = self.parser.dialect.short_tags
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
588
589 # When it should be expanded..
590 # (That is, <div>\n...\n</div> or similar -- wherein something must go
591 # inside the opening/closing tags)
aa064c9 @rstacruz Initial commit.
rstacruz authored
592 if len(self.children) > 0 \
593 or self.expand \
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
594 or prefix or suffix \
aa064c9 @rstacruz Initial commit.
rstacruz authored
595 or (self.parser.options.has('expand-divs') and self.name == 'div'):
596
597 for child in self.children:
598 output += child.render()
599
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
600 # For expand divs: if there are no children (that is, `output`
601 # is still blank despite above), fill it with a blank line.
aa064c9 @rstacruz Initial commit.
rstacruz authored
602 if (output == ''): output = indent + spaces + "\n"
603
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
604 # If we're a root node and we have a prefix or suffix...
605 # (Only the root node can have a prefix or suffix.)
606 if prefix or suffix:
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
607 output = "%s%s%s%s%s\n" % \
608 (indent, prefix, output, suffix, guide)
609
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
610 # Uh..
611 elif self.name != '' or \
612 self.opening_tag is not None or \
613 self.closing_tag is not None:
614 output = start_guide + \
615 indent + self.get_opening_tag() + "\n" + \
616 output + \
617 indent + self.get_closing_tag() + \
618 guide + end_guide + "\n"
619
620
594211b @rstacruz Added more short self-closing tags (like <meta />)
rstacruz authored
621 # Short, self-closing tags (<br />)
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
622 elif self.name in short_tags:
744520f @rstacruz Added input:button shortcut, fixed short tags (br)
rstacruz authored
623 output = "%s<%s />\n" % (indent, self.get_default_tag())
aa064c9 @rstacruz Initial commit.
rstacruz authored
624
625 # Tags with text, possibly
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
626 elif self.name != '' or \
627 self.opening_tag is not None or \
628 self.closing_tag is not None:
629 output = "%s%s%s%s%s%s%s%s" % \
630 (start_guide, indent, self.get_opening_tag(), \
631 self.text, \
632 self.get_closing_tag(), \
633 guide, end_guide, "\n")
aa064c9 @rstacruz Initial commit.
rstacruz authored
634
635 # Else, it's an empty-named element (like the root). Pass.
636 else: pass
637
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
638
aa064c9 @rstacruz Initial commit.
rstacruz authored
639 return output
640
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
641 def get_default_tag(self):
642 """Returns the opening tag (without brackets).
643
644 Usage:
645 element.get_default_tag()
646
647 [Grouped under "Rendering methods"]
648 """
649
aa064c9 @rstacruz Initial commit.
rstacruz authored
650 output = '%s' % (self.name)
651 for key, value in self.attributes.iteritems():
652 output += ' %s="%s"' % (key, value)
653 return output
654
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
655 def get_opening_tag(self):
656 if self.opening_tag is None:
657 return "<%s>" % self.get_default_tag()
658 else:
659 return self.opening_tag
660
661 def get_closing_tag(self):
662 if self.closing_tag is None:
663 return "</%s>" % self.name
664 else:
665 return self.closing_tag
666
aa064c9 @rstacruz Initial commit.
rstacruz authored
667 def append(self, object):
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
668 """Registers an element as a child of this element.
669
670 Usage:
671 element.append(child)
672
673 Description:
674 Adds a given element `child` to the children list of this element. It
675 will be rendered when [[render()]] is called on the element.
676
677 See also:
678 - [[get_last_child()]]
679
680 [Grouped under "Traversion methods"]
681 """
682
aa064c9 @rstacruz Initial commit.
rstacruz authored
683 self.children.append(object)
684
685 def get_last_child(self):
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
686 """Returns the last child element which was [[append()]]ed to this element.
687
688 Usage:
689 element.get_last_child()
690
691 Description:
692 This is the same as using `element.children[-1]`.
693
694 [Grouped under "Traversion methods"]
695 """
696
aa064c9 @rstacruz Initial commit.
rstacruz authored
697 return self.children[-1]
698
699 def _populate(self):
700 """Expands with default items.
701
702 This is called when the [[populate]] flag is turned on.
703 """
704
705 if self.name == 'ul':
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
706 elements = [Element(name='li', parent=self, parser=self.parser)]
aa064c9 @rstacruz Initial commit.
rstacruz authored
707
708 elif self.name == 'dl':
709 elements = [
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
710 Element(name='dt', parent=self, parser=self.parser),
711 Element(name='dd', parent=self, parser=self.parser)]
aa064c9 @rstacruz Initial commit.
rstacruz authored
712
713 elif self.name == 'table':
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
714 tr = Element(name='tr', parent=self, parser=self.parser)
715 td = Element(name='td', parent=tr, parser=self.parser)
aa064c9 @rstacruz Initial commit.
rstacruz authored
716 tr.children.append(td)
717 elements = [tr]
718
719 else:
720 elements = []
721
722 for el in elements:
723 self.children.append(el)
724
725 def _fill_attributes(self):
726 """Fills default attributes for certain elements.
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
727
728 Description:
729 This is called by the constructor.
730
731 [Protected, grouped under "Protected methods"]
aa064c9 @rstacruz Initial commit.
rstacruz authored
732 """
733
734 # Make sure <a>'s have a href, <img>'s have an src, etc.
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
735 required = self.parser.dialect.required
aa064c9 @rstacruz Initial commit.
rstacruz authored
736
737 for element, attribs in required.iteritems():
738 if self.name == element:
739 for attrib in attribs:
740 if attrib not in self.attributes:
741 self.attributes[attrib] = attribs[attrib]
742
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
743 # ---------------------------------------------------------------------------
744
745 # Property: last_child
746 # [Read-only]
aa064c9 @rstacruz Initial commit.
rstacruz authored
747 last_child = property(get_last_child)
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
748
749 # ---------------------------------------------------------------------------
750
751 # Property: parent
752 # (Element) The parent element.
aa064c9 @rstacruz Initial commit.
rstacruz authored
753 parent = None
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
754
755 # Property: name
756 # (String) The name of the element (e.g., `div`)
aa064c9 @rstacruz Initial commit.
rstacruz authored
757 name = ''
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
758
759 # Property: attributes
760 # (Dict) The dictionary of attributes (e.g., `{'src': 'image.jpg'}`)
aa064c9 @rstacruz Initial commit.
rstacruz authored
761 attributes = None
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
762
763 # Property: children
764 # (List of Elements) The children
aa064c9 @rstacruz Initial commit.
rstacruz authored
765 children = None
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
766
767 # Property: opening_tag
768 # (String or None) The opening tag. Optional; will use `name` and
769 # `attributes` if this is not given.
770 opening_tag = None
771
772 # Property: closing_tag
773 # (String or None) The closing tag
774 closing_tag = None
775
aa064c9 @rstacruz Initial commit.
rstacruz authored
776 text = ''
777 depth = -1
778 expand = False
779 populate = False
780 parser = None
781
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
782 # Property: prefix
783 # Only the root note can have this.
48dbb10 @rstacruz Added support for HTML tag prefixes/suffixes. You can now use sparkup on...
rstacruz authored
784 prefix = None
785 suffix = None
786
aa064c9 @rstacruz Initial commit.
rstacruz authored
787 # ===============================================================================
788
789 class Token:
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
790 def __init__(self, str, parser=None):
791 """Token.
792
793 Description:
794 str - The string to parse
795
796 In the string `div > ul`, there are 3 tokens. (`div`, `>`, and `ul`)
797
798 For `>`, it will be a `Token` with `type` set to `Token.CHILD`
799 """
800
aa064c9 @rstacruz Initial commit.
rstacruz authored
801 self.str = str.strip()
802 self.attributes = {}
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
803 self.parser = parser
aa064c9 @rstacruz Initial commit.
rstacruz authored
804
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
805 # Set the type.
aa064c9 @rstacruz Initial commit.
rstacruz authored
806 if self.str == '<':
807 self.type = Token.PARENT
808 elif self.str == '>':
809 self.type = Token.CHILD
810 elif self.str == '+':
811 self.type = Token.SIBLING
812 else:
813 self.type = Token.ELEMENT
814 self._init_element()
815
816 def _init_element(self):
817 """Initializes. Only called if the token is an element token.
818 [Private]
819 """
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
820
aa064c9 @rstacruz Initial commit.
rstacruz authored
821 # Get the tag name. Default to DIV if none given.
eba8aea @rstacruz Added numerous shortcuts; fixed classnames
rstacruz authored
822 name = re.findall('^([\w\-:]*)', self.str)[0]
823 name = name.lower().replace('-', ':')
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
824
825 # Find synonyms through this thesaurus
826 synonyms = self.parser.dialect.synonyms
827 if name in synonyms.keys():
828 name = synonyms[name]
829
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
830 if ':' in name:
831 try: spaces_count = int(self.parser.options.get('indent-spaces'))
832 except: spaces_count = 4
833 indent = ' ' * spaces_count
834
9b66f6c @rstacruz Implemented a thesaurus; moved HTML stuff into HtmlDialect
rstacruz authored
835 shortcuts = self.parser.dialect.shortcuts
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
836 if name in shortcuts.keys():
837 for key, value in shortcuts[name].iteritems():
838 setattr(self, key, value)
744520f @rstacruz Added input:button shortcut, fixed short tags (br)
rstacruz authored
839 if 'html' in name:
840 return
092e18f @rstacruz Added new shortcuts: form:get and form:post
rstacruz authored
841 else:
842 self.name = name
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
843
744520f @rstacruz Added input:button shortcut, fixed short tags (br)
rstacruz authored
844 elif (name == ''): self.name = 'div'
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
845 else: self.name = name
aa064c9 @rstacruz Initial commit.
rstacruz authored
846
c2f389f Fixed: A dot in an attribute adds a class.
Guillermo O. Freschi authored
847 # Look for attributes
848 attribs = []
849 for attrib in re.findall('\[([^\]]*)\]', self.str):
850 attribs.append(attrib)
851 self.str = self.str.replace("[" + attrib + "]", "")
852 if len(attribs) > 0:
853 for attrib in attribs:
854 try: key, value = attrib.split('=', 1)
9d50c59 Fixed Issue 2: Multiples Attributes not working
Guillermo O. Freschi authored
855 except: key, value = attrib, ''
856 self.attributes[key] = value
c2f389f Fixed: A dot in an attribute adds a class.
Guillermo O. Freschi authored
857
5807acc Fixed: A dot in text adds a class.
Guillermo O. Freschi authored
858 # Try looking for text
859 text = None
860 for text in re.findall('\{([^\}]*)\}', self.str):
861 self.str = self.str.replace("{" + text + "}", "")
862 if text is not None:
863 self.text = text
864
aa064c9 @rstacruz Initial commit.
rstacruz authored
865 # Get the class names
866 classes = []
867 for classname in re.findall('\.([\$a-zA-Z0-9_\-\&]+)', self.str):
868 classes.append(classname)
869 if len(classes) > 0:
eba8aea @rstacruz Added numerous shortcuts; fixed classnames
rstacruz authored
870 try: self.attributes['class']
871 except: self.attributes['class'] = ''
872 self.attributes['class'] += ' ' + ' '.join(classes)
873 self.attributes['class'] = self.attributes['class'].strip()
aa064c9 @rstacruz Initial commit.
rstacruz authored
874
875 # Get the ID
876 id = None
877 for id in re.findall('#([\$a-zA-Z0-9_\-\&]+)', self.str): pass
878 if id is not None:
879 self.attributes['id'] = id
880
881 # See if there's a multiplier (e.g., "li*3")
882 multiplier = None
883 for multiplier in re.findall('\*\s*([0-9]+)', self.str): pass
884 if multiplier is not None:
885 self.multiplier = int(multiplier)
886
887 # Populate flag (e.g., ul+)
888 flags = None
889 for flags in re.findall('[\+\!]+$', self.str): pass
890 if flags is not None:
891 if '+' in flags: self.populate = True
892 if '!' in flags: self.expand = True
893
894 def __str__(self):
895 return self.str
896
897 str = ''
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
898 parser = None
aa064c9 @rstacruz Initial commit.
rstacruz authored
899
900 # For elements
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
901 # See the properties of `Element` for description on these.
aa064c9 @rstacruz Initial commit.
rstacruz authored
902 name = ''
903 attributes = None
904 multiplier = 1
905 expand = False
906 populate = False
907 text = ''
4ac8ad6 @rstacruz Implemented shortcuts (html:xs, html:xxs, html:xt, html:5.. etc)
rstacruz authored
908 opening_tag = None
909 closing_tag = None
aa064c9 @rstacruz Initial commit.
rstacruz authored
910
911 # Type
912 type = 0
913 ELEMENT = 2
914 CHILD = 4
915 PARENT = 8
916 SIBLING = 16
917
918 # ===============================================================================
919
920 class Router:
921 """The router.
922 """
923
924 # Constructor
925 # ---------------------------------------------------------------------------
926
927 def __init__(self):
928 pass
929
930 # Methods
931 # ---------------------------------------------------------------------------
932
c813071 @rstacruz Added a simple unit test
rstacruz authored
933 def start(self, options=None, str=None, ret=None):
874d1ad @rstacruz TextMate bundle: Rewrote the command in Python
rstacruz authored
934 if (options):
935 self.options = Options(router=self, options=options, argv=None)
936 else:
937 self.options = Options(router=self, argv=sys.argv[1:], options=None)
aa064c9 @rstacruz Initial commit.
rstacruz authored
938
939 if (self.options.has('help')):
c813071 @rstacruz Added a simple unit test
rstacruz authored
940 return self.help()
aa064c9 @rstacruz Initial commit.
rstacruz authored
941
942 elif (self.options.has('version')):
c813071 @rstacruz Added a simple unit test
rstacruz authored
943 return self.version()
aa064c9 @rstacruz Initial commit.
rstacruz authored
944
945 else:
c813071 @rstacruz Added a simple unit test
rstacruz authored
946 return self.parse(str=str, ret=ret)
aa064c9 @rstacruz Initial commit.
rstacruz authored
947
948 def help(self):
949 print "Usage: %s [OPTIONS]" % sys.argv[0]
950 print "Expands input into HTML."
951 print ""
952 for short, long, info in self.options.cmdline_keys:
06b5857 @rstacruz The <!-- /#section --> guide tags are now off by default. Add --post-tag...
rstacruz authored
953 if "Deprecated" in info: continue
aa064c9 @rstacruz Initial commit.
rstacruz authored
954 if not short == '': short = '-%s,' % short
5d528a1 @rstacruz Fixed --help text
rstacruz authored
955 if not long == '': long = '--%s' % long.replace("=", "=XXX")
aa064c9 @rstacruz Initial commit.
rstacruz authored
956
6f969fb @rstacruz Added support for --start-guide-format and --end-guide-format (experimen...
rstacruz authored
957 print "%6s %-25s %s" % (short, long, info)
aa064c9 @rstacruz Initial commit.
rstacruz authored
958 print ""
959 print "\n".join(self.help_content)
960
961 def version(self):
962 print "Uhm, yeah."
963
c813071 @rstacruz Added a simple unit test
rstacruz authored
964 def parse(self, str=None, ret=None):
aa064c9 @rstacruz Initial commit.
rstacruz authored
965 self.parser = Parser(self.options)
966
967 try:
968 # Read the files
969 # for line in fileinput.input(): lines.append(line.rstrip(os.linesep))
c813071 @rstacruz Added a simple unit test
rstacruz authored
970 if str is not None:
971 lines = str
972 else:
973 lines = [sys.stdin.read()]
974 lines = " ".join(lines)
aa064c9 @rstacruz Initial commit.
rstacruz authored
975
976 except KeyboardInterrupt:
977 pass
978
979 except:
980 sys.stderr.write("Reading failed.\n")
981 return
982
983 try:
984 self.parser.load_string(lines)
985 output = self.parser.render()
c813071 @rstacruz Added a simple unit test
rstacruz authored
986 if ret: return output
aa064c9 @rstacruz Initial commit.
rstacruz authored
987 sys.stdout.write(output)
988
989 except:
990 sys.stderr.write("Parse error. Check your input.\n")
991 print sys.exc_info()[0]
813772f @rstacruz TextMate support; added --no-last-newline and --textmate arguments
rstacruz authored
992 print sys.exc_info()[1]
aa064c9 @rstacruz Initial commit.
rstacruz authored
993
994 def exit(self):
995 sys.exit()
996
997 help_content = [
998 "Please refer to the manual for more information.",
999 ]
1000
1001 # ===============================================================================
1002
1003 class Options:
874d1ad @rstacruz TextMate bundle: Rewrote the command in Python
rstacruz authored
1004 def __init__(self, router, argv, options=None):
aa064c9 @rstacruz Initial commit.
rstacruz authored
1005 # Init self
1006 self.router = router
1007
874d1ad @rstacruz TextMate bundle: Rewrote the command in Python
rstacruz authored
1008 # `options` can be given as a dict of stuff to preload
1009 if options:
1010 for k, v in options.iteritems():
1011 self.options[k] = v
1012 return
1013
aa064c9 @rstacruz Initial commit.
rstacruz authored
1014 # Prepare for getopt()
1015 short_keys, long_keys = "", []
1016 for short, long, info in self.cmdline_keys: # 'v', 'version'
1017 short_keys += short
1018 long_keys.append(long)
1019
1020 try:
1021 getoptions, arguments = getopt.getopt(argv, short_keys, long_keys)
6f969fb @rstacruz Added support for --start-guide-format and --end-guide-format (experimen...
rstacruz authored
1022
aa064c9 @rstacruz Initial commit.
rstacruz authored
1023 except getopt.GetoptError:
1024 err = sys.exc_info()[1]
1025 sys.stderr.write("Options error: %s\n" % err)
1026 sys.stderr.write("Try --help for a list of arguments.\n")
1027 return router.exit()
1028
1029 # Sort them out into options
1030 options = {}
3ac1922 @rstacruz --indent-spaces now works again
rstacruz authored
1031 i = 0
aa064c9 @rstacruz Initial commit.
rstacruz authored
1032 for option in getoptions:
1033 key, value = option # '--version', ''
6f969fb @rstacruz Added support for --start-guide-format and --end-guide-format (experimen...
rstacruz authored
1034 if (value == ''): value = True
aa064c9 @rstacruz Initial commit.
rstacruz authored
1035
1036 # If the key is long, write it
1037 if key[0:2] == '--':
1038 clean_key = key[2:]
6f969fb @rstacruz Added support for --start-guide-format and --end-guide-format (experimen...
rstacruz authored
1039 options[clean_key] = value
aa064c9 @rstacruz Initial commit.
rstacruz authored
1040
1041 # If the key is short, look for the long version of it
1042 elif key[0:1] == '-':
1043 for short, long, info in self.cmdline_keys:
1044 if short == key[1:]:
6f969fb @rstacruz Added support for --start-guide-format and --end-guide-format (experimen...
rstacruz authored
1045 print long
1046 options[long] = True
aa064c9 @rstacruz Initial commit.
rstacruz authored
1047
1048 # Done
1049 for k, v in options.iteritems():
1050 self.options[k] = v
6f969fb @rstacruz Added support for --start-guide-format and --end-guide-format (experimen...
rstacruz authored
1051
aa064c9 @rstacruz Initial commit.
rstacruz authored
1052 def __getattr__(self, attr):
6f969fb @rstacruz Added support for --start-guide-format and --end-guide-format (experimen...
rstacruz authored
1053 return self.get(attr)
1054
1055 def get(self, attr):
aa064c9 @rstacruz Initial commit.
rstacruz authored
1056 try: return self.options[attr]
1057 except: return None
1058
1059 def has(self, attr):
1060 try: return self.options.has_key(attr)
1061 except: return False
1062
1063 options = {
1064 'indent-spaces': 4
1065 }
1066 cmdline_keys = [
1067 ('h', 'help', 'Shows help'),
1068 ('v', 'version', 'Shows the version'),
06b5857 @rstacruz The <!-- /#section --> guide tags are now off by default. Add --post-tag...
rstacruz authored
1069 ('', 'no-guides', 'Deprecated'),
1070 ('', 'post-tag-guides', 'Adds comments at the end of DIV tags'),
813772f @rstacruz TextMate support; added --no-last-newline and --textmate arguments
rstacruz authored
1071 ('', 'textmate', 'Adds snippet info (textmate mode)'),
5d528a1 @rstacruz Fixed --help text
rstacruz authored
1072 ('', 'indent-spaces=', 'Indent spaces'),
aa064c9 @rstacruz Initial commit.
rstacruz authored
1073 ('', 'expand-divs', 'Automatically expand divs'),
813772f @rstacruz TextMate support; added --no-last-newline and --textmate arguments
rstacruz authored
1074 ('', 'no-last-newline', 'Skip the trailing newline'),
6f969fb @rstacruz Added support for --start-guide-format and --end-guide-format (experimen...
rstacruz authored
1075 ('', 'start-guide-format=', 'To be documented'),
1076 ('', 'end-guide-format=', 'To be documented'),
aa064c9 @rstacruz Initial commit.
rstacruz authored
1077 ]
1078
1079 # Property: router
1080 # Router
1081 router = 1
1082
1083 # ===============================================================================
1084
1085 if __name__ == "__main__":
1086 z = Router()
1087 z.start()
Something went wrong with that request. Please try again.