99 lines
3.1 KiB
Python
99 lines
3.1 KiB
Python
|
#!/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 <source directory or file> [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
|