From d47f28f4db37b35546e78fdad1713fa8caa03081 Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Mon, 7 Mar 2011 23:53:21 +0100 Subject: [PATCH] Improve get_tm_snippets.py script: - add support for importing from local directory via two arguments: "dir/path" and "name" - add support for variable translation by fixed map - remove decode+encode from unescape(); this did not work with some string from the php.tmbundle - handle ElementTree.ParseError --- utils/get_tm_snippets.py | 85 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 77 insertions(+), 8 deletions(-) diff --git a/utils/get_tm_snippets.py b/utils/get_tm_snippets.py index 892462b..3684001 100755 --- a/utils/get_tm_snippets.py +++ b/utils/get_tm_snippets.py @@ -6,6 +6,9 @@ import re from xml.etree import ElementTree from xml.parsers.expat import ExpatError import htmlentitydefs +import os +import glob + _UNESCAPE = re.compile(ur'&\w+?;', re.UNICODE) def unescape(s): @@ -13,12 +16,43 @@ def unescape(s): return "" def fixup(m): ent = m.group(0)[1:-1] - print ent return unichr(htmlentitydefs.name2codepoint[ent]) try: - return _UNESCAPE.sub(fixup,s.decode("utf-8")).encode("utf-8") + return _UNESCAPE.sub(fixup,s) except: - print repr(s) + print "unescape failed: %s" % repr(s) + raise + +class UnknownVariable(Exception): + pass + +class UnsupportedVariableExpression(Exception): + pass + +def replace_vars(m): + """ Replace vars in 'content' portion. + :m: match object + :returns: string""" + var = m.group(1) + default = m.group(2) + + if not re.match(r'\w+$', var): + raise UnsupportedVariableExpression(var) + + translate_vars = { + 'TM_PHP_OPEN_TAG_WITH_ECHO': 'g:UltiSnipsOpenTagWithEcho', + 'TM_PHP_OPEN_TAG': 'g:UltiSnipsOpenTag', + 'PHPDOC_AUTHOR': 'g:snips_author', + } + # TODO: TM_SELECTED_TEXT/([\t ]*).*/$1/m + + if var in translate_vars: + newvar = translate_vars[var] + else: + # TODO: this could be autogenerated + raise UnknownVariable(var) + + return "`!v exists('%s') ? %s : '%s'`" % (newvar, newvar, default) def parse_content(c): try: @@ -28,12 +62,22 @@ def parse_content(c): for k,v in zip(data[::2], data[1::2]): rv[k.text] = unescape(v.text) + if re.search( r'\$\{\D', rv["content"] ): + rv["content"] = re.sub(r'\$\{([^\d}][^}:]*)(?::([^}]*))?\}', replace_vars, rv["content"]) + return rv - except ExpatError: - print " Syntax Error" + except (ExpatError, ElementTree.ParseError) as detail: + print " Syntax Error: %s" % (detail,) + print c + return None + except UnknownVariable as detail: + print " Unknown variable: %s" % (detail,) + return None + except UnsupportedVariableExpression as detail: + print " Unsupported variable expression: %s" % (detail,) return None -def fetch_snippets(name): +def fetch_snippets_from_svn(name): base_url = "http://svn.textmate.org/trunk/Bundles/" + name + ".tmbundle/" snippet_idx = base_url + "Snippets/" @@ -57,6 +101,20 @@ def fetch_snippets(name): return rv +def fetch_snippets_from_dir(path): + """ Fetch snippets from a given path""" + + rv = [] + for filename in glob.glob(os.path.join(path, '*.tmSnippet')): + print "Reading file %s" % filename + f = open(filename) + content = f.read() + + cont = parse_content(content) + if cont: + name = os.path.splitext(os.path.basename(filename))[0] + rv.append((name, cont)) + return rv def write_snippets(snip_descr, f): @@ -64,6 +122,10 @@ def write_snippets(snip_descr, f): if "tabTrigger" not in d: continue + if "content" not in d or d["content"] is None: + print "SKIP: %s (no content)" % (d,) + continue + f.write('snippet %s "%s"\n' % (d["tabTrigger"], name)) f.write(d["content"].encode("utf-8") + "\n") f.write("endsnippet\n\n") @@ -74,6 +136,13 @@ if __name__ == '__main__': import sys bundle = sys.argv[1] - rv = fetch_snippets(bundle) - write_snippets(rv, open("tm_" + bundle.lower() + ".snippets","w")) + + if os.path.isdir(bundle): + name = sys.argv[2] + rv = fetch_snippets_from_dir(bundle) + else: + rv = fetch_snippets_from_svn(bundle) + name = bundle.lower() + + write_snippets(rv, open("tm_" + name + ".snippets","w"))