From f4934967798c0c68c535bc2fa6cb26fff82512ff Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Fri, 24 Apr 2009 20:31:41 +0900 Subject: [PATCH] Generic argument parsing and formatting --- geekigeeki.py | 76 +++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/geekigeeki.py b/geekigeeki.py index fbf3d93..8bd3e0b 100755 --- a/geekigeeki.py +++ b/geekigeeki.py @@ -33,7 +33,6 @@ file_re = re.compile(r"^\b([A-Za-z0-9_\-][A-Za-z0-9_\.\-/]*)\b$") img_re = re.compile(r"^.*\.(png|gif|jpg|jpeg|bmp|ico|ogm|ogg|mkv|mpg|mpeg|mp4|avi|asf|flv|wmv|qt)$", re.IGNORECASE) video_re = re.compile(r"^.*\.(ogm|ogg|mkv|mpg|mpeg|mp4|avi|asf|flv|wmv|qt)$", re.IGNORECASE) url_re = re.compile(r"^[a-z]{3,8}://[^\s'\"]+\S$") -link_re = re.compile(r"(?:\[\[|{{)([^\s\|]+)(?:\s*\|\s*([^\]]+)|)(?:\]\]|}})") ext_re = re.compile(r"\.([^\./]+)$") title_done = False @@ -83,6 +82,27 @@ def relative_url(pathname, privileged=False): def permalink(s): return re.sub(' ', '-', re.sub('[^a-z0-9_ ]', '', s.lower()).strip()) +# Split arg lists like "blah| blah blah| width=100 | align = center", +# return a list containing anonymous arguments and a map containing the named arguments +def parse_args(s): + args = [] + kwargs = {} + for arg in s.strip('<[{}]>').split('|'): + try: + key, val = arg.split('=', 1) + kwargs[key.strip()] = val.strip() + except ValueError: + args.append(arg.strip()) + return (args, kwargs) + +def url_args(kvargs): + argv = [] + for k, v in kvargs.items(): + argv.append(k + '=' + v) + if argv: + return '?' + '&'.join(argv) + return '' + # Formatting stuff -------------------------------------------------- def emit_header(mime_type="text/html"): print("Content-type: " + mime_type + "; charset=utf-8\n") @@ -175,7 +195,7 @@ def send_httperror(status="403 Not Found", query=""): send_title(None, msg_text=("%s: on query '%s'" % (status, query))) send_footer() -def link_tag(params, text=None, link_class=None, privileged=False): +def link_tag(params, text=None, link_class=None, privileged=False, **kvargs): if text is None: text = params # default elif img_re.match(text): @@ -197,13 +217,13 @@ def link_tag(params, text=None, link_class=None, privileged=False): return '%s' % (classattr, relative_url(params, privileged=privileged), text) -def link_inline(name, descr=None, args=''): +def link_inline(name, descr=None, kvargs={}): if not descr: descr = name url = relative_url(name) if video_re.match(name): return '' % url elif img_re.match(name): - return '%s' % (url, url + args, descr) + return '%s' % (url, url + url_args(kvargs), descr) elif file_re.match(name) and not ext_re.search(name): # FIXME: this guesses a wiki page return Page(name).send_naked() else: @@ -358,48 +378,34 @@ class WikiFormatter: return self._undent() + '\n
\n' % (len(word) - 2) def _macro_repl(self, word): - m = re.compile("\<\<([^\s\|\>]+)(?:\s*\|\s*([^\>]+)|)\>\>").match(word) - name = m.group(1) - argv = [name] - if m.group(2): - argv.extend(m.group(2).split('|')) - argv = list(map(str.strip, argv)) - - macro = globals().get('_macro_' + name) - if not macro: - try: + try: + args, kwargs = parse_args(word) + macro = globals().get('_macro_' + args[0]) + if not macro: exec(open("macros/" + name + ".py").read(), globals()) - except IOError as err: - if err.errno == errno.ENOENT: pass - macro = globals().get('_macro_' + name) - if macro: - return macro(argv) - else: - msg = '<<' + '|'.join(argv) + '>>' + macro = globals().get('_macro_' + name) + return macro(*args, **kwargs) + except Exception: + msg = cgi.escape(word) if not self.in_html: msg = '' + msg + '' return msg def _hurl_repl(self, word): - m = link_re.match(word) - return link_tag(m.group(1), m.group(2)) + args, kvargs = parse_args(word) + return link_tag(*args, **kvargs) def _inl_repl(self, word): - (name, descr) = link_re.match(word).groups() - - if descr: - argv = descr.split('|') - descr = argv.pop(0) - args = '' - if argv: - args = '?' + '&'.join(argv) - + args, kvargs = parse_args(word) + name = args.pop(0) + if len(args): + descr = args.pop(0) # The "extthumb" nonsense works around a limitation of the HTML block model return '
' \ - + link_inline(name, descr, args) \ + + link_inline(name, descr, kvargs) \ + '
' + descr + '
' else: - return link_inline(name, name) + return link_inline(name, None, kvargs) def _html_repl(self, word): if not self.in_html and word.startswith('