diff --git a/Makefile b/Makefile index ab5a324..a589117 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,8 @@ -.PHONY: install install-lib phony +.PHONY: install install-lib phony test WEECHAT_HOME ?= $(HOME)/.weechat PREFIX ?= $(WEECHAT_HOME) +PYTHON ?= python lib := $(patsubst matrix/%.py, $(DESTDIR)$(PREFIX)/python/matrix/%.py, \ $(wildcard matrix/*.py)) @@ -15,3 +16,6 @@ phony: $(DESTDIR)$(PREFIX)/python/matrix/%.py: matrix/%.py phony install -Dm644 $< $@ + +test: + $(PYTHON) -m pytest diff --git a/matrix/_weechat.py b/matrix/_weechat.py new file mode 100644 index 0000000..d207ce7 --- /dev/null +++ b/matrix/_weechat.py @@ -0,0 +1,93 @@ +def color(color_name): + # type: (str) -> str + # yapf: disable + weechat_base_colors = { + "black": "0", + "red": "1", + "green": "2", + "brown": "3", + "blue": "4", + "magenta": "5", + "cyan": "6", + "default": "7", + "gray": "8", + "lightred": "9", + "lightgreen": "10", + "yellow": "11", + "lightblue": "12", + "lightmagenta": "13", + "lightcyan": "14", + "white": "15" + } + + escape_codes = [] + reset_code = "0" + + def make_fg_color(color): + return "38;5;{}".format(color) + + def make_bg_color(color): + return "48;5;{}".format(color) + + attributes = { + "bold": "1", + "-bold": "21", + "reverse": "27", + "-reverse": "21", + "italic": "3", + "-italic": "23", + "underline": "4", + "-underline": "24", + "reset": "0", + "resetcolor": "39" + } + + short_attributes = { + "*": "1", + "!": "27", + "/": "3", + "_": "4" + } + + colors = color_name.split(",", 2) + + fg_color = colors.pop(0) + + bg_color = colors.pop(0) if colors else "" + + if fg_color in attributes: + escape_codes.append(attributes[fg_color]) + else: + chars = list(fg_color) + + for char in chars: + if char in short_attributes: + escape_codes.append(short_attributes[char]) + elif char == "|": + reset_code = "" + else: + break + + stripped_color = fg_color.lstrip("*_|/!") + + if stripped_color in weechat_base_colors: + escape_codes.append( + make_fg_color(weechat_base_colors[stripped_color])) + + elif stripped_color.isdecimal(): + num_color = int(stripped_color) + if num_color >= 0 and num_color < 256: + escape_codes.append(make_fg_color(stripped_color)) + + + if bg_color in weechat_base_colors: + escape_codes.append(make_bg_color(weechat_base_colors[bg_color])) + else: + if bg_color.isdecimal(): + num_color = int(bg_color) + if num_color >= 0 and num_color < 256: + escape_codes.append(make_bg_color(bg_color)) + + escape_string = "\033[{}{}m".format(reset_code, ";".join(escape_codes)) + + return escape_string diff --git a/matrix/colors.py b/matrix/colors.py index 21ed444..4c83f31 100644 --- a/matrix/colors.py +++ b/matrix/colors.py @@ -542,23 +542,26 @@ def colour_find_rgb(r, g, b): def color_html_to_weechat(color): # type: (str) -> str + # yapf: disable first_16 = { - (0, 0, 0): "black", # 0 - (128, 0, 0): "red", # 1 - (0, 128, 0): "green", # 2 - (128, 128, 0): "brown", # 3 - (0, 0, 128): "blue", # 4 - (128, 0, 128): "magenta", # 5 - (0, 128, 128): "cyan", # 6 - (192, 192, 192): "default", # 7 - (128, 128, 128): "gray", # 8 - (255, 0, 0): "lightred", # 9 - (0, 255, 0): "lightgreen", # 11 - (255, 255, 0): "yellow", # 12 - (0, 0, 255): "lightblue", # 13 - (255, 0, 255): "lightmagenta", # 14 - (0, 255, 255): "lightcyan", # 15 + (0, 0, 0): "black", # 0 + (128, 0, 0): "red", # 1 + (0, 128, 0): "green", # 2 + (128, 128, 0): "brown", # 3 + (0, 0, 128): "blue", # 4 + (128, 0, 128): "magenta", # 5 + (0, 128, 128): "cyan", # 6 + (192, 192, 192): "default", # 7 + (128, 128, 128): "gray", # 8 + (255, 0, 0): "lightred", # 9 + (0, 255, 0): "lightgreen", # 10 + (255, 255, 0): "yellow", # 11 + (0, 0, 255): "lightblue", # 12 + (255, 0, 255): "lightmagenta", # 13 + (0, 255, 255): "lightcyan", # 14 + (255, 255, 255): "white", # 15 } + # yapf: enable try: rgb_color = webcolors.html5_parse_legacy_color(color) @@ -573,24 +576,25 @@ def color_html_to_weechat(color): def color_weechat_to_html(color): # type: (str) -> str + # yapf: disable first_16 = { - "black": "black", # 0 - "red": "maroon", # 1 - "green": "green", # 2 - "brown": "olive", # 3 - "blue": "navy", # 4 - "magenta": "purple", # 5 - "cyan": "teal", # 6 - "default": "silver", # 7 - "gray": "grey", # 8 - "lightred": "red", # 9 - "lightgreen": "lime", # 11 - "yellow": "yellow", # 12 - "lightblue": "fuchsia", # 13 - "lightmagenta": "aqua", # 14 - "lightcyan": "white", # 15 + "black": "black", # 0 + "red": "maroon", # 1 + "green": "green", # 2 + "brown": "olive", # 3 + "blue": "navy", # 4 + "magenta": "purple", # 5 + "cyan": "teal", # 6 + "default": "silver", # 7 + "gray": "gray", # 8 + "lightred": "red", # 9 + "lightgreen": "lime", # 11 + "yellow": "yellow", # 12 + "lightblue": "blue", # 13 + "lightmagenta": "fuchsia", # 14 + "lightcyan": "aqua", # 15 + "white": "white", # 15 } - #yapf: disable hex_colors = { "0": "#000000", "1": "#800000", diff --git a/matrix/globals.py b/matrix/globals.py index c3e15fa..9c125b7 100644 --- a/matrix/globals.py +++ b/matrix/globals.py @@ -21,9 +21,12 @@ import sys from matrix.utf import WeechatWrapper from matrix.plugin_options import PluginOptions -import weechat - -W = weechat if sys.hexversion >= 0x3000000 else WeechatWrapper(weechat) +try: + import weechat + W = weechat if sys.hexversion >= 0x3000000 else WeechatWrapper(weechat) +except ImportError: + import matrix._weechat as weechat + W = weechat OPTIONS = PluginOptions() # type: PluginOptions SERVERS = dict() # type: Dict[str, MatrixServer] diff --git a/tests/color_test.py b/tests/color_test.py new file mode 100644 index 0000000..73772a8 --- /dev/null +++ b/tests/color_test.py @@ -0,0 +1,26 @@ +import webcolors +from hypothesis import given +from hypothesis.strategies import sampled_from + +from matrix.colors import (Formatted, color_html_to_weechat, + color_weechat_to_html) + +html_prism = ("Test") + +weechat_prism = ( + u"\x1b[038;5;1mT\x1b[039m\x1b[038;5;9me\x1b[039m\x1b[038;5;3ms\x1b[039m\x1b[038;5;11mt\x1b[039m" +) + +first_16_html_colors = list(webcolors.HTML4_HEX_TO_NAMES.values()) + + +def test_prism(): + formatted = Formatted.from_html(html_prism) + assert formatted.to_weechat() == weechat_prism + + +@given(sampled_from(first_16_html_colors)) +def test_color_conversion(color_name): + assert color_weechat_to_html( + color_html_to_weechat(color_name)) == color_name