90 lines
2.1 KiB
Python
Executable File
90 lines
2.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import argparse
|
|
import io
|
|
import json
|
|
import os.path
|
|
import plistlib
|
|
import re
|
|
import urllib.request
|
|
from typing import Any
|
|
|
|
import cson # pip install cson
|
|
|
|
TOKEN = re.compile(br'(\\\\|\\"|"|//|\n)')
|
|
|
|
|
|
def json_with_comments(s: bytes) -> Any:
|
|
bio = io.BytesIO()
|
|
|
|
idx = 0
|
|
in_string = False
|
|
in_comment = False
|
|
|
|
match = TOKEN.search(s, idx)
|
|
while match:
|
|
if not in_comment:
|
|
bio.write(s[idx:match.start()])
|
|
|
|
tok = match[0]
|
|
if not in_comment and tok == b'"':
|
|
in_string = not in_string
|
|
elif in_comment and tok == b'\n':
|
|
in_comment = False
|
|
elif not in_string and tok == b'//':
|
|
in_comment = True
|
|
|
|
if not in_comment:
|
|
bio.write(tok)
|
|
|
|
idx = match.end()
|
|
match = TOKEN.search(s, idx)
|
|
|
|
print(bio.getvalue())
|
|
bio.seek(0)
|
|
return json.load(bio)
|
|
|
|
|
|
STRATEGIES = (json.loads, plistlib.loads, cson.loads, json_with_comments)
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('name')
|
|
parser.add_argument('url')
|
|
args = parser.parse_args()
|
|
|
|
if '/blob/' in args.url:
|
|
url = args.url.replace('/blob/', '/raw/')
|
|
else:
|
|
url = args.url
|
|
|
|
contents = urllib.request.urlopen(url).read()
|
|
|
|
errors = []
|
|
for strategy in STRATEGIES:
|
|
try:
|
|
loaded = strategy(contents)
|
|
except Exception as e:
|
|
errors.append((f'{strategy.__module__}.{strategy.__name__}', e))
|
|
else:
|
|
break
|
|
else:
|
|
errors_s = '\n'.join(f'\t{name}: {error}' for name, error in errors)
|
|
raise AssertionError(f'could not load as json/plist/cson:\n{errors_s}')
|
|
|
|
config_dir = os.path.expanduser('~/.config/babi')
|
|
os.makedirs(config_dir, exist_ok=True)
|
|
dest = os.path.join(config_dir, f'{args.name}.json')
|
|
with open(dest, 'w') as f:
|
|
json.dump(loaded, f)
|
|
|
|
theme_json = os.path.join(config_dir, 'theme.json')
|
|
if os.path.lexists(theme_json):
|
|
os.remove(theme_json)
|
|
os.symlink(dest, theme_json)
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
exit(main())
|