From 978cdb918afbc9b637a9e30bd16f5354ec410608 Mon Sep 17 00:00:00 2001 From: Michael Lazar Date: Wed, 20 Sep 2017 12:46:44 -0400 Subject: [PATCH] Fixing a few edge cases --- rtv/page.py | 13 +++++++--- rtv/terminal.py | 22 ++++++++++++---- rtv/theme.py | 33 ++++++++++-------------- rtv/themes/high_contrast.cfg | 50 ------------------------------------ scripts/demo_theme.py | 13 ++++++---- 5 files changed, 49 insertions(+), 82 deletions(-) delete mode 100644 rtv/themes/high_contrast.cfg diff --git a/rtv/page.py b/rtv/page.py index 06e7657..a27193a 100644 --- a/rtv/page.py +++ b/rtv/page.py @@ -11,7 +11,6 @@ import six from kitchen.text.display import textual_width from . import docs -from .theme import get_next_theme, get_previous_theme from .objects import Controller, Command from .clipboard import copy from .exceptions import TemporaryFileError, ProgramError @@ -98,7 +97,11 @@ class Page(object): @PageController.register(Command('PREVIOUS_THEME')) def previous_theme(self): - theme = get_previous_theme(self.term.theme) + + theme = self.term.theme_list.previous(self.term.theme) + while not self.term.test_theme(theme): + theme = self.term.theme_list.previous(theme) + self.term.set_theme(theme) self.draw() message = self.term.theme.display_string @@ -106,7 +109,11 @@ class Page(object): @PageController.register(Command('NEXT_THEME')) def next_theme(self): - theme = get_next_theme(self.term.theme) + + theme = self.term.theme_list.next(self.term.theme) + while not self.term.test_theme(theme): + theme = self.term.theme_list.next(theme) + self.term.set_theme(theme) self.draw() message = self.term.theme.display_string diff --git a/rtv/terminal.py b/rtv/terminal.py index be672c3..86ca610 100644 --- a/rtv/terminal.py +++ b/rtv/terminal.py @@ -21,7 +21,7 @@ import six from kitchen.text.display import textual_width_chop from . import exceptions, mime_parsers -from .theme import Theme +from .theme import Theme, ThemeList from .objects import LoadScreen try: @@ -57,6 +57,7 @@ class Terminal(object): self.config = config self.loader = LoadScreen(self) self.theme = None # Initialized by term.set_theme() + self.theme_list = ThemeList() self._display = None self._mailcap_dict = mailcap.getcaps() @@ -829,6 +830,20 @@ class Terminal(object): return self.theme.get(element) + @staticmethod + def test_theme(theme): + """ + Check if the given theme is supported by the terminal + """ + terminal_colors = curses.COLORS if curses.has_colors() else 0 + + if theme.required_colors > terminal_colors: + return False + elif theme.required_color_pairs > curses.COLOR_PAIRS: + return False + else: + return True + def set_theme(self, theme=None): """ Check that the terminal supports the provided theme, and applies @@ -839,10 +854,7 @@ class Terminal(object): should be compatible with any terminal that supports basic colors. """ - if curses.has_colors(): - terminal_colors = curses.COLORS - else: - terminal_colors = 0 + terminal_colors = curses.COLORS if curses.has_colors() else 0 if theme is None: theme = Theme(use_color=bool(terminal_colors)) diff --git a/rtv/theme.py b/rtv/theme.py index 11870c6..e157162 100644 --- a/rtv/theme.py +++ b/rtv/theme.py @@ -50,8 +50,6 @@ class Theme(object): for i in range(256): COLOR_CODES['ansi_{0}'.format(i)] = i - # TODO: Apply selected on top of items, not underneath them - # For compatibility with as many terminals as possible, the default theme # can only use the 8 basic colors with the default color as the background DEFAULT_THEME = { @@ -159,26 +157,28 @@ class Theme(object): elements[key] = (None, None, None) self._set_fallback(elements, 'Normal', (-1, -1, curses.A_NORMAL)) - self._set_fallback(elements, 'Selected', 'Normal') - self._set_fallback(elements, 'SelectedCursor', 'Normal') - # Most elements have two possible attribute states: - # 1. The default state - inherits from "Normal" - # 2. The selected state - inherits from "Selected" and is - # prefixed by the "@" sign. + # Fill in the ``None`` values for all of the elements with normal text for name in self.DEFAULT_THEME['normal']: - dest = '@{0}'.format(name) - self._set_fallback(elements, name, 'Selected', dest) self._set_fallback(elements, name, 'Normal') - for name in self.DEFAULT_THEME['cursor']: - dest = '@{0}'.format(name) - self._set_fallback(elements, name, 'SelectedCursor', dest) self._set_fallback(elements, name, 'Normal') - for name in self.DEFAULT_THEME['page']: self._set_fallback(elements, name, 'Normal') + # Create the "Selected" versions of elements, which are prefixed with + # the @ symbol. For example, "@CommentText" represents how comment + # text is formatted when it is highlighted by the cursor. + for name in self.DEFAULT_THEME['normal']: + dest = '@{0}'.format(name) + self._set_fallback(elements, 'Selected', name, dest) + for name in self.DEFAULT_THEME['cursor']: + dest = '@{0}'.format(name) + self._set_fallback(elements, 'SelectedCursor', name, dest) + + self._set_fallback(elements, 'Selected', 'Normal') + self._set_fallback(elements, 'SelectedCursor', 'Normal') + self.elements = elements if self.use_color: @@ -546,8 +546,3 @@ class ThemeList(object): def previous(self, theme): return self._step(theme, -1) - - -theme_list = ThemeList() -get_next_theme = theme_list.next -get_previous_theme = theme_list.previous diff --git a/rtv/themes/high_contrast.cfg b/rtv/themes/high_contrast.cfg deleted file mode 100644 index a86df95..0000000 --- a/rtv/themes/high_contrast.cfg +++ /dev/null @@ -1,50 +0,0 @@ -[theme] -; = -Normal = default default - -Selected = - - - -SelectedCursor = - - reverse - -TitleBar = cyan - bold+reverse -OrderBar = yellow - bold -OrderBarHighlight = yellow - bold+reverse -HelpBar = cyan - bold+reverse -Prompt = cyan - bold+reverse -NoticeInfo = - - bold -NoticeLoading = - - bold -NoticeError = - - bold -NoticeSuccess = - - bold - -CursorBlock = - - - -CursorBar1 = magenta - - -CursorBar2 = cyan - - -CursorBar3 = green - - -CursorBar4 = yellow - - - -CommentAuthor = cyan - bold -CommentAuthorSelf = green - bold -CommentCount = - - - -CommentText = - - - -Created = - - - -Downvote = red - bold -Gold = yellow - bold -HiddenCommentExpand = - - bold -HiddenCommentText = - - - -MultiredditName = yellow - bold -MultiredditText = - - - -NeutralVote = - - bold -NSFW = red - bold+reverse -Saved = green - - -Score = - - - -Separator = - - bold -Stickied = green - - -SubscriptionName = yellow - bold -SubscriptionText = - - - -SubmissionAuthor = green - bold -SubmissionFlair = red - - -SubmissionSubreddit = yellow - - -SubmissionText = - - - -SubmissionTitle = - - bold -Upvote = green - bold -Link = cyan - underline -LinkSeen = magenta - underline -UserFlair = yellow - bold \ No newline at end of file diff --git a/scripts/demo_theme.py b/scripts/demo_theme.py index 16ee199..bc16c0d 100755 --- a/scripts/demo_theme.py +++ b/scripts/demo_theme.py @@ -15,7 +15,7 @@ from collections import Counter from vcr import VCR from six.moves.urllib.parse import urlparse, parse_qs -from rtv.theme import Theme, get_next_theme, get_previous_theme, theme_list +from rtv.theme import Theme, ThemeList from rtv.config import Config from rtv.packages import praw from rtv.oauth import OAuthHelper @@ -244,6 +244,8 @@ def main(): oauth = OAuthHelper(reddit, term, config) oauth.authorize() + theme_list = ThemeList() + while True: term = Terminal(stdscr, config) term.set_theme(theme) @@ -266,14 +268,15 @@ def main(): theme_list.reload() if ch == curses.KEY_RIGHT: - theme = get_next_theme(theme) + theme = theme_list.next(theme) elif ch == curses.KEY_LEFT: - theme = get_previous_theme(theme) + theme = theme_list.previous(theme) elif ch == Terminal.ESCAPE: break else: # Force the theme to reload - theme = get_next_theme(theme) - theme = get_previous_theme(theme) + theme = theme_list.next(theme) + theme = theme_list.previous(theme) sys.exit(main()) +