diff --git a/tests/cli/test_run.py b/tests/cli/test_run.py index 935a5396b9..1527a713d9 100644 --- a/tests/cli/test_run.py +++ b/tests/cli/test_run.py @@ -5,7 +5,6 @@ import pytest from zulipterminal.cli.run import ( - THEMES, _write_zuliprc, exit_with_error, get_login_id, @@ -140,7 +139,6 @@ def test_valid_zuliprc_but_no_connection( def test_warning_regarding_incomplete_theme( capsys, mocker, - monkeypatch, minimal_zuliprc, bad_theme, server_connection_error="sce", @@ -149,13 +147,12 @@ def test_warning_regarding_incomplete_theme( "zulipterminal.core.Controller.__init__", side_effect=ServerConnectionFailure(server_connection_error), ) - - monkeypatch.setitem(THEMES, bad_theme, []) mocker.patch("zulipterminal.cli.run.all_themes", return_value=("a", "b", "c", "d")) mocker.patch( "zulipterminal.cli.run.complete_and_incomplete_themes", return_value=(["a", "b"], ["c", "d"]), ) + mocker.patch("zulipterminal.cli.run.generate_theme") with pytest.raises(SystemExit) as e: main(["-c", minimal_zuliprc, "-t", bad_theme]) diff --git a/tests/config/test_color.py b/tests/config/test_color.py new file mode 100644 index 0000000000..54283cec18 --- /dev/null +++ b/tests/config/test_color.py @@ -0,0 +1,15 @@ +from enum import Enum + +from zulipterminal.config.color import color_properties + + +def test_color_properties(): + class Color(Enum): + WHITE = "wh #256 #24" + + Color = color_properties(Color, "BOLD", "ITALICS") + + assert Color.WHITE in Color + assert Color.WHITE.value == "wh #256 #24" + assert Color.WHITE__BOLD_ITALICS in Color + assert Color.WHITE__BOLD_ITALICS.value == "wh #256 #24 , bold , italics" diff --git a/tests/config/test_themes.py b/tests/config/test_themes.py index 8053d1b535..ab0a711d76 100644 --- a/tests/config/test_themes.py +++ b/tests/config/test_themes.py @@ -1,11 +1,14 @@ +import re +from enum import Enum + import pytest from zulipterminal.config.themes import ( + REQUIRED_STYLES, THEMES, all_themes, complete_and_incomplete_themes, - required_styles, - theme_with_monochrome_added, + parse_themefile, ) @@ -14,8 +17,26 @@ "gruvbox_dark", "zt_light", "zt_blue", - "gruvbox_dark24", } +aliases_16_color = [ + "default", + "black", + "dark red", + "dark green", + "brown", + "dark blue", + "dark magenta", + "dark cyan", + "dark gray", + "light red", + "light green", + "yellow", + "light blue", + "light magenta", + "light cyan", + "light gray", + "white", +] def test_all_themes(): @@ -34,10 +55,37 @@ def test_all_themes(): ) def test_builtin_theme_completeness(theme_name): theme = THEMES[theme_name] - styles_in_theme = {style[0] for style in theme} + theme_styles = theme.STYLES + theme_colors = theme.Color + + # Check if STYLE and REQUIRED_STYLES use the same styles. + assert len(theme_styles) == len(REQUIRED_STYLES) + assert all(required_style in theme_styles for required_style in REQUIRED_STYLES) + # Check if colors are defined with all 3 color codes. + for color in theme_colors: + if "__" in color.name: + continue - assert len(styles_in_theme) == len(required_styles) - assert all(required_style in styles_in_theme for required_style in required_styles) + codes = color.value.split() + assert len(codes) == 3 + # Check if 16-color alias is correct + assert codes[0].replace("_", " ") in aliases_16_color + # Check if 24-bit and 256 color is any of + # #000000-#ffffff or #000-#fff or h0-h255 or g0-g100 0r g#00-g#ff + pattern = re.compile( + "#[\\da-f]{6}|#[\\da-f]{3}|(?:h|g)([\\d]{1,3})|g#[\\da-f]{2}|default$" + ) + for code in [codes[1], codes[2]]: + code = pattern.match(code) + assert code + if code.group(1) and code.group(0).startswith("h"): + assert int(code.group(1)) < 256 + elif code.group(1) and code.group(0).startswith("g"): + assert int(code.group(1)) <= 100 + # Check if color used in STYLE exists in Color. + for style_name, style_conf in theme_styles.items(): + fg, bg = style_conf + assert fg in theme_colors and bg in theme_colors def test_complete_and_incomplete_themes(): @@ -50,26 +98,49 @@ def test_complete_and_incomplete_themes(): @pytest.mark.parametrize( - "theme, expected_new_theme, req_styles", + "color_depth, expected_urwid_theme", [ - ([("a", "another")], [], {}), - ([("a", "another")], [("a", "another")], {"a": ""}), - ([("a", "fg", "bg")], [("a", "fg", "bg", "x")], {"a": "x"}), - ([("a", "fg", "bg", "bold")], [("a", "fg", "bg", "x")], {"a": "x"}), + (1, [("s1", "", "", ""), ("s2", "", "", "bold")]), + ( + 16, + [ + ("s1", "white , bold", "dark magenta"), + ("s2", "white , bold , italics", "dark magenta"), + ], + ), ( - [("a", "fg", "bg", "bold", "h1", "h2")], - [("a", "fg", "bg", "x", "h1", "h2")], - {"a": "x"}, + 256, + [ + ("s1", "", "", "", "#fff , bold", "h90"), + ("s2", "", "", "", "#fff , bold , italics", "h90"), + ], + ), + ( + 2 ** 24, + [ + ("s1", "", "", "", "#ffffff , bold", "#870087"), + ("s2", "", "", "", "#ffffff , bold , italics", "#870087"), + ], ), ], ids=[ - "incomplete_theme", - "one_to_one", - "16_color_add_mono", - "16_color_mono_overwrite", - "256_color", + "mono-chrome", + "16-color", + "256-color", + "24-bit-color", ], ) -def test_theme_with_monochrome_added(mocker, theme, expected_new_theme, req_styles): - mocker.patch.dict("zulipterminal.config.themes.required_styles", req_styles) - assert theme_with_monochrome_added(theme) == expected_new_theme +def test_parse_themefile(mocker, color_depth, expected_urwid_theme): + class Color(Enum): + WHITE__BOLD = "white #fff #ffffff , bold" + WHITE__BOLD_ITALICS = "white #fff #ffffff , bold , italics" + DARK_MAGENTA = "dark_magenta h90 #870087" + + STYLES = { + "s1": (Color.WHITE__BOLD, Color.DARK_MAGENTA), + "s2": (Color.WHITE__BOLD_ITALICS, Color.DARK_MAGENTA), + } + + req_styles = {"s1": "", "s2": "bold"} + mocker.patch.dict("zulipterminal.config.themes.REQUIRED_STYLES", req_styles) + assert parse_themefile(STYLES, color_depth) == expected_urwid_theme diff --git a/zulipterminal/cli/run.py b/zulipterminal/cli/run.py index c43888e5d9..14dccae4f4 100755 --- a/zulipterminal/cli/run.py +++ b/zulipterminal/cli/run.py @@ -12,11 +12,10 @@ from urwid import display_common, set_encoding from zulipterminal.config.themes import ( - THEMES, aliased_themes, all_themes, complete_and_incomplete_themes, - theme_with_monochrome_added, + generate_theme, ) from zulipterminal.core import Controller from zulipterminal.model import ServerConnectionFailure @@ -486,10 +485,7 @@ def main(options: Optional[List[str]] = None) -> None: break boolean_settings[setting] = zterm[setting][0] == valid_values[0] - if color_depth == 1: - theme_data = theme_with_monochrome_added(THEMES[theme_to_use[0]]) - else: - theme_data = THEMES[theme_to_use[0]] + theme_data = generate_theme(theme_to_use[0], color_depth) Controller( zuliprc_path, diff --git a/zulipterminal/config/color.py b/zulipterminal/config/color.py new file mode 100644 index 0000000000..ef3132613b --- /dev/null +++ b/zulipterminal/config/color.py @@ -0,0 +1,63 @@ +""" +COLOR +----- +Contains color definitions or functions common across all themes. +For further details on themefiles look at the theme contribution guide. +""" +from enum import Enum +from typing import Any + + +# fmt: off +# NOTE: The 24bit color codes use 256 color which can be +# enhanced to be truly 24bit. +# NOTE: The 256code format can be moved to h0-255 to +# make use of the complete range instead of only 216 colors. +class DefaultColor(Enum): + # color = 16code 256code 24code + DEFAULT = 'default default default' + BLACK = 'black g19 g19' + DARK_RED = 'dark_red #a00 #a00' + DARK_GREEN = 'dark_green #080 #080' + BROWN = 'brown #880 #880' + DARK_BLUE = 'dark_blue #24a #24a' + DARK_MAGENTA = 'dark_magenta h90 h90' # #870087 + DARK_CYAN = 'dark_cyan #088 #088' + DARK_GRAY = 'dark_gray #666 #666' + LIGHT_RED = 'light_red #f00 #f00' + LIGHT_GREEN = 'light_green #0f0 #0f0' + YELLOW = 'yellow #ff0 #ff0' + LIGHT_BLUE = 'light_blue #28d #28d' + LIGHT_MAGENTA = 'light_magenta #c8f #c8f' + LIGHT_CYAN = 'light_cyan h152 h152' # #afd7d7 + LIGHT_GRAY = 'light_gray #ccc #ccc' + WHITE = 'white #fff #fff' +# fmt: on + + +def color_properties(colors: Any, *prop: str) -> Any: + """ + Adds properties(Bold, Italics, etc...) to Enum Colors in theme files. + Useage: color_properties(Color, 'BOLD', 'ITALICS', 'STRIKETHROUGH') + + NOTE: color_properties(Color, BOLD, ITALICS) would result in only + Color.WHITE and Color.WHITE__BOLD_ITALICS + but not Color.WHITE__BOLD or Color.WHITE__ITALICS. + One would also have to do color_properties(Color, BOLD) + and color_properties(Color, ITALICS) for the others to work + >>> This function can be later extended to achieve all combinations + with one call to the function. + """ + prop_n = "_".join([p.upper() for p in prop]) + prop_v = " , ".join([p.lower() for p in prop]) + updated_colors: Any = Enum( # type: ignore # Ref: python/mypy#529, #535 and #5317 + "Color", + { + **{c.name: c.value for c in colors}, + **{c.name + f"__{prop_n}": c.value + f" , {prop_v}" for c in colors}, + }, + ) + return updated_colors + + +DefaultBoldColor = color_properties(DefaultColor, "BOLD") diff --git a/zulipterminal/config/themes.py b/zulipterminal/config/themes.py index c8200877a6..1131044c59 100644 --- a/zulipterminal/config/themes.py +++ b/zulipterminal/config/themes.py @@ -1,128 +1,80 @@ -from typing import Dict, List, Optional, Tuple +from typing import Any, Dict, List, Optional, Tuple, Union +from zulipterminal.themes import gruvbox, zt_blue, zt_dark, zt_light -ThemeSpec = List[Tuple[Optional[str], ...]] -# The keys in required_styles specify what styles are necessary for a theme to +StyleSpec = Union[ + Tuple[Optional[str], str, str], + Tuple[Optional[str], str, str, Optional[str]], + Tuple[Optional[str], str, str, Optional[str], str, str], +] +ThemeSpec = List[StyleSpec] + +# fmt: off +# The keys in REQUIRED_STYLES specify what styles are necessary for a theme to # be complete, while the values are those used to style each element in # monochrome (1-bit) mode - independently of the specified theme - -required_styles = { # style-name: monochrome-bit-depth-style - None: "", - "selected": "standout", - "msg_selected": "standout", - "header": "bold", - "general_narrow": "standout", - "general_bar": "", - "name": "", - "unread": "strikethrough", - "user_active": "bold", - "user_idle": "", - "user_offline": "", - "user_inactive": "", - "title": "bold", - "column_title": "bold", - "time": "", - "bar": "standout", - "popup_contrast": "standout", - "msg_emoji": "bold", - "reaction": "bold", - "reaction_mine": "standout", - "msg_mention": "bold", - "msg_link": "", - "msg_link_index": "bold", - "msg_quote": "underline", - "msg_code": "bold", - "msg_bold": "bold", - "msg_time": "bold", - "footer": "standout", - "footer_contrast": "standout", - "starred": "bold", - "popup_category": "bold", - "unread_count": "bold", - "starred_count": "", - "table_head": "bold", - "filter_results": "bold", - "edit_topic": "standout", - "edit_tag": "standout", - "edit_author": "bold", - "edit_time": "bold", - "current_user": "", - "muted": "bold", - "popup_border": "bold", - "area:help": "standout", - "area:msg": "standout", - "area:stream": "standout", - "area:error": "standout", - "search_error": "standout", - "task:success": "standout", - "task:error": "standout", - "task:warning": "standout", +REQUIRED_STYLES = { + # style name : monochrome style + None : '', + 'selected' : 'standout', + 'msg_selected' : 'standout', + 'header' : 'bold', + 'general_narrow' : 'standout', + 'general_bar' : '', + 'name' : '', + 'unread' : 'strikethrough', + 'user_active' : 'bold', + 'user_idle' : '', + 'user_offline' : '', + 'user_inactive' : '', + 'title' : 'bold', + 'column_title' : 'bold', + 'time' : '', + 'bar' : 'standout', + 'popup_contrast' : 'standout', + 'msg_emoji' : 'bold', + 'reaction' : 'bold', + 'reaction_mine' : 'standout', + 'msg_mention' : 'bold', + 'msg_link' : '', + 'msg_link_index' : 'bold', + 'msg_quote' : 'underline', + 'msg_code' : 'bold', + 'msg_bold' : 'bold', + 'msg_time' : 'bold', + 'footer' : 'standout', + 'footer_contrast' : 'standout', + 'starred' : 'bold', + 'popup_category' : 'bold', + 'unread_count' : 'bold', + 'starred_count' : '', + 'table_head' : 'bold', + 'filter_results' : 'bold', + 'edit_topic' : 'standout', + 'edit_tag' : 'standout', + 'edit_author' : 'bold', + 'edit_time' : 'bold', + 'current_user' : '', + 'muted' : 'bold', + 'popup_border' : 'bold', + 'area:help' : 'standout', + 'area:msg' : 'standout', + 'area:stream' : 'standout', + 'area:error' : 'standout', + 'search_error' : 'standout', + 'task:success' : 'standout', + 'task:error' : 'standout', + 'task:warning' : 'standout', } +# fmt: on - -# 256-color base names for default theme (bold values added below) -DEF_base = dict( - dark_red="#a00", - brown="#880", - dark_blue="#24a", - dark_cyan="#088", - dark_gray="#666", - light_gray="#ccc", - light_red="#f00", - light_green="#0f0", - dark_green="#080", - yellow="#ff0", - light_blue="#28d", - light_magenta="#c8f", - white="#fff", - black="g19", -) - -DEF = dict( - DEF_base, **{f"{color}:bold": f"{code}, bold" for color, code in DEF_base.items()} -) - -# Colors used in gruvbox-256 -# See https://github.com/morhetz/gruvbox/blob/master/colors/gruvbox.vim -BLACK = "h234" # dark0_hard -WHITE = "h250" # light2 -WHITEBOLD = f"{WHITE}, bold" -DARKBLUE = "h24" # faded_blue -DARKRED = "h88" # faded_red -LIGHTBLUE = "h109" # bright_blue -LIGHTBLUEBOLD = f"{LIGHTBLUE}, bold" -YELLOW = "h172" # neutral_yellow -YELLOWBOLD = f"{YELLOW}, bold" -LIGHTGREEN = "h142" # bright_green -LIGHTRED = "h167" # bright_red -LIGHTREDBOLD = f"{LIGHTRED}, bold" -GRAY = "h244" # gray_244 -LIGHTGRAY = "h248" # light3 -LIGHTMAGENTA = "h132" # neutral_purple -LIGHTMAGENTABOLD = f"{LIGHTMAGENTA}, bold" -DARKCYAN = "h66" # neutral_blue -BROWN = "h136" # faded_yellow - -# Colors used in gruvbox_dark24 -BLACK24 = "#1d2021" # dark0_hard -WHITE24 = "#d5c4a1" # light2 -WHITEBOLD24 = f"{WHITE24}, bold" -DARKBLUE24 = "#076678" # faded_blue -DARKRED24 = "#9d0006" # faded_red -LIGHTBLUE24 = "#83a598" # bright_blue -LIGHTBLUEBOLD24 = f"{LIGHTBLUE24}, bold" -YELLOW24 = "#d79921" # neutral_yellow -YELLOWBOLD24 = f"{YELLOW24}, bold" -LIGHTGREEN24 = "#b8bb26" # bright_green -LIGHTRED24 = "#fb4934" # bright_red -LIGHTREDBOLD24 = f"{LIGHTRED24}, bold" -GRAY24 = "#928374" # gray_244 -LIGHTGRAY24 = "#bdae93" # light3 -LIGHTMAGENTA24 = "#b16286" # neutral_purple -LIGHTMAGENTABOLD24 = f"{LIGHTMAGENTA24}, bold" -DARKCYAN24 = "#458588" # neutral_blue -BROWN24 = "#b57614" # faded_yellow +THEMES = { + "gruvbox_dark": gruvbox, + "zt_dark": zt_dark, + "zt_light": zt_light, + "zt_blue": zt_blue, +} THEME_ALIASES = { "default": "zt_dark", @@ -131,425 +83,6 @@ "blue": "zt_blue", } -# fmt: off -THEMES: Dict[str, ThemeSpec] = { - 'zt_dark': [ - (None, 'white', 'black', - None, DEF['white'], DEF['black']), - ('selected', 'white', 'dark blue', - None, DEF['white'], DEF['dark_blue']), - ('msg_selected', 'white', 'dark blue', - None, DEF['white'], DEF['dark_blue']), - ('header', 'dark cyan', 'dark blue', - None, DEF['dark_cyan'], DEF['dark_blue']), - ('general_narrow', 'white', 'dark blue', - None, DEF['white'], DEF['dark_blue']), - ('general_bar', 'white', 'black', - None, DEF['white'], DEF['black']), - ('name', 'yellow, bold', 'black', - None, DEF['yellow:bold'], DEF['black']), - ('unread', 'dark blue', 'black', - None, DEF['dark_blue'], DEF['black']), - ('user_active', 'light green', 'black', - None, DEF['light_green'], DEF['black']), - ('user_idle', 'yellow', 'black', - None, DEF['yellow'], DEF['black']), - ('user_offline', 'white', 'black', - None, DEF['white'], DEF['black']), - ('user_inactive', 'white', 'black', - None, DEF['white'], DEF['black']), - ('title', 'white, bold', 'black', - None, DEF['white:bold'], DEF['black']), - ('column_title', 'white, bold', 'black', - None, DEF['white:bold'], DEF['black']), - ('time', 'light blue', 'black', - None, DEF['light_blue'], DEF['black']), - ('bar', 'white', 'dark gray', - None, DEF['white'], DEF['dark_gray']), - ('popup_contrast', 'white', 'dark gray', - None, DEF['white'], DEF['dark_gray']), - ('msg_emoji', 'light magenta', 'black', - None, DEF['light_magenta'], DEF['black']), - ('reaction', 'light magenta, bold', 'black', - None, DEF['light_magenta:bold'], DEF['black']), - ('reaction_mine', 'black', 'light magenta', - None, DEF['black'], DEF['light_magenta']), - ('msg_mention', 'light red, bold', 'black', - None, DEF['light_red:bold'], DEF['black']), - ('msg_link', 'light blue', 'black', - None, DEF['light_blue'], DEF['black']), - ('msg_link_index', 'light blue, bold', 'black', - None, DEF['light_blue:bold'], DEF['black']), - ('msg_quote', 'brown', 'black', - None, DEF['brown'], DEF['black']), - ('msg_code', 'black', 'white', - None, DEF['black'], DEF['white']), - ('msg_bold', 'white, bold', 'black', - None, DEF['white:bold'], DEF['black']), - ('msg_time', 'black', 'white', - None, DEF['black'], DEF['white']), - ('footer', 'black', 'light gray', - None, DEF['black'], DEF['light_gray']), - ('footer_contrast', 'white', 'black', - None, DEF['white'], DEF['black']), - ('starred', 'light red, bold', 'black', - None, DEF['light_red:bold'], DEF['black']), - ('popup_category', 'light blue, bold', 'black', - None, DEF['light_blue:bold'], DEF['black']), - ('unread_count', 'yellow', 'black', - None, DEF['yellow'], DEF['black']), - ('starred_count', 'light gray', 'black', - None, DEF['light_gray'], DEF['black']), - ('table_head', 'white, bold', 'black', - None, DEF['white:bold'], DEF['black']), - ('filter_results', 'white', 'dark green', - None, DEF['white'], DEF['dark_green']), - ('edit_topic', 'white', 'dark gray', - None, DEF['white'], DEF['dark_gray']), - ('edit_tag', 'white', 'dark gray', - None, DEF['white'], DEF['dark_gray']), - ('edit_author', 'yellow', 'black', - None, DEF['yellow'], DEF['black']), - ('edit_time', 'light blue', 'black', - None, DEF['light_blue'], DEF['black']), - ('current_user', 'white', 'black', - None, DEF['white'], DEF['black']), - ('muted', 'light blue', 'black', - None, DEF['light_blue'], DEF['black']), - ('popup_border', 'white', 'black', - None, DEF['white'], DEF['black']), - ('area:help', 'white', 'dark green', - None, DEF['white'], DEF['dark_green']), - ('area:msg', 'white', 'brown', - None, DEF['white'], DEF['brown']), - ('area:stream', 'white', 'dark cyan', - None, DEF['white'], DEF['dark_cyan']), - ('area:error', 'white', 'dark red', - None, DEF['white'], DEF['dark_red']), - ('search_error', 'light red', 'black', - None, DEF['light_red'], DEF['black']), - ('task:success', 'white', 'dark green', - None, DEF['white'], DEF['dark_green']), - ('task:error', 'white', 'dark red', - None, DEF['white'], DEF['dark_red']), - ('task:warning', 'white', 'brown', - None, DEF['white'], DEF['brown']), - ], - 'gruvbox_dark': [ - # default colorscheme on 16 colors, gruvbox colorscheme - # on 256 colors - (None, 'white', 'black', - None, WHITE, BLACK), - ('selected', 'black', 'white', - None, BLACK, WHITE), - ('msg_selected', 'black', 'white', - None, BLACK, WHITE), - ('header', 'dark cyan', 'dark blue', - None, DARKCYAN, DARKBLUE), - ('general_narrow', 'white', 'dark blue', - None, WHITE, DARKBLUE), - ('general_bar', 'white', 'black', - None, WHITE, BLACK), - ('name', 'yellow, bold', 'black', - None, YELLOWBOLD, BLACK), - ('unread', 'light magenta', 'black', - None, LIGHTMAGENTA, BLACK), - ('user_active', 'light green', 'black', - None, LIGHTGREEN, BLACK), - ('user_idle', 'yellow', 'black', - None, YELLOW, BLACK), - ('user_offline', 'white', 'black', - None, WHITE, BLACK), - ('user_inactive', 'white', 'black', - None, WHITE, BLACK), - ('title', 'white, bold', 'black', - None, WHITEBOLD, BLACK), - ('column_title', 'white, bold', 'black', - None, WHITEBOLD, BLACK), - ('time', 'light blue', 'black', - None, LIGHTBLUE, BLACK), - ('bar', 'white', 'dark gray', - None, WHITE, GRAY), - ('popup_contrast', 'black', 'dark gray', - None, BLACK, GRAY), - ('msg_emoji', 'light magenta', 'black', - None, LIGHTMAGENTA, BLACK), - ('reaction', 'light magenta, bold', 'black', - None, LIGHTMAGENTABOLD, BLACK), - ('reaction_mine', 'black', 'light magenta', - None, BLACK, LIGHTMAGENTA), - ('msg_mention', 'light red, bold', 'black', - None, LIGHTREDBOLD, BLACK), - ('msg_link', 'light blue', 'black', - None, LIGHTBLUE, BLACK), - ('msg_link_index', 'light blue, bold', 'black', - None, LIGHTBLUEBOLD, BLACK), - ('msg_quote', 'brown', 'black', - None, BROWN, BLACK), - ('msg_code', 'black', 'white', - None, BLACK, WHITE), - ('msg_bold', 'white, bold', 'black', - None, WHITEBOLD, BLACK), - ('msg_time', 'black', 'white', - None, BLACK, WHITE), - ('footer', 'black', 'light gray', - None, BLACK, LIGHTGRAY), - ('footer_contrast', 'white', 'black', - None, WHITE, BLACK), - ('starred', 'light red, bold', 'black', - None, LIGHTREDBOLD, BLACK), - ('popup_category', 'light blue, bold', 'black', - None, LIGHTBLUEBOLD, BLACK), - ('unread_count', 'yellow', 'black', - None, YELLOW, BLACK), - ('starred_count', 'light gray', 'black', - None, LIGHTGRAY, BLACK), - ('table_head', 'white, bold', 'black', - None, WHITEBOLD, BLACK), - ('filter_results', 'black', 'light green', - None, BLACK, LIGHTGREEN), - ('edit_topic', 'black', 'dark gray', - None, BLACK, GRAY), - ('edit_tag', 'black', 'dark gray', - None, BLACK, GRAY), - ('edit_author', 'yellow', 'black', - None, YELLOW, BLACK), - ('edit_time', 'light blue', 'black', - None, LIGHTBLUE, BLACK), - ('current_user', 'white', 'black', - None, WHITE, BLACK), - ('muted', 'light blue', 'black', - None, LIGHTBLUE, BLACK), - ('popup_border', 'white', 'black', - None, WHITE, BLACK), - ('area:help', 'black', 'light green', - None, BLACK, LIGHTGREEN), - ('area:msg', 'black', 'light red', - None, BLACK, LIGHTRED), - ('area:stream', 'black', 'light blue', - None, BLACK, LIGHTBLUE), - ('area:error', 'white', 'dark red', - None, WHITE, DARKRED), - ('search_error', 'light red', 'black', - None, LIGHTRED, BLACK), - ('task:success', 'black', 'light green', - None, BLACK, LIGHTGREEN), - ('task:error', 'white', 'dark red', - None, WHITE, DARKRED), - ('task:warning', 'black', 'light red', - None, BLACK, LIGHTRED), - ], - 'gruvbox_dark24': [ - # default colorscheme on 16 colors, gruvbox colorscheme - # on 24 bit color (true color) - (None, 'white', 'black', - None, WHITE24, BLACK24), - ('selected', 'black', 'white', - None, BLACK24, WHITE24), - ('msg_selected', 'black', 'white', - None, BLACK24, WHITE24), - ('header', 'dark cyan', 'dark blue', - None, DARKCYAN24, DARKBLUE24), - ('general_narrow', 'white', 'dark blue', - None, WHITE24, DARKBLUE24), - ('general_bar', 'white', 'black', - None, WHITE24, BLACK24), - ('name', 'yellow, bold', 'black', - None, YELLOWBOLD24, BLACK24), - ('unread', 'light magenta', 'black', - None, LIGHTMAGENTA24, BLACK24), - ('user_active', 'light green', 'black', - None, LIGHTGREEN24, BLACK24), - ('user_idle', 'yellow', 'black', - None, YELLOW24, BLACK24), - ('user_offline', 'white', 'black', - None, WHITE24, BLACK24), - ('user_inactive', 'white', 'black', - None, WHITE24, BLACK24), - ('title', 'white, bold', 'black', - None, WHITEBOLD24, BLACK24), - ('column_title', 'white, bold', 'black', - None, WHITEBOLD24, BLACK24), - ('time', 'light blue', 'black', - None, LIGHTBLUE24, BLACK24), - ('bar', 'white', 'dark gray', - None, WHITE24, GRAY24), - ('popup_contrast', 'black', 'dark gray', - None, BLACK24, GRAY24), - ('msg_emoji', 'light magenta', 'black', - None, LIGHTMAGENTA24, BLACK24), - ('reaction', 'light magenta, bold', 'black', - None, LIGHTMAGENTABOLD24, BLACK24), - ('reaction_mine', 'black', 'light magenta', - None, BLACK24, LIGHTMAGENTA24), - ('msg_mention', 'light red, bold', 'black', - None, LIGHTREDBOLD24, BLACK24), - ('msg_link', 'light blue', 'black', - None, LIGHTBLUE24, BLACK24), - ('msg_link_index', 'light blue, bold', 'black', - None, LIGHTBLUEBOLD24, BLACK24), - ('msg_quote', 'brown', 'black', - None, BROWN24, BLACK24), - ('msg_code', 'black', 'white', - None, BLACK24, WHITE24), - ('msg_bold', 'white, bold', 'black', - None, WHITEBOLD24, BLACK24), - ('msg_time', 'black', 'white', - None, BLACK24, WHITE24), - ('footer', 'black', 'light gray', - None, BLACK24, LIGHTGRAY24), - ('footer_contrast', 'white', 'black', - None, WHITE24, BLACK24), - ('starred', 'light red, bold', 'black', - None, LIGHTREDBOLD24, BLACK24), - ('popup_category', 'light blue, bold', 'black', - None, LIGHTBLUEBOLD24, BLACK24), - ('unread_count', 'yellow', 'black', - None, YELLOW24, BLACK24), - ('starred_count', 'light gray', 'black', - None, LIGHTGRAY24, BLACK24), - ('table_head', 'white, bold', 'black', - None, WHITEBOLD24, BLACK24), - ('filter_results', 'black', 'light green', - None, BLACK24, LIGHTGREEN24), - ('edit_topic', 'black', 'dark gray', - None, BLACK24, GRAY24), - ('edit_tag', 'black', 'dark gray', - None, BLACK24, GRAY24), - ('edit_author', 'yellow', 'black', - None, YELLOW24, BLACK24), - ('edit_time', 'light blue', 'black', - None, LIGHTBLUE24, BLACK24), - ('current_user', 'white', 'black', - None, WHITE24, BLACK24), - ('muted', 'light blue', 'black', - None, LIGHTBLUE24, BLACK24), - ('popup_border', 'white', 'black', - None, WHITE24, BLACK24), - ('area:help', 'black', 'light green', - None, BLACK24, LIGHTGREEN24), - ('area:msg', 'black', 'light red', - None, BLACK24, LIGHTRED24), - ('area:stream', 'black', 'light blue', - None, BLACK24, LIGHTBLUE24), - ('area:error', 'white', 'dark red', - None, WHITE24, DARKRED24), - ('search_error', 'light red', 'black', - None, LIGHTRED24, BLACK24), - ('task:success', 'black', 'light green', - None, BLACK24, LIGHTGREEN24), - ('task:error', 'white', 'dark red', - None, WHITE24, DARKRED24), - ('task:warning', 'black', 'light red', - None, BLACK24, LIGHTRED24), - ], - 'zt_light': [ - (None, 'black', 'white'), - ('selected', 'black', 'light green'), - ('msg_selected', 'black', 'light green'), - ('header', 'white', 'dark blue'), - ('general_narrow', 'white', 'dark blue'), - ('general_bar', 'dark blue', 'white'), - ('name', 'dark green', 'white'), - ('unread', 'dark gray', 'light gray'), - ('user_active', 'dark green', 'white'), - ('user_idle', 'dark blue', 'white'), - ('user_offline', 'black', 'white'), - ('user_inactive', 'black', 'white'), - ('title', 'white, bold', 'dark gray'), - ('column_title', 'black, bold', 'white'), - ('time', 'dark blue', 'white'), - ('bar', 'white', 'dark gray'), - ('popup_contrast', 'white', 'dark gray'), - ('msg_emoji', 'light magenta', 'white'), - ('reaction', 'light magenta, bold', 'white'), - ('reaction_mine', 'white', 'light magenta'), - ('msg_mention', 'light red, bold', 'white'), - ('msg_link', 'dark blue', 'white'), - ('msg_link_index', 'dark blue, bold', 'white'), - ('msg_quote', 'black', 'brown'), - ('msg_code', 'black', 'light gray'), - ('msg_bold', 'white, bold', 'dark gray'), - ('msg_time', 'white', 'dark gray'), - ('footer', 'white', 'dark gray'), - ('footer_contrast', 'black', 'white'), - ('starred', 'light red, bold', 'white'), - ('popup_category', 'dark gray, bold', 'light gray'), - ('unread_count', 'dark blue, bold', 'white'), - ('starred_count', 'black', 'white'), - ('table_head', 'black, bold', 'white'), - ('filter_results', 'white', 'dark green'), - ('edit_topic', 'white', 'dark gray'), - ('edit_tag', 'white', 'dark gray'), - ('edit_author', 'dark green', 'white'), - ('edit_time', 'dark blue', 'white'), - ('current_user', 'dark gray', 'white'), - ('muted', 'dark gray', 'white'), - ('popup_border', 'black', 'white'), - ('area:help', 'black', 'light green'), - ('area:stream', 'black', 'light blue'), - ('area:msg', 'black', 'yellow'), - ('area:error', 'black', 'light red'), - ('search_error', 'light red', 'white'), - ('task:success', 'black', 'dark green'), - ('task:error', 'white', 'dark red'), - ('task:warning', 'black', 'yellow'), - ], - 'zt_blue': [ - (None, 'black', 'light blue'), - ('selected', 'black', 'light gray'), - ('msg_selected', 'black', 'light gray'), - ('header', 'black', 'dark blue'), - ('general_narrow', 'white', 'dark blue'), - ('general_bar', 'dark blue', 'light blue'), - ('name', 'dark red', 'light blue'), - ('unread', 'light gray', 'light blue'), - ('user_active', 'light green, bold', 'light blue'), - ('user_idle', 'dark gray', 'light blue'), - ('user_offline', 'black', 'light blue'), - ('user_inactive', 'black', 'light blue'), - ('title', 'white, bold', 'dark blue'), - ('column_title', 'black, bold', 'light blue'), - ('time', 'dark blue', 'light blue'), - ('bar', 'white', 'dark blue'), - ('popup_contrast', 'white', 'dark blue'), - ('msg_emoji', 'dark magenta', 'light blue'), - ('reaction', 'dark magenta, bold', 'light blue'), - ('reaction_mine', 'light blue', 'dark magenta'), - ('msg_mention', 'light red, bold', 'light blue'), - ('msg_link', 'dark blue', 'light gray'), - ('msg_link_index', 'dark blue, bold', 'light gray'), - ('msg_quote', 'brown', 'dark blue'), - ('msg_code', 'dark blue', 'white'), - ('msg_bold', 'white, bold', 'dark blue'), - ('msg_time', 'dark blue', 'white'), - ('footer', 'white', 'dark gray'), - ('footer_contrast', 'black', 'white'), - ('starred', 'light red, bold', 'light blue'), - ('popup_category', 'light gray, bold', 'light blue'), - ('unread_count', 'yellow', 'light blue'), - ('starred_count', 'black', 'light blue'), - ('table_head', 'black, bold', 'light blue'), - ('filter_results', 'white', 'dark green'), - ('edit_topic', 'white', 'dark blue'), - ('edit_tag', 'white', 'dark blue'), - ('edit_author', 'dark gray', 'light blue'), - ('edit_time', 'dark blue', 'light blue'), - ('current_user', 'light gray', 'light blue'), - ('muted', 'light gray', 'light blue'), - ('popup_border', 'white', 'light blue'), - ('area:help', 'white', 'dark green'), - ('area:stream', 'white', 'dark cyan'), - ('area:msg', 'white', 'brown'), - ('area:error', 'white', 'dark red'), - ('search_error', 'light red', 'light blue'), - ('task:success', 'white', 'dark green'), - ('task:error', 'white', 'dark red'), - ('task:warning', 'white', 'brown'), - ] -} -# fmt: on - def all_themes() -> List[str]: return list(THEMES.keys()) @@ -562,27 +95,45 @@ def aliased_themes() -> Dict[str, str]: def complete_and_incomplete_themes() -> Tuple[List[str], List[str]]: complete = { name - for name, styles in THEMES.items() - if {s[0] for s in styles} == set(required_styles) + for name, theme in THEMES.items() + if set(theme.STYLES) == set(REQUIRED_STYLES) } incomplete = list(set(THEMES) - complete) return sorted(list(complete)), sorted(incomplete) -def theme_with_monochrome_added(theme: ThemeSpec) -> ThemeSpec: - updated_theme = [] - for style in theme: - style_name = style[0] - if style_name not in required_styles: # incomplete theme - continue - mono_style = required_styles[style_name] - if len(style) > 4: # 256 colors+ - new_style = style[:3] + (mono_style,) + style[4:] - elif len(style) == 4: # 16 colors + mono (overwrite mono) - new_style = style[:3] + (mono_style,) - elif len(style) == 3: # 16 colors only - new_style = style[:3] + (mono_style,) - else: # 1-to-1 mapping (same as other style) - new_style = style - updated_theme.append(new_style) - return updated_theme +def generate_theme(theme_name: str, color_depth: int) -> ThemeSpec: + theme_styles = THEMES[theme_name].STYLES + urwid_theme = parse_themefile(theme_styles, color_depth) + return urwid_theme + + +def parse_themefile( + theme_styles: Dict[Optional[str], Tuple[Any, Any]], color_depth: int +) -> ThemeSpec: + urwid_theme = [] + for style_name, (fg, bg) in theme_styles.items(): + fg_code16, fg_code256, fg_code24, *fg_props = fg.value.split() + bg_code16, bg_code256, bg_code24, *bg_props = bg.value.split() + + new_style: StyleSpec + if color_depth == 1: + new_style = (style_name, "", "", REQUIRED_STYLES[style_name]) + + elif color_depth == 16: + fg = " ".join([fg_code16] + fg_props).replace("_", " ") + bg = " ".join([bg_code16] + bg_props).replace("_", " ") + new_style = (style_name, fg, bg) + + elif color_depth == 256: + fg = " ".join([fg_code256] + fg_props) + bg = " ".join([bg_code256] + bg_props) + new_style = (style_name, "", "", "", fg, bg) + + elif color_depth == 2 ** 24: + fg = " ".join([fg_code24] + fg_props) + bg = " ".join([bg_code24] + bg_props) + new_style = (style_name, "", "", "", fg, bg) + + urwid_theme.append(new_style) + return urwid_theme diff --git a/zulipterminal/themes/THEME_CONTRIBUTING.md b/zulipterminal/themes/THEME_CONTRIBUTING.md new file mode 100644 index 0000000000..553594fd14 --- /dev/null +++ b/zulipterminal/themes/THEME_CONTRIBUTING.md @@ -0,0 +1,100 @@ + +# ZT : THEME CONTRIBUTION GUIDE + +This document explains how Zulip Terminal manages themes. + +ZT uses theme-files to define a particular theme which can be found in the `zulipterminal/themes` folder. + +> **TIP**: For a theme to be accepted, it has to pass certain tests. The easiest way to make sure you have all the styles, format and spacing correct is to copy-paste an existing theme and then edit them but to understand more, read on! + +## COLOR SCHEME + +> Zulip creates some default color schemes for use in themes which can be found in `color.py`. These colors also make use of the BOLD property, more on which in the next section. Make sure if any of the existing color schemes from any of the existing themes can be useful. + +To use the default bold color scheme in a theme, paste this line at the top of the file: + +```python +from zulipterminal.config.color import DefaultBoldColor as Color +``` + +If BOLD is something that is not needed, just use: + +```python +from zulipterminal.config.color import DefaultColor as Color +``` + +Likewise, to use a color scheme from any other theme like Gruvbox, use: + +```python +from zulipterminal.themes.gruvbox import Color +``` + +--- + +If any of these are not enough for the theme that you want to create, the following format would give an idea of how to create a new color scheme ( Refer: `gruvbox.py` ). + +```python +class ThemeColor(Enum): + WHITE = '16code 256code 24code' + ... +``` + +We use **Enum** to define color constants. +Each color constant is a string containing 3 space separated +color codes: + +* **16code**: Terminal's default 16 color aliases. + * Only those used in DefaultColor are acceptable. + * Eg: `black, light_cyan, etc` +* **256code**: High color, 256 color code. + * Acceptable formats: `#000-#fff`, `h0-h255`, `g0-g100`, `g#00-g#ff` + * Eg: `#rgb or h255 or g19` +* **24code**: True color, 24 bit color code. + * Similar to HTML colors. + * Eg: `#rrggbb` + +`'default'` is a special alias which uses the default +foreground or background. + +### COLOR PROPERTIES + +The `color_properties()` function adds special properties like +Bold, Italics, Strikethrough, etc to the color scheme. + +```python +Color = color_properties(ThemeColor, 'BOLD', 'ITALICS', 'STRIKETHROUGH') +``` + +**Note**: It is advisable to only use BOLD as of now, similar to `DefaultBoldColor`, to support as many terminals as possible. + +## THEME STYLE + +To use these colors in a theme style use the dot notation: + +```python +(Color.BLACK, Color.DARK_CYAN) +``` + +Everything after a Dunder or Double Underscore +are considered as properties. + +```python +(Color.YELLOW__BOLD, Color.LIGHT_CYAN__BOLD_ITALICS) +``` + +The actual styles are defined in a dictionary called STYLES +which takes the style as the key and a tuple with foreground +and background as the value. + +```python +STYLES = { + # style_name : foreground background + 'selected' : (Color.BLACK, Color.LIGHT_GREEN) + ... +} +``` + +The REQUIRED_STYLES dictionary in `config/themes.py` shows all the required styles needed for a theme to be considered complete and pass tests but as mentioned above it is best to copy-paste an existing theme +and then edit it. + +If there are any issues, feel free to bring it up on [#zulip-terminal](https://chat.zulip.org/#narrow/stream/206-zulip-terminal) diff --git a/zulipterminal/themes/gruvbox.py b/zulipterminal/themes/gruvbox.py new file mode 100644 index 0000000000..b30f602457 --- /dev/null +++ b/zulipterminal/themes/gruvbox.py @@ -0,0 +1,90 @@ +""" +GRUVBOX +------- +This theme uses the official gruvbox color scheme. +For color reference see: + https://github.com/morhetz/gruvbox/blob/master/colors/gruvbox.vim + +For further details on themefiles look at the theme contribution guide +""" +from enum import Enum + +from zulipterminal.config.color import color_properties + + +# fmt: off +class GruvBoxColor(Enum): + # color = 16code 256code 24code + DEFAULT = 'default default default' + DARK0_HARD = 'black h234 #1d2021' + GRAY_244 = 'dark_gray h244 #928374' + LIGHT2 = 'white h250 #d5c4a1' + LIGHT4 = 'light_gray h248 #bdae93' + BRIGHT_BLUE = 'light_blue h109 #83a598' + BRIGHT_GREEN = 'light_green h142 #b8bb26' + BRIGHT_RED = 'light_red h167 #fb4934' + NEUTRAL_PURPLE = 'light_magenta h132 #b16286' + NEUTRAL_BLUE = 'dark_cyan h66 #458588' + NEUTRAL_YELLOW = 'yellow h172 #d79921' + FADED_BLUE = 'dark_blue h24 #076678' + FADED_YELLOW = 'brown h136 #b57614' + FADED_RED = 'dark_red h88 #9d0006' + + +Color = color_properties(GruvBoxColor, 'BOLD') + + +STYLES = { + # style_name : foreground background + None : (Color.LIGHT2, Color.DARK0_HARD), + 'selected' : (Color.DARK0_HARD, Color.LIGHT2), + 'msg_selected' : (Color.DARK0_HARD, Color.LIGHT2), + 'header' : (Color.NEUTRAL_BLUE, Color.FADED_BLUE), + 'general_narrow' : (Color.LIGHT2, Color.FADED_BLUE), + 'general_bar' : (Color.LIGHT2, Color.DARK0_HARD), + 'name' : (Color.NEUTRAL_YELLOW__BOLD, Color.DARK0_HARD), + 'unread' : (Color.NEUTRAL_PURPLE, Color.DARK0_HARD), + 'user_active' : (Color.BRIGHT_GREEN, Color.DARK0_HARD), + 'user_idle' : (Color.NEUTRAL_YELLOW, Color.DARK0_HARD), + 'user_offline' : (Color.LIGHT2, Color.DARK0_HARD), + 'user_inactive' : (Color.LIGHT2, Color.DARK0_HARD), + 'title' : (Color.LIGHT2__BOLD, Color.DARK0_HARD), + 'column_title' : (Color.LIGHT2__BOLD, Color.DARK0_HARD), + 'time' : (Color.BRIGHT_BLUE, Color.DARK0_HARD), + 'bar' : (Color.LIGHT2, Color.GRAY_244), + 'popup_contrast' : (Color.DARK0_HARD, Color.GRAY_244), + 'msg_emoji' : (Color.NEUTRAL_PURPLE, Color.DARK0_HARD), + 'reaction' : (Color.NEUTRAL_PURPLE__BOLD, Color.DARK0_HARD), + 'reaction_mine' : (Color.DARK0_HARD, Color.NEUTRAL_PURPLE), + 'msg_mention' : (Color.BRIGHT_RED__BOLD, Color.DARK0_HARD), + 'msg_link' : (Color.BRIGHT_BLUE, Color.DARK0_HARD), + 'msg_link_index' : (Color.BRIGHT_BLUE__BOLD, Color.DARK0_HARD), + 'msg_quote' : (Color.FADED_YELLOW, Color.DARK0_HARD), + 'msg_code' : (Color.DARK0_HARD, Color.LIGHT2), + 'msg_bold' : (Color.LIGHT2__BOLD, Color.DARK0_HARD), + 'msg_time' : (Color.DARK0_HARD, Color.LIGHT2), + 'footer' : (Color.DARK0_HARD, Color.LIGHT4), + 'footer_contrast' : (Color.LIGHT2, Color.DARK0_HARD), + 'starred' : (Color.BRIGHT_RED__BOLD, Color.DARK0_HARD), + 'popup_category' : (Color.BRIGHT_BLUE__BOLD, Color.DARK0_HARD), + 'unread_count' : (Color.NEUTRAL_YELLOW, Color.DARK0_HARD), + 'starred_count' : (Color.LIGHT4, Color.DARK0_HARD), + 'table_head' : (Color.LIGHT2__BOLD, Color.DARK0_HARD), + 'filter_results' : (Color.DARK0_HARD, Color.BRIGHT_GREEN), + 'edit_topic' : (Color.DARK0_HARD, Color.GRAY_244), + 'edit_tag' : (Color.DARK0_HARD, Color.GRAY_244), + 'edit_author' : (Color.NEUTRAL_YELLOW, Color.DARK0_HARD), + 'edit_time' : (Color.BRIGHT_BLUE, Color.DARK0_HARD), + 'current_user' : (Color.LIGHT2, Color.DARK0_HARD), + 'muted' : (Color.BRIGHT_BLUE, Color.DARK0_HARD), + 'popup_border' : (Color.LIGHT2, Color.DARK0_HARD), + 'area:help' : (Color.DARK0_HARD, Color.BRIGHT_GREEN), + 'area:msg' : (Color.DARK0_HARD, Color.BRIGHT_RED), + 'area:stream' : (Color.DARK0_HARD, Color.BRIGHT_BLUE), + 'area:error' : (Color.LIGHT2, Color.FADED_RED), + 'search_error' : (Color.BRIGHT_RED, Color.DARK0_HARD), + 'task:success' : (Color.DARK0_HARD, Color.BRIGHT_GREEN), + 'task:error' : (Color.LIGHT2, Color.FADED_RED), + 'task:warning' : (Color.DARK0_HARD, Color.BRIGHT_RED), +} +# fmt: on diff --git a/zulipterminal/themes/zt_blue.py b/zulipterminal/themes/zt_blue.py new file mode 100644 index 0000000000..cec70635c5 --- /dev/null +++ b/zulipterminal/themes/zt_blue.py @@ -0,0 +1,64 @@ +""" +ZT BLUE +------- +This theme uses the default color scheme. +For further details on themefiles look at the theme contribution guide +""" +from zulipterminal.config.color import DefaultBoldColor as Color + + +# fmt: off +STYLES = { + # style_name : foreground background + None : (Color.BLACK, Color.LIGHT_BLUE), + 'selected' : (Color.BLACK, Color.LIGHT_GRAY), + 'msg_selected' : (Color.BLACK, Color.LIGHT_GRAY), + 'header' : (Color.BLACK, Color.DARK_BLUE), + 'general_narrow' : (Color.WHITE, Color.DARK_BLUE), + 'general_bar' : (Color.DARK_BLUE, Color.LIGHT_BLUE), + 'name' : (Color.DARK_RED, Color.LIGHT_BLUE), + 'unread' : (Color.LIGHT_GRAY, Color.LIGHT_BLUE), + 'user_active' : (Color.LIGHT_GREEN__BOLD, Color.LIGHT_BLUE), + 'user_idle' : (Color.DARK_GRAY, Color.LIGHT_BLUE), + 'user_offline' : (Color.BLACK, Color.LIGHT_BLUE), + 'user_inactive' : (Color.BLACK, Color.LIGHT_BLUE), + 'title' : (Color.WHITE__BOLD, Color.DARK_BLUE), + 'column_title' : (Color.BLACK__BOLD, Color.LIGHT_BLUE), + 'time' : (Color.DARK_BLUE, Color.LIGHT_BLUE), + 'bar' : (Color.WHITE, Color.DARK_BLUE), + 'popup_contrast' : (Color.WHITE, Color.DARK_BLUE), + 'msg_emoji' : (Color.DARK_MAGENTA, Color.LIGHT_BLUE), + 'reaction' : (Color.DARK_MAGENTA__BOLD, Color.LIGHT_BLUE), + 'reaction_mine' : (Color.LIGHT_BLUE, Color.DARK_MAGENTA), + 'msg_mention' : (Color.LIGHT_RED__BOLD, Color.LIGHT_BLUE), + 'msg_link' : (Color.DARK_BLUE, Color.LIGHT_GRAY), + 'msg_link_index' : (Color.DARK_BLUE__BOLD, Color.LIGHT_GRAY), + 'msg_quote' : (Color.BROWN, Color.DARK_BLUE), + 'msg_code' : (Color.DARK_BLUE, Color.WHITE), + 'msg_bold' : (Color.WHITE__BOLD, Color.DARK_BLUE), + 'msg_time' : (Color.DARK_BLUE, Color.WHITE), + 'footer' : (Color.WHITE, Color.DARK_GRAY), + 'footer_contrast' : (Color.BLACK, Color.WHITE), + 'starred' : (Color.LIGHT_RED__BOLD, Color.LIGHT_BLUE), + 'popup_category' : (Color.LIGHT_GRAY__BOLD, Color.LIGHT_BLUE), + 'unread_count' : (Color.YELLOW, Color.LIGHT_BLUE), + 'starred_count' : (Color.BLACK, Color.LIGHT_BLUE), + 'table_head' : (Color.BLACK__BOLD, Color.LIGHT_BLUE), + 'filter_results' : (Color.WHITE, Color.DARK_GREEN), + 'edit_topic' : (Color.WHITE, Color.DARK_BLUE), + 'edit_tag' : (Color.WHITE, Color.DARK_BLUE), + 'edit_author' : (Color.DARK_GRAY, Color.LIGHT_BLUE), + 'edit_time' : (Color.DARK_BLUE, Color.LIGHT_BLUE), + 'current_user' : (Color.LIGHT_GRAY, Color.LIGHT_BLUE), + 'muted' : (Color.LIGHT_GRAY, Color.LIGHT_BLUE), + 'popup_border' : (Color.WHITE, Color.LIGHT_BLUE), + 'area:help' : (Color.WHITE, Color.DARK_GREEN), + 'area:stream' : (Color.WHITE, Color.DARK_CYAN), + 'area:msg' : (Color.WHITE, Color.BROWN), + 'area:error' : (Color.WHITE, Color.DARK_RED), + 'search_error' : (Color.LIGHT_RED, Color.LIGHT_BLUE), + 'task:success' : (Color.WHITE, Color.DARK_GREEN), + 'task:error' : (Color.WHITE, Color.DARK_RED), + 'task:warning' : (Color.WHITE, Color.BROWN), +} +# fmt: on diff --git a/zulipterminal/themes/zt_dark.py b/zulipterminal/themes/zt_dark.py new file mode 100644 index 0000000000..60097b09dc --- /dev/null +++ b/zulipterminal/themes/zt_dark.py @@ -0,0 +1,64 @@ +""" +ZT DARK +------- +This theme uses the default color scheme. +For further details on themefiles look at the theme contribution guide. +""" +from zulipterminal.config.color import DefaultBoldColor as Color + + +# fmt: off +STYLES = { + # style_name : foreground background + None : (Color.WHITE, Color.BLACK), + 'selected' : (Color.WHITE, Color.DARK_BLUE), + 'msg_selected' : (Color.WHITE, Color.DARK_BLUE), + 'header' : (Color.DARK_CYAN, Color.DARK_BLUE), + 'general_narrow' : (Color.WHITE, Color.DARK_BLUE), + 'general_bar' : (Color.WHITE, Color.BLACK), + 'name' : (Color.YELLOW__BOLD, Color.BLACK), + 'unread' : (Color.DARK_BLUE, Color.BLACK), + 'user_active' : (Color.LIGHT_GREEN, Color.BLACK), + 'user_idle' : (Color.YELLOW, Color.BLACK), + 'user_offline' : (Color.WHITE, Color.BLACK), + 'user_inactive' : (Color.WHITE, Color.BLACK), + 'title' : (Color.WHITE__BOLD, Color.BLACK), + 'column_title' : (Color.WHITE__BOLD, Color.BLACK), + 'time' : (Color.LIGHT_BLUE, Color.BLACK), + 'bar' : (Color.WHITE, Color.DARK_GRAY), + 'popup_contrast' : (Color.WHITE, Color.DARK_GRAY), + 'msg_emoji' : (Color.LIGHT_MAGENTA, Color.BLACK), + 'reaction' : (Color.LIGHT_MAGENTA__BOLD, Color.BLACK), + 'reaction_mine' : (Color.BLACK, Color.LIGHT_MAGENTA), + 'msg_mention' : (Color.LIGHT_RED__BOLD, Color.BLACK), + 'msg_link' : (Color.LIGHT_BLUE, Color.BLACK), + 'msg_link_index' : (Color.LIGHT_BLUE__BOLD, Color.BLACK), + 'msg_quote' : (Color.BROWN, Color.BLACK), + 'msg_code' : (Color.BLACK, Color.WHITE), + 'msg_bold' : (Color.WHITE__BOLD, Color.BLACK), + 'msg_time' : (Color.BLACK, Color.WHITE), + 'footer' : (Color.BLACK, Color.LIGHT_GRAY), + 'footer_contrast' : (Color.WHITE, Color.BLACK), + 'starred' : (Color.LIGHT_RED__BOLD, Color.BLACK), + 'popup_category' : (Color.LIGHT_BLUE__BOLD, Color.BLACK), + 'unread_count' : (Color.YELLOW, Color.BLACK), + 'starred_count' : (Color.LIGHT_GRAY, Color.BLACK), + 'table_head' : (Color.WHITE__BOLD, Color.BLACK), + 'filter_results' : (Color.WHITE, Color.DARK_GREEN), + 'edit_topic' : (Color.WHITE, Color.DARK_GRAY), + 'edit_tag' : (Color.WHITE, Color.DARK_GRAY), + 'edit_author' : (Color.YELLOW, Color.BLACK), + 'edit_time' : (Color.LIGHT_BLUE, Color.BLACK), + 'current_user' : (Color.WHITE, Color.BLACK), + 'muted' : (Color.LIGHT_BLUE, Color.BLACK), + 'popup_border' : (Color.WHITE, Color.BLACK), + 'area:help' : (Color.WHITE, Color.DARK_GREEN), + 'area:msg' : (Color.WHITE, Color.BROWN), + 'area:stream' : (Color.WHITE, Color.DARK_CYAN), + 'area:error' : (Color.WHITE, Color.DARK_RED), + 'search_error' : (Color.LIGHT_RED, Color.BLACK), + 'task:success' : (Color.WHITE, Color.DARK_GREEN), + 'task:error' : (Color.WHITE, Color.DARK_RED), + 'task:warning' : (Color.WHITE, Color.BROWN), +} +# fmt: on diff --git a/zulipterminal/themes/zt_light.py b/zulipterminal/themes/zt_light.py new file mode 100644 index 0000000000..736043de7b --- /dev/null +++ b/zulipterminal/themes/zt_light.py @@ -0,0 +1,64 @@ +""" +ZT LIGHT +-------- +This theme uses the default color scheme. +For further details on themefiles look at the theme contribution guide. +""" +from zulipterminal.config.color import DefaultBoldColor as Color + + +# fmt: off +STYLES = { + # style_name : foreground background + None : (Color.BLACK, Color.WHITE), + 'selected' : (Color.BLACK, Color.LIGHT_GREEN), + 'msg_selected' : (Color.BLACK, Color.LIGHT_GREEN), + 'header' : (Color.WHITE, Color.DARK_BLUE), + 'general_narrow' : (Color.WHITE, Color.DARK_BLUE), + 'general_bar' : (Color.DARK_BLUE, Color.WHITE), + 'name' : (Color.DARK_GREEN, Color.WHITE), + 'unread' : (Color.DARK_GRAY, Color.LIGHT_GRAY), + 'user_active' : (Color.DARK_GREEN, Color.WHITE), + 'user_idle' : (Color.DARK_BLUE, Color.WHITE), + 'user_offline' : (Color.BLACK, Color.WHITE), + 'user_inactive' : (Color.BLACK, Color.WHITE), + 'title' : (Color.WHITE__BOLD, Color.DARK_GRAY), + 'column_title' : (Color.BLACK__BOLD, Color.WHITE), + 'time' : (Color.DARK_BLUE, Color.WHITE), + 'bar' : (Color.WHITE, Color.DARK_GRAY), + 'popup_contrast' : (Color.WHITE, Color.DARK_GRAY), + 'msg_emoji' : (Color.LIGHT_MAGENTA, Color.WHITE), + 'reaction' : (Color.LIGHT_MAGENTA__BOLD, Color.WHITE), + 'reaction_mine' : (Color.WHITE, Color.LIGHT_MAGENTA), + 'msg_mention' : (Color.LIGHT_RED__BOLD, Color.WHITE), + 'msg_link' : (Color.DARK_BLUE, Color.WHITE), + 'msg_link_index' : (Color.DARK_BLUE__BOLD, Color.WHITE), + 'msg_quote' : (Color.BLACK, Color.BROWN), + 'msg_code' : (Color.BLACK, Color.LIGHT_GRAY), + 'msg_bold' : (Color.WHITE__BOLD, Color.DARK_GRAY), + 'msg_time' : (Color.WHITE, Color.DARK_GRAY), + 'footer' : (Color.WHITE, Color.DARK_GRAY), + 'footer_contrast' : (Color.BLACK, Color.WHITE), + 'starred' : (Color.LIGHT_RED__BOLD, Color.WHITE), + 'popup_category' : (Color.DARK_GRAY__BOLD, Color.LIGHT_GRAY), + 'unread_count' : (Color.DARK_BLUE__BOLD, Color.WHITE), + 'starred_count' : (Color.BLACK, Color.WHITE), + 'table_head' : (Color.BLACK__BOLD, Color.WHITE), + 'filter_results' : (Color.WHITE, Color.DARK_GREEN), + 'edit_topic' : (Color.WHITE, Color.DARK_GRAY), + 'edit_tag' : (Color.WHITE, Color.DARK_GRAY), + 'edit_author' : (Color.DARK_GREEN, Color.WHITE), + 'edit_time' : (Color.DARK_BLUE, Color.WHITE), + 'current_user' : (Color.DARK_GRAY, Color.WHITE), + 'muted' : (Color.DARK_GRAY, Color.WHITE), + 'popup_border' : (Color.BLACK, Color.WHITE), + 'area:help' : (Color.BLACK, Color.LIGHT_GREEN), + 'area:stream' : (Color.BLACK, Color.LIGHT_BLUE), + 'area:msg' : (Color.BLACK, Color.YELLOW), + 'area:error' : (Color.BLACK, Color.LIGHT_RED), + 'search_error' : (Color.LIGHT_RED, Color.WHITE), + 'task:success' : (Color.BLACK, Color.DARK_GREEN), + 'task:error' : (Color.WHITE, Color.DARK_RED), + 'task:warning' : (Color.BLACK, Color.YELLOW), +} +# fmt: on