diff --git a/utils/get_snipmate_snippets.py b/utils/get_snipmate_snippets.py new file mode 100755 index 0000000..5606a51 --- /dev/null +++ b/utils/get_snipmate_snippets.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# encoding: utf-8 +""" + Convert snipmate compatible snippets to UltiSnips compatible snippets + by Phillip Berndt +""" +import sys +import re +import os + +def global_code_as_required(content): + " Return some global code for the resulting snippet. Only python support here.. " + if "`!p snip.rv = Filename" in content: + return "import os\n" + \ + """def Filename(fn, *args): + filename = os.path.splitext(fn)[0] + if filename == "": + return args[1] if len(args) == 2 else "" + return filename if len(args) == 0 or args[0] == "" else args[1].replace("$1", filename) + """ + +def convert_snippet_contents(content): + " If the snippet contains snipmate style substitutions, convert them to ultisnips style " + content = re.sub("`\s*Filename\(", "`!p snip.rv = Filename(fn, ", content) + content = re.sub("`(?!!)([^`]+`)", "`!v \g<1>", content) + return content + +def convert_snippet_file(source): + " One file per filetype " + retval = "" + state = 0 + for line in open(source).readlines(): + # Ignore empty lines + if line.strip() == "": + continue + # The rest of the handlig is stateful + if state == 0: + # Find snippet start + if line[:8] == "snippet ": + snippet_info = re.match("(\S+)\s*(.*)", line[8:]) + if not snippet_info: + print >> sys.stderr, "Warning: Malformed snippet\n %s\n" % line + continue + retval += 'snippet %s "%s"' % (snippet_info.group(1), snippet_info.group(2) if snippet_info.group(2) else snippet_info.group(1)) + "\n" + state = 1 + snippet = "" + elif state == 1: + # First line of snippet: Get indentation + whitespace = re.search("^\s+", line) + if not whitespace: + print >> sys.stderr, "Warning: Malformed snippet, content not indented.\n" + retval += "endsnippet\n\n" + state = 0 + else: + whitespace = whitespace.group(0) + snippet += line[len(whitespace):] + state = 2 + elif state == 2: + # In snippet: Check if indentation level is the same. If not, snippet has ended + if line[:len(whitespace)] != whitespace: + retval += convert_snippet_contents(snippet) + "endsnippet\n\n" + state = 0 + else: + snippet += line[len(whitespace):] + if state == 2: + retval += convert_snippet_contents(snippet) + "endsnippet\n\n" + return retval + +def convert_snippet(source): + " One file per snippet " + name = os.path.basename(source)[:-8] + return 'snippet %s "%s"' % (name, name) + "\n" + \ + convert_snippet_contents(open(source).read()) + \ + "\nendsnippet\n" + +def convert_snippets(source): + if os.path.isdir(source): + return "\n".join((convert_snippet(os.path.join(source, x)) for x in os.listdir(source) if x[-8:] == ".snippet")) + else: + return convert_snippet_file(source) + +if __name__ == '__main__': + if len(sys.argv) not in (3, 2): + print >> sys.stderr, "Syntax: get_snipmate_snippets.py [target file]" + print >> sys.stderr + sys.exit(1) + if len(sys.argv) == 2: + source = sys.argv[1] + target = sys.stdout + else: + source, target = sys.argv[1:] + target = open(target, "w") + + snippets = convert_snippets(source) + global_code = global_code_as_required(snippets) + if global_code: + print >> target, "global !p\n%s\nendglobal\n" % global_code + print >> target, snippets