def config_schema(): return { "highlight_selected_text": { "enabled": Boolean(default=True), "color": Color(default=get_color("FEFF6B")), }, "indent": { "mode": Enum(const.INDENT_MODE_SPACE, const.INDENT_MODE_TAB, default=const.INDENT_MODE_SPACE), "size": Integer(default=4, minimum=1), }, "newline_mode": Enum(const.NEWLINE_MODE_UNIX, const.NEWLINE_MODE_MAC, const.NEWLINE_MODE_WINDOWS, const.NEWLINE_MODE_UNICODE, default=const.NEWLINE_MODE_UNIX), "right_margin": { "position": Integer(default=const.DEFAULT_RIGHT_MARGIN, minimum=0), "line_color": Color(default=get_color("E6E6E6")), "margin_color": Color(default=get_color("F7F7F7")), }, "soft_wrap": Enum(const.WRAP_NONE, const.WRAP_WORD, default=const.WRAP_NONE), }
def config_schema(): return { "highlight_selected_text": { "enabled": Boolean(default=True), "color": Color(default=get_color("FEFF6B")), }, "indent": { "mode": Enum( const.INDENT_MODE_SPACE, const.INDENT_MODE_TAB, default=const.INDENT_MODE_SPACE), "size": Integer(default=4, minimum=1), }, "newline_mode": Enum( const.NEWLINE_MODE_UNIX, const.NEWLINE_MODE_MAC, const.NEWLINE_MODE_WINDOWS, const.NEWLINE_MODE_UNICODE, default=const.NEWLINE_MODE_UNIX), "right_margin": { "position": Integer(default=const.DEFAULT_RIGHT_MARGIN, minimum=0), "line_color": Color(default=get_color("E6E6E6")), "margin_color": Color(default=get_color("F7F7F7")), }, "soft_wrap": Enum( const.WRAP_NONE, const.WRAP_WORD, default=const.WRAP_NONE), } class Type(object):
def test_Config_default_config(): schema = { "group": { "bool": mod.Boolean(default=False), "enum": mod.Enum(("abc", 1), ("def", 2), ("ghi", 1), default=1), "color": mod.Color(default=get_color("0EFF6B")), "sub": { "int": mod.Integer(default=42), } }, "hidden": mod.NOT_SET, "int": mod.Integer(default=42), "str": mod.String(default="the answer"), } config = mod.Config("/tmp/missing.3216546841325465132546514321654", schema) eq_(config.default_config, "#group:\n" "# bool: false\n" "# color: 0EFF6B\n" "# enum: abc\n" "# sub:\n" "# int: 42\n" "\n" "\n" "#int: 42\n" "#str: the answer\n" )
def selection_secondary_color(config): """Unused proof of concept Derived theme value that can be overridden in the config """ value = config.get("theme.selection_secondary_color", Color(None)) if value is None: color = hex_value(config["theme.selection_color"]) value = get_color(rgb2gray(color)) return value
def validate(self, value, key): if value is NOT_SET: value = self.default if value is NOT_SET: return value try: return get_color(value) except Exception: log.error("cannot parse color: %r", value, exc_info=True) raise ValueError("{}: expected RRGGBB hex color string, got {!r}" .format(key, value))
def validate(self, value, key): if value is NOT_SET: value = self.default if value is NOT_SET: return value try: return get_color(value) except Exception: log.error("cannot parse color: %r", value, exc_info=True) raise ValueError( "{}: expected RRGGBB hex color string, got {!r}".format( key, value))
def test_Type_validate(): NOT_SET = mod.NOT_SET def test(Type, input, value, default=NOT_SET): if default is NOT_SET: type_ = Type() else: type_ = Type(default=default) if isinstance(value, Exception): with assert_raises(type(value), msg=str(value)): type_.validate(input, "key") else: eq_(type_.validate(input, "key"), value) yield test, mod.Boolean, True, True yield test, mod.Boolean, True, True yield test, mod.Boolean, False, False yield test, mod.Boolean, "true", True yield test, mod.Boolean, "false", False yield test, mod.Boolean, "yes", True yield test, mod.Boolean, "no", False yield test, mod.Boolean, NOT_SET, NOT_SET yield test, mod.Boolean, NOT_SET, True, True yield test, mod.Boolean, NOT_SET, None, None yield test, mod.Boolean, 42, ValueError("key: expected boolean, got 42") yield test, mod.Boolean, "null", \ ValueError("key: expected boolean, got 'null'") yield test, mod.String, "true", "true" yield test, mod.String, NOT_SET, NOT_SET yield test, mod.String, NOT_SET, "abc", "abc" yield test, mod.String, NOT_SET, None, None yield test, mod.String, 42, ValueError("key: expected string, got 42") yield test, mod.Integer, 42, 42 yield test, mod.Integer, NOT_SET, NOT_SET yield test, mod.Integer, NOT_SET, "abc", "abc" yield test, mod.Integer, NOT_SET, None, None yield test, mod.Integer, 'x', ValueError("key: expected integer, got 'x'") yield test, mod.Float, 42, 42.0 yield test, mod.Float, 42.1, 42.1 yield test, mod.Float, NOT_SET, NOT_SET yield test, mod.Float, NOT_SET, "abc", "abc" yield test, mod.Float, NOT_SET, None, None yield test, mod.Float, 'x', ValueError("key: expected float, got 'x'") yield test, mod.Color, "FEFF6B", get_color("FEFF6B") yield test, mod.Color, "x", \ ValueError("key: expected RRGGBB hex color string, got 'x'") yield test, mod.Enum, NOT_SET, NOT_SET
def test_Type_validate(): NOT_SET = mod.NOT_SET def test(Type, input, value, default=NOT_SET): if default is NOT_SET: type_ = Type() else: type_ = Type(default=default) if isinstance(value, Exception): with assert_raises(type(value), msg=str(value)): type_.validate(input, "key") else: eq_(type_.validate(input, "key"), value) yield test, mod.Boolean, True, True yield test, mod.Boolean, True, True yield test, mod.Boolean, False, False yield test, mod.Boolean, "true", True yield test, mod.Boolean, "false", False yield test, mod.Boolean, "yes", True yield test, mod.Boolean, "no", False yield test, mod.Boolean, NOT_SET, NOT_SET yield test, mod.Boolean, NOT_SET, True, True yield test, mod.Boolean, NOT_SET, None, None yield test, mod.Boolean, 42, ValueError("key: expected boolean, got 42") yield test, mod.Boolean, "null", \ ValueError("key: expected boolean, got 'null'") yield test, mod.String, "true", "true" yield test, mod.String, NOT_SET, NOT_SET yield test, mod.String, NOT_SET, "abc", "abc" yield test, mod.String, NOT_SET, None, None yield test, mod.String, 42, ValueError("key: expected string, got 42") yield test, mod.Integer, 42, 42 yield test, mod.Integer, NOT_SET, NOT_SET yield test, mod.Integer, NOT_SET, "abc", "abc" yield test, mod.Integer, NOT_SET, None, None yield test, mod.Integer, 'x', ValueError("key: expected integer, got 'x'") yield test, mod.Color, "FEFF6B", get_color("FEFF6B") yield test, mod.Color, "x", \ ValueError("key: expected RRGGBB hex color string, got 'x'") yield test, mod.Enum, NOT_SET, NOT_SET
def test_Config_default_config(): schema = { "group": { "bool": mod.Boolean(default=False), "enum": mod.Enum(("abc", 1), ("def", 2), ("ghi", 1), default=1), "color": mod.Color(default=get_color("0EFF6B")), }, "hidden": mod.NOT_SET, "int": mod.Integer(default=42), "str": mod.String(default="the answer"), } config = mod.Config("/tmp/missing.3216546841325465132546514321654", schema) eq_( config.default_config, "#group:\n" "# bool: false\n" "# color: 0EFF6B\n" "# enum: abc\n" "\n" "#int: 42\n" "#str: the answer\n")
def get_syntax_color(self, name): try: value = self.default[name] except KeyError: lang, token_name = name.rsplit(" ", 1) if token_name: value = self._get(lang, token_name) if value is None: value = self._get("default", token_name) if value is not None: try: value = get_color(value) except Exception: log.warn("unknown color: %s -> %r", name, value) value = None if value is None: if "background" in name.lower(): value = self.background_color else: value = self.text_color else: value = self.text_color self.default[name] = value return value
def test_Config_schema(): def test(data, key, value, errors={}): config = mod.Config("/tmp/missing.3216546841325465132546514321654") config.data = data with CaptureLog(mod) as log: if isinstance(value, Exception): with assert_raises(type(value), msg=str(value)): config[key] else: eq_(config[key], value) eq_(log.data, errors) yield test, {}, "unknown", KeyError("unknown") yield test, {}, "unknown.sub", KeyError("unknown.sub") yield test, {}, "highlight_selected_text.enabled", True yield test, {"highlight_selected_text": {}}, \ "highlight_selected_text.enabled", True yield test, {"highlight_selected_text": {"enabled": True}}, \ "highlight_selected_text.enabled", True yield test, {"highlight_selected_text": []}, \ "highlight_selected_text.enabled", True, \ {"error": ["highlight_selected_text: expected dict, got []"]} yield test, {"highlight_selected_text": {"enabled": "treu"}}, \ "highlight_selected_text.enabled", True, \ {"error": ["highlight_selected_text.enabled: expected boolean, got 'treu'"]} yield test, {"highlight_selected_text": True}, \ "highlight_selected_text.enabled", True, \ {"error": ["highlight_selected_text: expected dict, got True"]} yield test, {}, "highlight_selected_text.enabled.x", \ ValueError("highlight_selected_text.enabled.x: " "highlight_selected_text.enabled is boolean, not a dict") yield test, {}, "indent.mode", const.INDENT_MODE_SPACE yield test, {"indent": {"mode": "xyz"}}, \ "indent.mode", const.INDENT_MODE_SPACE, \ {"error": ["indent.mode: expected one of (space|tab), got 'xyz'"]} yield test, {}, "indent.size", 4 yield test, {"indent": {"size": "two"}}, "indent.size", 4, \ {"error": ["indent.size: expected integer, got 'two'"]} yield test, {"indent": {"size": 0}}, "indent.size", 4, \ {"error": ["indent.size: 0 is less than the minimum value (1)"]} yield test, {}, "newline_mode", const.NEWLINE_MODE_UNIX yield test, {"newline_mode": "xyz"}, \ "newline_mode", const.NEWLINE_MODE_UNIX, \ {"error": ["newline_mode: expected one of (LF|CR|CRLF|UNICODE), got 'xyz'"]} yield test, {}, "right_margin.position", const.DEFAULT_RIGHT_MARGIN yield test, {"right_margin": {"position": 42}}, "right_margin.position", 42 yield test, {"right_margin": {"position": "xyz"}}, \ "right_margin.position", const.DEFAULT_RIGHT_MARGIN, \ {"error": ["right_margin.position: expected integer, got 'xyz'"]} yield test, {}, "right_margin.line_color", get_color("E6E6E6") yield test, {}, "right_margin.margin_color", get_color("F7F7F7") yield test, {}, "soft_wrap", const.WRAP_NONE yield test, {"soft_wrap": "xyz"}, \ "soft_wrap", const.WRAP_NONE, \ {"error": ["soft_wrap: expected one of (none|word), got 'xyz'"]}
def test_Config_schema(): eq_(configify({"indent.mode": "xyz"}), {"indent": {"mode": "xyz"}}) def test(data, key, value, errors={}, stop=[1]): config = mod.Config("/tmp/missing.3216546841325465132546514321654") config.data = configify(data) config.transform_deprecations() with CaptureLog(mod) as log: if isinstance(value, Exception): with assert_raises(type(value), msg=str(value)): config[key] else: eq_(config[key], value) eq_(dict(log.data), errors) yield test, {}, "unknown", KeyError("unknown") yield test, {}, "unknown.sub", KeyError("unknown.sub") yield test, {}, "theme.highlight_selected_text.enabled", True yield test, {"theme.highlight_selected_text": {}}, \ "theme.highlight_selected_text.enabled", True yield test, {"theme.highlight_selected_text": {"enabled": True}}, \ "theme.highlight_selected_text.enabled", True yield test, {"theme.highlight_selected_text": []}, \ "theme.highlight_selected_text.enabled", True, \ {"error": ["theme.highlight_selected_text: expected dict, got []"]} yield test, {"theme.highlight_selected_text": {"enabled": "treu"}}, \ "theme.highlight_selected_text.enabled", True, \ {"error": ["theme.highlight_selected_text.enabled: expected boolean, got 'treu'"]} yield test, {"theme.highlight_selected_text": True}, \ "theme.highlight_selected_text.enabled", True, \ {"error": ["theme.highlight_selected_text: expected dict, got True"]} yield test, {}, "theme.highlight_selected_text.enabled.x", \ ValueError("theme.highlight_selected_text.enabled.x: " "theme.highlight_selected_text.enabled is boolean, not a dict") # deprecated settings should still work yield test, {"highlight_selected_text": {"enabled": False}}, \ "theme.highlight_selected_text.enabled", False yield test, {"highlight_selected_text": {"color": get_color("FFEEFF")}}, \ "theme.highlight_selected_text.color", get_color("FFEEFF") yield test, {}, "indent.mode", const.INDENT_MODE_SPACE yield test, {"indent": {"mode": "xyz"}}, \ "indent.mode", const.INDENT_MODE_SPACE, \ {"error": ["indent.mode: expected one of (space|tab), got 'xyz'"]} yield test, {}, "indent.size", 4 yield test, {"indent.size": "two"}, "indent.size", 4, \ {"error": ["indent.size: expected integer, got 'two'"]} yield test, {"indent.size": 0}, "indent.size", 4, \ {"error": ["indent.size: 0 is less than the minimum value (1)"]} yield test, {}, "newline_mode", const.NEWLINE_MODE_UNIX yield test, {"newline_mode": "xyz"}, \ "newline_mode", const.NEWLINE_MODE_UNIX, \ {"error": ["newline_mode: expected one of (LF|CR|CRLF|UNICODE), got 'xyz'"]} yield test, {}, "theme.right_margin.position", const.DEFAULT_RIGHT_MARGIN yield test, {"theme.right_margin": {"position": 42}}, "theme.right_margin.position", 42 yield test, {"theme.right_margin": {"position": "xyz"}}, \ "theme.right_margin.position", const.DEFAULT_RIGHT_MARGIN, \ {"error": ["theme.right_margin.position: expected integer, got 'xyz'"]} # deprecated key should still work yield test, {"right_margin": {"position": 42}}, "theme.right_margin.position", 42 yield test, {}, "theme.right_margin.line_color", get_color("E6E6E6") yield test, {}, "theme.right_margin.margin_color", get_color("F7F7F7") # deprecated key should still work yield test, {"right_margin.line_color": get_color("eeeeee")}, \ "theme.right_margin.line_color", get_color("eeeeee") yield test, {"right_margin.margin_color": get_color("eeeeee")}, \ "theme.right_margin.margin_color", get_color("eeeeee") yield test, {}, "soft_wrap", const.WRAP_NONE yield test, {"soft_wrap": "xyz"}, \ "soft_wrap", const.WRAP_NONE, \ {"error": ["soft_wrap: expected one of (none|word), got 'xyz'"]} yield test, {}, "updates_path_on_file_move", True yield test, {}, "diff_program", "opendiff" yield test, {"diff_program": "gdiff -u"}, "diff_program", "gdiff -u"
def __init__(self, filename, name, filepatterns, word_groups=(), delimited_ranges=(), comment_token="", disabled=False, flags=0): """Syntax definition arguments: word_groups - a sequence of two-tuples associating word-tokens with a color: [ (['word1', 'word2'], <RRGGBB color string>) ] delimited_ranges - a list of four-tuples associating a set of delimiters with a color and a syntax definition: [ ( <start delimiter>, <list of end delimiters>, <RRGGBB color string>, <SyntaxDefinition instance> or None ), ('<!--', ['-->'], 'RRGGBB', None), ('"', ['"', '\n'], 'RRGGBB', None), ('<?', ['?>'], 'RRGGBB', "php"), ] """ super(SyntaxDefinition, self).__init__(name, comment_token, disabled) def escape(token): if hasattr(token, "pattern"): return token.pattern token = re.escape(token) return token.replace(re.escape("\n"), "\\n") namegen = ("g%i" % i for i in count()) self.filename = filename self.filepatterns = set(filepatterns) self.word_groups = list(word_groups) self.delimited_ranges = list(delimited_ranges) self.wordinfo = wordinfo = {} flags |= re.DOTALL groups = [] word_char = re.compile(r"\w") for tokens, color in word_groups: name = next(namegen) color = get_color(color) wordgroup = [] for token in tokens: if hasattr(token, "pattern"): word = token.pattern else: word = escape(token) if word_char.match(token[0]): word = r"\b" + word if word_char.match(token[-1]): word = word + r"\b" wordgroup.append(word) groups.append("(?P<%s>%s)" % (name, "|".join(wordgroup))) wordinfo[name] = (color, name) for start, ends, color, sdef in delimited_ranges: name = next(namegen) color = get_color(color) phrase = "(?P<%s>(%s).*?(%s))" % ( name, escape(start), "|".join(escape(token) for token in chain(ends, [RE("$")])) ) groups.append(phrase) endxp = re.compile(".*?" + "|".join(escape(token) for token in ends), flags) wordinfo[name] = (color, name) #, endxp) self.regex = re.compile("|".join(groups), flags)
def config_schema(): return { "diff_program": String("opendiff"), "indent": { "mode": Enum( const.INDENT_MODE_SPACE, const.INDENT_MODE_TAB, default=const.INDENT_MODE_SPACE), "size": Integer(default=4, minimum=1), }, "font": { "face": String(default=DEFAULT_FONT.face), "size": Float(minimum=-1.0, default=DEFAULT_FONT.size), "smooth": Boolean(default=DEFAULT_FONT.smooth), }, "newline_mode": Enum( const.NEWLINE_MODE_UNIX, const.NEWLINE_MODE_MAC, const.NEWLINE_MODE_WINDOWS, const.NEWLINE_MODE_UNICODE, default=const.NEWLINE_MODE_UNIX), "theme": { "text_color": Color(default=platform.COLOR.text_color), "selection_color": Color(default=platform.COLOR.selection_color), "background_color": Color(default=platform.COLOR.background_color), "visited_link_color": Color(default=get_color("720E74")), "highlight_selected_text": { "enabled": Boolean(default=True), "color": Color(default=get_color("FEFF6B")), }, "line_number_color": Color(default=get_color("707070")), "right_margin": { "position": Integer(default=const.DEFAULT_RIGHT_MARGIN, minimum=0), "line_color": Color(default=get_color("E6E6E6")), "margin_color": Color(default=get_color("F7F7F7")), }, "syntax": { "default": { "attribute": ColorString("004080"), "builtin": ColorString("000080"), "comment": ColorString("008000"), "group": ColorString("CC0066"), "header": ColorString("D32E1B"), "identifier": ColorString("720E74"), "keyword": ColorString("0000CC"), "name": ColorString("800000"), "operator": ColorString("CC0066"), "operator.escape": ColorString("EE8000"), "preprocessor": ColorString("78492A"), "punctuation": ColorString("606000"), "string": ColorString("008080"), "tag": ColorString("800000"), "regexp": ColorString("804000"), "value": ColorString("400080"), "variable": ColorString("800080"), "red": ColorString("CC0000"), "orange": ColorString("EE8000"), "yellow": ColorString("FFFF00"), "green": ColorString("008000"), "blue": ColorString("0000FF"), "navy": ColorString("000080"), "purple": ColorString("800080"), "brown": ColorString("804000"), "gray": ColorString("666666"), } } }, "soft_wrap": Enum( const.WRAP_NONE, const.WRAP_WORD, default=const.WRAP_NONE), "updates_path_on_file_move": Boolean(default=True), "command": { # namespace for values added by @command decorated functions }, "shortcuts": { # leading space -> not saved in command history "Command+Alt+Left": { "name": String("Previous Document"), "rank": Integer(1000), "command": String(" doc previous"), }, "Command+Alt+Right": { "name": String("Next Document"), "rank": Integer(1010), "command": String(" doc next"), }, "Command+Alt+Up": { "name": String("↑ Document"), "rank": Integer(1020), "command": String(" doc up"), }, "Command+Alt+Down": { "name": String("↓ Document"), "rank": Integer(1030), "command": String(" doc down"), }, }, "logging_config": Dict({}), } deprecation_transforms = {
def __init__(self, filename, name, filepatterns, word_groups=(), delimited_ranges=(), comment_token="", disabled=False, flags=0): """Syntax definition arguments: word_groups - a sequence of two-tuples associating word-tokens with a color: [ (['word1', 'word2'], <RRGGBB color string>) ] delimited_ranges - a list of four-tuples associating a set of delimiters with a color and a syntax definition: [ ( <start delimiter>, <list of end delimiters>, <RRGGBB color string>, <SyntaxDefinition instance> or None ), ('<!--', ['-->'], 'RRGGBB', None), ('"', ['"', '\n'], 'RRGGBB', None), ('<?', ['?>'], 'RRGGBB', "php"), ] """ super(SyntaxDefinition, self).__init__(name, comment_token, disabled) def escape(token): if hasattr(token, "pattern"): return token.pattern token = re.escape(token) return token.replace(re.escape("\n"), "\\n") namegen = ("g%i" % i for i in count()) self.filename = filename self.filepatterns = set(filepatterns) self.word_groups = list(word_groups) self.delimited_ranges = list(delimited_ranges) self.wordinfo = wordinfo = {} flags |= re.DOTALL groups = [] word_char = re.compile(r"\w") for tokens, color in word_groups: name = next(namegen) color = get_color(color) wordgroup = [] for token in tokens: if hasattr(token, "pattern"): word = token.pattern else: word = escape(token) if word_char.match(token[0]): word = r"\b" + word if word_char.match(token[-1]): word = word + r"\b" wordgroup.append(word) groups.append("(?P<%s>%s)" % (name, "|".join(wordgroup))) wordinfo[name] = (color, name) for start, ends, color, sdef in delimited_ranges: name = next(namegen) color = get_color(color) phrase = "(?P<%s>(%s).*?(%s))" % (name, escape(start), "|".join( escape(token) for token in chain(ends, [RE("$")]))) groups.append(phrase) endxp = re.compile( ".*?" + "|".join(escape(token) for token in ends), flags) wordinfo[name] = (color, name) #, endxp) self.regex = re.compile("|".join(groups), flags)