Created
November 7, 2017 21:31
-
-
Save evandrocoan/eba23f91b7afbc8f324b318ebddf9800 to your computer and use it in GitHub Desktop.
Scheme Converter
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
""" | |
Convert Color Scheme. | |
Licensed under MIT. | |
Copyright (C) 2017 Isaac Muse <[email protected]> | |
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated | |
documentation files (the "Software"), to deal in the Software without restriction, including without limitation | |
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and | |
to permit persons to whom the Software is furnished to do so, subject to the following conditions: | |
The above copyright notice and this permission notice shall be included in all copies or substantial portions of | |
the Software. | |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO | |
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
""" | |
from __future__ import absolute_import | |
import sublime | |
import sublime_plugin | |
import re | |
from os import path | |
from os import makedirs | |
from plistlib import readPlistFromBytes | |
import codecs | |
TEMP_FOLDER = "sublime_color_scheme_format" | |
TEMP_PATH = "Packages/User/%s" % TEMP_FOLDER | |
GLOBAL_OPTIONS = "globals" | |
# XML | |
XML_COMMENT_RE = re.compile(br"^[\r\n\s]*<!--[\s\S]*?-->[\s\r\n]*|<!--[\s\S]*?-->") | |
RE_CAMEL_CASE = re.compile('[A-Z]') | |
RE_SNAKE_CASE = re.compile('_(.)') | |
def packages_path(pth): | |
"""Get packages path.""" | |
return path.join(path.dirname(sublime.packages_path()), path.normpath(pth)) | |
def to_snake(m): | |
"""Convert to snake case.""" | |
return '_' + m.group(0).lower() | |
def to_camel(m): | |
"""Convert to camel case.""" | |
return m.group(1).Upper() | |
def get_tmtheme(scheme): | |
"""Get old tmtheme style.""" | |
tmtheme = { | |
"settings": [ | |
{ | |
"settings": {} | |
} | |
] | |
} | |
for k, v in scheme.get("globals", {}).items(): | |
tmtheme["settings"]["settings"][RE_SNAKE_CASE.sub(to_camel, k)] = v | |
for k, v in scheme.items(): | |
if k in ('variables', 'rules', "globals"): | |
continue | |
tmtheme[k] = v | |
for rule in scheme["rules"]: | |
entry = {} | |
name = rule.get('name') | |
scope = rule.get('scope') | |
if name: | |
entry['name'] = name | |
if scope: | |
entry['scope'] = scope | |
entry['settings'] = {} | |
foreground = rule.get('foreground') | |
background = rule.get('background') | |
fontstyle = rule.get("font_style") | |
selection_foreground = rule.get('selection_foreground') | |
if foreground and isinstance(foreground, str): | |
entry['settings']['foreground'] = foreground | |
if selection_foreground: | |
entry['selectionForeground'] = selection_foreground | |
if background: | |
entry['settings']['background'] = background | |
if fontstyle: | |
entry['settings']['fontStyle'] = fontstyle | |
tmtheme['settings'].append(entry) | |
return tmtheme | |
def sublime_format_path(pth): | |
"""Format path for sublime internal use.""" | |
m = re.match(r"^([A-Za-z]{1}):(?:/|\\)(.*)", pth) | |
if sublime.platform() == "windows" and m is not None: | |
pth = m.group(1) + "/" + m.group(2) | |
return pth.replace("\\", "/") | |
class ConvertSublimeColorSchemeFormat(object): | |
"""Determine color scheme colors and style for text in a Sublime view buffer.""" | |
def __init__(self, scheme_file): | |
"""Initialize.""" | |
self.color_scheme = path.normpath(scheme_file) | |
self.base_name = path.basename(self.color_scheme) | |
assert not scheme_file.endswith('.sublime-color-scheme'), "Scheme not the correct format!" | |
content = sublime.load_binary_resource(sublime_format_path(self.color_scheme)) | |
self.legacy = True | |
self.convert_format(readPlistFromBytes(XML_COMMENT_RE.sub(b'', content))) | |
self.scheme_file = scheme_file | |
def convert_format(self, obj): | |
"""Convert tmTheme object to new format.""" | |
self.scheme_obj = { | |
"variables": {}, | |
"globals": {}, | |
"rules": [] | |
} | |
for k, v in obj.items(): | |
if k == "settings": | |
continue | |
self.scheme_obj[k] = v | |
for item in obj["settings"]: | |
if item.get('scope', None) is None and item.get('name', None) is None: | |
for k, v in item["settings"].items(): | |
self.scheme_obj["globals"][RE_CAMEL_CASE.sub(to_snake, k)] = v | |
if 'settings' in item and item.get('scope') is not None: | |
rule = {} | |
name = item.get('name') | |
if name is not None: | |
rule['name'] = name | |
scope = item.get('scope') | |
if scope is not None: | |
rule["scope"] = scope | |
fg = item['settings'].get('foreground') | |
if fg is not None: | |
rule['foreground'] = item['settings'].get('foreground') | |
bg = item['settings'].get('background') | |
if bg is not None: | |
rule['background'] = bg | |
selfg = item["settings"].get("selectionForeground") | |
if selfg is not None: | |
rule["selection_foreground"] = selfg | |
font_style = item["settings"].get('fontStyle') | |
if font_style is not None: | |
rule['font_style'] = font_style | |
self.scheme_obj['rules'].append(rule) | |
def get_scheme_obj(self): | |
"""Get the scheme file used during the process.""" | |
return self.scheme_obj | |
def get_scheme_file(self): | |
"""Get the scheme file used during the process.""" | |
return self.scheme_file | |
class ConvertSublimeColorSchemeCommand(sublime_plugin.TextCommand): | |
"""Convert tmTheme file from the active view to sublime-color-scheme format.""" | |
def run(self, edit): | |
"""Run the command.""" | |
temp = packages_path(TEMP_PATH) | |
if not path.exists(temp): | |
makedirs(temp) | |
scheme = self.view.settings().get("color_scheme") | |
if scheme is None: | |
pref_settings = sublime.load_settings('Preferences.sublime-settings') | |
scheme = pref_settings.get('color_scheme') | |
try: | |
converter = ConvertSublimeColorSchemeFormat(scheme) | |
except Exception: | |
return | |
name = packages_path(path.join(TEMP_PATH, path.splitext(converter.base_name)[0] + '.sublime-color-scheme')) | |
with codecs.open(name, "w", encoding='utf-8') as f: | |
f.write(sublime.encode_value(converter.get_scheme_obj(), pretty=True)) | |
class ConvertAllSublimeColorSchemeCommand(sublime_plugin.ApplicationCommand): | |
"""Convert all tmTheme files to sublime-color-scheme format.""" | |
def run(self): | |
"""Run the command.""" | |
temp = packages_path(TEMP_PATH) | |
if not path.exists(temp): | |
makedirs(temp) | |
# Skip User folder | |
for scheme in sublime.find_resources('*.tmTheme'): | |
if scheme.startswith('Packages/User/'): | |
continue | |
try: | |
converter = ConvertSublimeColorSchemeFormat(scheme) | |
except Exception: | |
return | |
name = packages_path(path.join(TEMP_PATH, path.splitext(converter.base_name)[0] + '.sublime-color-scheme')) | |
with codecs.open(name, "w", encoding='utf-8') as f: | |
f.write(sublime.encode_value(converter.get_scheme_obj(), pretty=True)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment