Merge pull request #385 from ihabunek/colors-settings
Read TUI colors from settings
This commit is contained in:
commit
5e8a7bb415
5 changed files with 105 additions and 84 deletions
|
@ -50,3 +50,62 @@ sensitive = true
|
|||
visibility = "unlisted"
|
||||
scheduled_in = "30 minutes"
|
||||
```
|
||||
|
||||
## TUI color palette
|
||||
|
||||
TUI uses Urwid which provides several color modes. See
|
||||
[Urwid documentation](https://urwid.org/manual/displayattributes.html)
|
||||
for more details.
|
||||
|
||||
By default, TUI operates in 16-color mode which can be changed by setting the
|
||||
`color` setting in the `[tui]` section to one of the following values:
|
||||
|
||||
* `1` (monochrome)
|
||||
* `16` (default)
|
||||
* `88`
|
||||
* `256`
|
||||
* `16777216` (24 bit)
|
||||
|
||||
TUI defines a list of colors which can be customized, currently they can be seen
|
||||
[in the source code](https://github.com/ihabunek/toot/blob/master/toot/tui/constants.py). They can be overriden in the `[tui.palette]` section.
|
||||
|
||||
Each color is defined as a list of upto 5 values:
|
||||
|
||||
* foreground color (16 color mode)
|
||||
* background color (16 color mode)
|
||||
* monochrome color (monochrome mode)
|
||||
* foreground color (high-color mode)
|
||||
* background color (high-color mode)
|
||||
|
||||
Any colors which are not used by your desired color mode can be skipped or set
|
||||
to an empty string.
|
||||
|
||||
For example, to change the button colors in 16 color mode:
|
||||
|
||||
```toml
|
||||
[tui.palette]
|
||||
button = ["dark red,bold", ""]
|
||||
button_focused = ["light gray", "green"]
|
||||
```
|
||||
|
||||
In monochrome mode:
|
||||
|
||||
```toml
|
||||
[tui]
|
||||
colors = 1
|
||||
|
||||
[tui.palette]
|
||||
button = ["", "", "bold"]
|
||||
button_focused = ["", "", "italics"]
|
||||
```
|
||||
|
||||
In 256 color mode:
|
||||
|
||||
```toml
|
||||
[tui]
|
||||
colors = 256
|
||||
|
||||
[tui.palette]
|
||||
button = ["", "", "", "#aaa", "#bbb"]
|
||||
button_focused = ["", "", "", "#aaa", "#bbb"]
|
||||
```
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
from toot.tui.constants import PALETTE, MONO_PALETTE
|
||||
|
||||
|
||||
def test_palette():
|
||||
# for every entry in PALETTE, there must be
|
||||
# a corresponding entry in MONO_PALETTE
|
||||
for pal in PALETTE:
|
||||
matches = [item for item in MONO_PALETTE if item[0] == pal[0]]
|
||||
assert len(matches) > 0, f"{pal}, present in PALETTE, missing from MONO_PALETTE"
|
||||
|
||||
# for every entry in MONO_PALETTE, there must be
|
||||
# a corresponding entry in PALETTE
|
||||
for pal in MONO_PALETTE:
|
||||
matches = [item for item in PALETTE if item[0] == pal[0]]
|
||||
assert len(matches) > 0, f"{pal}, present in MONO_PALETTE, missing from PALETTE"
|
|
@ -3,12 +3,12 @@ import urwid
|
|||
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
from toot import api, config, __version__
|
||||
from toot import api, config, __version__, settings
|
||||
from toot.console import get_default_visibility
|
||||
from toot.exceptions import ApiError
|
||||
|
||||
from .compose import StatusComposer
|
||||
from .constants import PALETTE, MONO_PALETTE
|
||||
from .constants import PALETTE
|
||||
from .entities import Status
|
||||
from .overlays import ExceptionStackTrace, GotoMenu, Help, StatusSource, StatusLinks, StatusZoom
|
||||
from .overlays import StatusDeleteConfirmation, Account
|
||||
|
@ -78,19 +78,20 @@ class TUI(urwid.Frame):
|
|||
loop: urwid.MainLoop
|
||||
screen: urwid.BaseScreen
|
||||
|
||||
@classmethod
|
||||
def create(cls, app, user, args):
|
||||
@staticmethod
|
||||
def create(app, user, args):
|
||||
"""Factory method, sets up TUI and an event loop."""
|
||||
screen = urwid.raw_display.Screen()
|
||||
tui = cls(app, user, screen, args)
|
||||
screen = TUI.create_screen(args)
|
||||
tui = TUI(app, user, screen, args)
|
||||
|
||||
if args.no_color:
|
||||
screen.set_terminal_properties(1)
|
||||
screen.reset_default_terminal_palette()
|
||||
palette = PALETTE.copy()
|
||||
overrides = settings.get_setting("tui.palette", dict, {})
|
||||
for name, styles in overrides.items():
|
||||
palette.append(tuple([name] + styles))
|
||||
|
||||
loop = urwid.MainLoop(
|
||||
tui,
|
||||
palette=MONO_PALETTE if args.no_color else PALETTE,
|
||||
palette=palette,
|
||||
event_loop=urwid.AsyncioEventLoop(),
|
||||
unhandled_input=tui.unhandled_input,
|
||||
screen=screen,
|
||||
|
@ -99,6 +100,18 @@ class TUI(urwid.Frame):
|
|||
|
||||
return tui
|
||||
|
||||
@staticmethod
|
||||
def create_screen(args):
|
||||
screen = urwid.raw_display.Screen()
|
||||
|
||||
# Determine how many colors to use
|
||||
default_colors = 1 if args.no_color else 16
|
||||
colors = settings.get_setting("tui.colors", int, default_colors)
|
||||
logger.debug(f"Setting colors to {colors}")
|
||||
screen.set_terminal_properties(colors)
|
||||
|
||||
return screen
|
||||
|
||||
def __init__(self, app, user, screen, args):
|
||||
self.app = app
|
||||
self.user = user
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
# name, fg, bg, mono, fg_h, bg_h
|
||||
# Color definitions are tuples of:
|
||||
# - name
|
||||
# - foreground (normal mode)
|
||||
# - background (normal mode)
|
||||
# - foreground (monochrome mode)
|
||||
# - foreground (high color mode)
|
||||
# - background (high color mode)
|
||||
#
|
||||
# See:
|
||||
# http://urwid.org/tutorial/index.html#display-attributes
|
||||
# http://urwid.org/manual/displayattributes.html#using-display-attributes
|
||||
|
||||
PALETTE = [
|
||||
# Components
|
||||
('button', 'white', 'black'),
|
||||
('button_focused', 'light gray', 'dark magenta'),
|
||||
('button_focused', 'light gray', 'dark magenta', 'bold,underline'),
|
||||
('card_author', 'yellow', ''),
|
||||
('card_title', 'dark green', ''),
|
||||
('columns_divider', 'white', 'dark blue'),
|
||||
|
@ -14,7 +25,7 @@ PALETTE = [
|
|||
('footer_status', 'white', 'dark blue'),
|
||||
('footer_status_bold', 'white, bold', 'dark blue'),
|
||||
('header', 'white', 'dark blue'),
|
||||
('header_bold', 'white,bold', 'dark blue'),
|
||||
('header_bold', 'white,bold', 'dark blue', 'bold'),
|
||||
('intro_bigtext', 'yellow', ''),
|
||||
('intro_smalltext', 'light blue', ''),
|
||||
('poll_bar', 'white', 'dark blue'),
|
||||
|
@ -22,16 +33,17 @@ PALETTE = [
|
|||
('status_detail_bookmarked', 'light red', ''),
|
||||
('status_detail_timestamp', 'light blue', ''),
|
||||
('status_list_account', 'dark green', ''),
|
||||
('status_list_selected', 'white,bold', 'dark green'),
|
||||
('status_list_selected', 'white,bold', 'dark green', 'bold,underline'),
|
||||
('status_list_timestamp', 'light blue', ''),
|
||||
|
||||
# Functional
|
||||
('hashtag', 'light cyan,bold', ''),
|
||||
('hashtag_followed', 'yellow,bold', ''),
|
||||
('link', ',italics', ''),
|
||||
('link_focused', ',italics', 'dark magenta'),
|
||||
('account', 'dark green', ''),
|
||||
('hashtag', 'light cyan,bold', '', 'bold'),
|
||||
('hashtag_followed', 'yellow,bold', '', 'bold'),
|
||||
('link', ',italics', '', ',italics'),
|
||||
('link_focused', ',italics', 'dark magenta', "underline,italics"),
|
||||
('shortcut', 'light blue', ''),
|
||||
('shortcut_highlight', 'white,bold', ''),
|
||||
('shortcut_highlight', 'white,bold', '', 'bold'),
|
||||
('warning', 'light red', ''),
|
||||
|
||||
# Visiblity
|
||||
|
@ -47,54 +59,6 @@ PALETTE = [
|
|||
('success', 'dark green', ''),
|
||||
]
|
||||
|
||||
MONO_PALETTE = [
|
||||
# Components
|
||||
('button', 'white', 'black'),
|
||||
('button_focused', 'black', 'white'),
|
||||
('card_author', 'white', ''),
|
||||
('card_title', 'white, bold', ''),
|
||||
('columns_divider', 'white', 'black'),
|
||||
('content_warning', 'white', 'black'),
|
||||
('editbox', 'white', 'black'),
|
||||
('editbox_focused', 'black', 'white'),
|
||||
('footer_message', 'white', 'black'),
|
||||
('footer_message_error', 'white,bold', 'black'),
|
||||
('footer_status', 'black', 'white'),
|
||||
('footer_status_bold', 'black,bold', 'white'),
|
||||
('header', 'black', 'white'),
|
||||
('header_bold', 'black,bold', 'white'),
|
||||
('intro_bigtext', 'white', 'black'),
|
||||
('intro_smalltext', 'white', 'black'),
|
||||
('poll_bar', 'black', 'white'),
|
||||
('status_detail_account', 'white', ''),
|
||||
('status_detail_bookmarked', 'white', ''),
|
||||
('status_detail_timestamp', 'white', ''),
|
||||
('status_list_account', 'white', ''),
|
||||
('status_list_selected', 'white,bold', ''),
|
||||
('status_list_timestamp', 'white', ''),
|
||||
('warning', 'white,bold', 'black'),
|
||||
|
||||
# Functional
|
||||
('hashtag_followed', 'white,bold', ''),
|
||||
('hashtag', 'white,bold', ''),
|
||||
('link', ',italics', ''),
|
||||
('link_focused', ',bold,italics', ''),
|
||||
('shortcut', 'white', ''),
|
||||
('shortcut_highlight', 'white,bold', ''),
|
||||
|
||||
# Visiblity
|
||||
('visibility_public', 'white', ''),
|
||||
('visibility_unlisted', 'white', ''),
|
||||
('visibility_private', 'white', ''),
|
||||
('visibility_direct', 'white', ''),
|
||||
|
||||
# Styles
|
||||
('bold', ',bold', ''),
|
||||
('dim', 'light gray', ''),
|
||||
('highlight', ',bold', ''),
|
||||
('success', '', ''),
|
||||
]
|
||||
|
||||
VISIBILITY_OPTIONS = [
|
||||
("public", "Public", "Post to public timelines"),
|
||||
("unlisted", "Unlisted", "Do not post to public timelines"),
|
||||
|
|
|
@ -326,9 +326,9 @@ class StatusDetails(urwid.Pile):
|
|||
yield ("pack", urwid.AttrMap(urwid.Divider("-"), "dim"))
|
||||
|
||||
if status.author.display_name:
|
||||
yield ("pack", urwid.Text(("status_detail_author", status.author.display_name)))
|
||||
yield ("pack", urwid.Text(("bold", status.author.display_name)))
|
||||
|
||||
account_color = "highlight" if status.author.account in self.followed_accounts else "dim"
|
||||
account_color = "highlight" if status.author.account in self.followed_accounts else "account"
|
||||
yield ("pack", urwid.Text((account_color, status.author.account)))
|
||||
yield ("pack", urwid.Divider())
|
||||
|
||||
|
|
Loading…
Reference in a new issue