Created
June 27, 2021 16:47
-
-
Save infosec-intern/efb5af0a5cc94f5ffce87abd58c17032 to your computer and use it in GitHub Desktop.
Python script to convert an XML-based TextMate bundle to JSON format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
''' Convert an XML-based TextMate bundle to JSON format ''' | |
import argparse | |
import json | |
import xml.etree.ElementTree as ET | |
parser = argparse.ArgumentParser(description='Convert XML TM bundle to JSON TM bundle') | |
parser.add_argument('input', type=argparse.FileType('r')) | |
parser.add_argument('-o', '--output', type=argparse.FileType('w')) | |
args = parser.parse_args() | |
tree = ET.parse(args.input) | |
root = tree.getroot() | |
json_bundle = { | |
'fileTypes': [], | |
'name': None, | |
'scopeName': None, | |
'patterns': [], | |
'smartTypingPairs': [], | |
'highlightPairs': [] | |
} | |
# first find all the top-level keys for our JSON document | |
bundle = root.find('./dict') | |
for i in range(0, len(bundle)): | |
element = bundle[i] | |
if element.tag == 'key' and element.text == 'fileTypes': | |
# next element is an array of <string> filetypes | |
json_bundle['fileTypes'] = list(map(lambda x: x.text, bundle[i+1])) | |
elif element.tag == 'key' and element.text == 'array': | |
pass | |
elif element.tag == 'key' and element.text == 'name': | |
# next element is a <string> with the correct name | |
json_bundle['name'] = bundle[i+1].text | |
elif element.tag == 'key' and element.text == 'scopeName': | |
# next element is a <string> with the correct name | |
json_bundle['scopeName'] = bundle[i+1].text | |
elif element.tag == 'key' and element.text == 'smartTypingPairs': | |
# next element is an <array> of <array>s of <string> characters | |
json_bundle['smartTypingPairs'] = list(map(lambda x: [x[0].text, x[1].text], bundle[i+1])) | |
elif element.tag == 'key' and element.text == 'highlightPairs': | |
# next element is an <array> of <array>s of <string> characters | |
json_bundle['highlightPairs'] = list(map(lambda x: [x[0].text, x[1].text], bundle[i+1])) | |
elif element.tag == 'key' and element.text == 'patterns': | |
# next element is an <array> of <dict>s of <string> elements | |
# NOTE: this is incomplete. For example, sub-patterns are skipped | |
patterns = bundle[i+1] | |
CURR_KEY = None | |
for pattern_dict in patterns.iterfind('./dict'): | |
pattern = {} | |
for element in pattern_dict.iter(): | |
if element.tag == 'key': | |
CURR_KEY = element.text | |
elif element.tag == 'string': | |
pattern[CURR_KEY] = element.text | |
CURR_KEY = None | |
json_bundle['patterns'].append(pattern) | |
if args.output: | |
json.dump(json_bundle, args.output, indent=2) | |
else: | |
print(json.dumps(json_bundle, indent=2)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Specific to the VSCode implementation of TextMate bundles: https://code.visualstudio.com/api/language-extensions/syntax-highlight-guide