Switching to more vim-inspired theme attributes
This commit is contained in:
@@ -178,8 +178,10 @@ def main():
|
|||||||
term = Terminal(stdscr, config)
|
term = Terminal(stdscr, config)
|
||||||
|
|
||||||
if config['monochrome']:
|
if config['monochrome']:
|
||||||
|
_logger.info('Using monochrome theme')
|
||||||
theme = Theme(use_color=False)
|
theme = Theme(use_color=False)
|
||||||
elif config['theme']:
|
elif config['theme']:
|
||||||
|
_logger.info('Loading theme: %s', config['theme'])
|
||||||
theme = Theme.from_name(config['theme'])
|
theme = Theme.from_name(config['theme'])
|
||||||
else:
|
else:
|
||||||
# Set to None to let the terminal figure out which default
|
# Set to None to let the terminal figure out which default
|
||||||
|
|||||||
@@ -193,23 +193,23 @@ class OAuthHelper(object):
|
|||||||
# If an exception is raised it will be seen by the thread
|
# If an exception is raised it will be seen by the thread
|
||||||
# so we don't need to explicitly shutdown() the server
|
# so we don't need to explicitly shutdown() the server
|
||||||
_logger.exception(e)
|
_logger.exception(e)
|
||||||
self.term.show_notification('Browser Error', style='error')
|
self.term.show_notification('Browser Error', style='Error')
|
||||||
else:
|
else:
|
||||||
self.server.shutdown()
|
self.server.shutdown()
|
||||||
finally:
|
finally:
|
||||||
thread.join()
|
thread.join()
|
||||||
|
|
||||||
if self.params['error'] == 'access_denied':
|
if self.params['error'] == 'access_denied':
|
||||||
self.term.show_notification('Denied access', style='error')
|
self.term.show_notification('Denied access', style='Error')
|
||||||
return
|
return
|
||||||
elif self.params['error']:
|
elif self.params['error']:
|
||||||
self.term.show_notification('Authentication error', style='error')
|
self.term.show_notification('Authentication error', style='Error')
|
||||||
return
|
return
|
||||||
elif self.params['state'] is None:
|
elif self.params['state'] is None:
|
||||||
# Something went wrong but it's not clear what happened
|
# Something went wrong but it's not clear what happened
|
||||||
return
|
return
|
||||||
elif self.params['state'] != state:
|
elif self.params['state'] != state:
|
||||||
self.term.show_notification('UUID mismatch', style='error')
|
self.term.show_notification('UUID mismatch', style='Error')
|
||||||
return
|
return
|
||||||
|
|
||||||
with self.term.loader('Logging in'):
|
with self.term.loader('Logging in'):
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ class LoadScreen(object):
|
|||||||
# Some exceptions we want to swallow and display a notification
|
# Some exceptions we want to swallow and display a notification
|
||||||
if isinstance(e, e_type):
|
if isinstance(e, e_type):
|
||||||
msg = message.format(e)
|
msg = message.format(e)
|
||||||
self._terminal.show_notification(msg, style='error')
|
self._terminal.show_notification(msg, style='Error')
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def animate(self, delay, interval, message, trail):
|
def animate(self, delay, interval, message, trail):
|
||||||
@@ -260,7 +260,7 @@ class LoadScreen(object):
|
|||||||
s_row = (n_rows - 3) // 2 + v_offset
|
s_row = (n_rows - 3) // 2 + v_offset
|
||||||
s_col = (n_cols - message_len - 1) // 2 + h_offset
|
s_col = (n_cols - message_len - 1) // 2 + h_offset
|
||||||
window = curses.newwin(3, message_len + 2, s_row, s_col)
|
window = curses.newwin(3, message_len + 2, s_row, s_col)
|
||||||
window.bkgd(str(' '), self._terminal.attr('notice_loading'))
|
window.bkgd(str(' '), self._terminal.attr('NoticeLoading'))
|
||||||
|
|
||||||
# Animate the loading prompt until the stopping condition is triggered
|
# Animate the loading prompt until the stopping condition is triggered
|
||||||
# when the context manager exits.
|
# when the context manager exits.
|
||||||
|
|||||||
18
rtv/page.py
18
rtv/page.py
@@ -367,7 +367,7 @@ class Page(object):
|
|||||||
window = self.term.stdscr.derwin(1, n_cols, self._row, 0)
|
window = self.term.stdscr.derwin(1, n_cols, self._row, 0)
|
||||||
window.erase()
|
window.erase()
|
||||||
# curses.bkgd expects bytes in py2 and unicode in py3
|
# curses.bkgd expects bytes in py2 and unicode in py3
|
||||||
window.bkgd(str(' '), self.term.attr('title_bar'))
|
window.bkgd(str(' '), self.term.attr('PageTitle'))
|
||||||
|
|
||||||
sub_name = self.content.name
|
sub_name = self.content.name
|
||||||
sub_name = sub_name.replace('/r/front', 'Front Page')
|
sub_name = sub_name.replace('/r/front', 'Front Page')
|
||||||
@@ -420,7 +420,7 @@ class Page(object):
|
|||||||
n_rows, n_cols = self.term.stdscr.getmaxyx()
|
n_rows, n_cols = self.term.stdscr.getmaxyx()
|
||||||
window = self.term.stdscr.derwin(1, n_cols, self._row, 0)
|
window = self.term.stdscr.derwin(1, n_cols, self._row, 0)
|
||||||
window.erase()
|
window.erase()
|
||||||
window.bkgd(str(' '), self.term.attr('order_bar'))
|
window.bkgd(str(' '), self.term.attr('PageOrder'))
|
||||||
|
|
||||||
banner = docs.BANNER_SEARCH if self.content.query else docs.BANNER
|
banner = docs.BANNER_SEARCH if self.content.query else docs.BANNER
|
||||||
items = banner.strip().split(' ')
|
items = banner.strip().split(' ')
|
||||||
@@ -432,7 +432,7 @@ class Page(object):
|
|||||||
if self.content.order is not None:
|
if self.content.order is not None:
|
||||||
order = self.content.order.split('-')[0]
|
order = self.content.order.split('-')[0]
|
||||||
col = text.find(order) - 3
|
col = text.find(order) - 3
|
||||||
attr = self.term.theme.get('order_bar', modifier='highlight')
|
attr = self.term.attr('PageOrderHighlight')
|
||||||
window.chgat(0, col, 3, attr)
|
window.chgat(0, col, 3, attr)
|
||||||
|
|
||||||
self._row += 1
|
self._row += 1
|
||||||
@@ -499,17 +499,17 @@ class Page(object):
|
|||||||
# pushed out of bounds
|
# pushed out of bounds
|
||||||
self.nav.cursor_index = len(self._subwindows) - 1
|
self.nav.cursor_index = len(self._subwindows) - 1
|
||||||
|
|
||||||
|
# TODO: Don't highlight the submission box
|
||||||
|
|
||||||
# Now that the windows are setup, we can take a second pass through
|
# Now that the windows are setup, we can take a second pass through
|
||||||
# to draw the content
|
# to draw the content
|
||||||
for index, (win, data, inverted) in enumerate(self._subwindows):
|
for index, (win, data, inverted) in enumerate(self._subwindows):
|
||||||
if index == self.nav.cursor_index:
|
if index == self.nav.cursor_index:
|
||||||
win.bkgd(str(' '), self.term.attr('@highlight'))
|
win.bkgd(str(' '), self.term.attr('Selected'))
|
||||||
# This lets the theme know to invert the cursor color and
|
with self.term.theme.turn_on_selected():
|
||||||
# apply any other special highlighting effects to the window
|
|
||||||
with self.term.theme.set_modifier('highlight'):
|
|
||||||
self._draw_item(win, data, inverted)
|
self._draw_item(win, data, inverted)
|
||||||
else:
|
else:
|
||||||
win.bkgd(str(' '), self.term.attr('@normal'))
|
win.bkgd(str(' '), self.term.attr('Normal'))
|
||||||
self._draw_item(win, data, inverted)
|
self._draw_item(win, data, inverted)
|
||||||
|
|
||||||
self._row += win_n_rows
|
self._row += win_n_rows
|
||||||
@@ -519,7 +519,7 @@ class Page(object):
|
|||||||
n_rows, n_cols = self.term.stdscr.getmaxyx()
|
n_rows, n_cols = self.term.stdscr.getmaxyx()
|
||||||
window = self.term.stdscr.derwin(1, n_cols, self._row, 0)
|
window = self.term.stdscr.derwin(1, n_cols, self._row, 0)
|
||||||
window.erase()
|
window.erase()
|
||||||
window.bkgd(str(' '), self.term.attr('help_bar'))
|
window.bkgd(str(' '), self.term.attr('Help'))
|
||||||
|
|
||||||
text = self.FOOTER.strip()
|
text = self.FOOTER.strip()
|
||||||
self.term.add_line(window, text, 0, 0)
|
self.term.add_line(window, text, 0, 0)
|
||||||
|
|||||||
@@ -315,15 +315,15 @@ class SubmissionPage(Page):
|
|||||||
row = offset
|
row = offset
|
||||||
if row in valid_rows:
|
if row in valid_rows:
|
||||||
if data['is_author']:
|
if data['is_author']:
|
||||||
attr = self.term.attr('comment_author_self')
|
attr = self.term.attr('CommentAuthorSelf')
|
||||||
text = '{author} [S]'.format(**data)
|
text = '{author} [S]'.format(**data)
|
||||||
else:
|
else:
|
||||||
attr = self.term.attr('comment_author')
|
attr = self.term.attr('CommentAuthor')
|
||||||
text = '{author}'.format(**data)
|
text = '{author}'.format(**data)
|
||||||
self.term.add_line(win, text, row, 1, attr)
|
self.term.add_line(win, text, row, 1, attr)
|
||||||
|
|
||||||
if data['flair']:
|
if data['flair']:
|
||||||
attr = self.term.attr('user_flair')
|
attr = self.term.attr('UserFlair')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '{flair}'.format(**data), attr=attr)
|
self.term.add_line(win, '{flair}'.format(**data), attr=attr)
|
||||||
|
|
||||||
@@ -331,38 +331,38 @@ class SubmissionPage(Page):
|
|||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, arrow, attr=attr)
|
self.term.add_line(win, arrow, attr=attr)
|
||||||
|
|
||||||
attr = self.term.attr('score')
|
attr = self.term.attr('Score')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '{score}'.format(**data), attr=attr)
|
self.term.add_line(win, '{score}'.format(**data), attr=attr)
|
||||||
|
|
||||||
attr = self.term.attr('created')
|
attr = self.term.attr('Created')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '{created}'.format(**data), attr=attr)
|
self.term.add_line(win, '{created}'.format(**data), attr=attr)
|
||||||
|
|
||||||
if data['gold']:
|
if data['gold']:
|
||||||
attr = self.term.attr('gold')
|
attr = self.term.attr('Gold')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, self.term.guilded, attr=attr)
|
self.term.add_line(win, self.term.guilded, attr=attr)
|
||||||
|
|
||||||
if data['stickied']:
|
if data['stickied']:
|
||||||
attr = self.term.attr('stickied')
|
attr = self.term.attr('Stickied')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '[stickied]', attr=attr)
|
self.term.add_line(win, '[stickied]', attr=attr)
|
||||||
|
|
||||||
if data['saved']:
|
if data['saved']:
|
||||||
attr = self.term.attr('saved')
|
attr = self.term.attr('Saved')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '[saved]', attr=attr)
|
self.term.add_line(win, '[saved]', attr=attr)
|
||||||
|
|
||||||
for row, text in enumerate(split_body, start=offset+1):
|
for row, text in enumerate(split_body, start=offset+1):
|
||||||
attr = self.term.attr('comment_text')
|
attr = self.term.attr('CommentText')
|
||||||
if row in valid_rows:
|
if row in valid_rows:
|
||||||
self.term.add_line(win, text, row, 1, attr=attr)
|
self.term.add_line(win, text, row, 1, attr=attr)
|
||||||
|
|
||||||
# Unfortunately vline() doesn't support custom color so we have to
|
# curses.vline() doesn't support custom colors so need to build the
|
||||||
# build it one segment at a time.
|
# cursor bar on the left of the comment one character at a time
|
||||||
index = data['level'] % len(self.term.theme.BAR_LEVELS)
|
index = data['level'] % len(self.term.theme.CURSOR_BARS)
|
||||||
attr = self.term.attr(self.term.theme.BAR_LEVELS[index])
|
attr = self.term.attr(self.term.theme.CURSOR_BARS[index])
|
||||||
for y in range(n_rows):
|
for y in range(n_rows):
|
||||||
self.term.addch(win, y, 0, self.term.vline, attr)
|
self.term.addch(win, y, 0, self.term.vline, attr)
|
||||||
|
|
||||||
@@ -371,15 +371,15 @@ class SubmissionPage(Page):
|
|||||||
n_rows, n_cols = win.getmaxyx()
|
n_rows, n_cols = win.getmaxyx()
|
||||||
n_cols -= 1
|
n_cols -= 1
|
||||||
|
|
||||||
attr = self.term.attr('hidden_comment_text')
|
attr = self.term.attr('HiddenCommentText')
|
||||||
self.term.add_line(win, '{body}'.format(**data), 0, 1, attr=attr)
|
self.term.add_line(win, '{body}'.format(**data), 0, 1, attr=attr)
|
||||||
|
|
||||||
attr = self.term.attr('hidden_comment_expand')
|
attr = self.term.attr('HiddenCommentExpand')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '[{count}]'.format(**data), attr=attr)
|
self.term.add_line(win, '[{count}]'.format(**data), attr=attr)
|
||||||
|
|
||||||
index = data['level'] % len(self.term.theme.BAR_LEVELS)
|
index = data['level'] % len(self.term.theme.CURSOR_BARS)
|
||||||
attr = self.term.attr(self.term.theme.BAR_LEVELS[index])
|
attr = self.term.attr(self.term.theme.CURSOR_BARS[index])
|
||||||
self.term.addch(win, 0, 0, self.term.vline, attr)
|
self.term.addch(win, 0, 0, self.term.vline, attr)
|
||||||
|
|
||||||
def _draw_submission(self, win, data):
|
def _draw_submission(self, win, data):
|
||||||
@@ -387,32 +387,32 @@ class SubmissionPage(Page):
|
|||||||
n_rows, n_cols = win.getmaxyx()
|
n_rows, n_cols = win.getmaxyx()
|
||||||
n_cols -= 3 # one for each side of the border + one for offset
|
n_cols -= 3 # one for each side of the border + one for offset
|
||||||
|
|
||||||
attr = self.term.attr('submission_title')
|
attr = self.term.attr('SubmissionTitle')
|
||||||
for row, text in enumerate(data['split_title'], start=1):
|
for row, text in enumerate(data['split_title'], start=1):
|
||||||
self.term.add_line(win, text, row, 1, attr)
|
self.term.add_line(win, text, row, 1, attr)
|
||||||
|
|
||||||
row = len(data['split_title']) + 1
|
row = len(data['split_title']) + 1
|
||||||
attr = self.term.attr('submission_author')
|
attr = self.term.attr('SubmissionAuthor')
|
||||||
self.term.add_line(win, '{author}'.format(**data), row, 1, attr)
|
self.term.add_line(win, '{author}'.format(**data), row, 1, attr)
|
||||||
|
|
||||||
if data['flair']:
|
if data['flair']:
|
||||||
attr = self.term.attr('submission_flair')
|
attr = self.term.attr('SubmissionFlair')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '{flair}'.format(**data), attr=attr)
|
self.term.add_line(win, '{flair}'.format(**data), attr=attr)
|
||||||
|
|
||||||
attr = self.term.attr('created')
|
attr = self.term.attr('Created')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '{created}'.format(**data), attr=attr)
|
self.term.add_line(win, '{created}'.format(**data), attr=attr)
|
||||||
|
|
||||||
attr = self.term.attr('submission_subreddit')
|
attr = self.term.attr('SubmissionSubreddit')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '/r/{subreddit}'.format(**data), attr=attr)
|
self.term.add_line(win, '/r/{subreddit}'.format(**data), attr=attr)
|
||||||
|
|
||||||
row = len(data['split_title']) + 2
|
row = len(data['split_title']) + 2
|
||||||
if data['url_full'] in self.config.history:
|
if data['url_full'] in self.config.history:
|
||||||
attr = self.term.attr('url_seen')
|
attr = self.term.attr('LinkSeen')
|
||||||
else:
|
else:
|
||||||
attr = self.term.attr('url')
|
attr = self.term.attr('Link')
|
||||||
self.term.add_line(win, '{url}'.format(**data), row, 1, attr)
|
self.term.add_line(win, '{url}'.format(**data), row, 1, attr)
|
||||||
|
|
||||||
offset = len(data['split_title']) + 3
|
offset = len(data['split_title']) + 3
|
||||||
@@ -424,34 +424,34 @@ class SubmissionPage(Page):
|
|||||||
split_text = split_text[:-cutoff]
|
split_text = split_text[:-cutoff]
|
||||||
split_text.append('(Not enough space to display)')
|
split_text.append('(Not enough space to display)')
|
||||||
|
|
||||||
attr = self.term.attr('submission_text')
|
attr = self.term.attr('SubmissionText')
|
||||||
for row, text in enumerate(split_text, start=offset):
|
for row, text in enumerate(split_text, start=offset):
|
||||||
self.term.add_line(win, text, row, 1, attr=attr)
|
self.term.add_line(win, text, row, 1, attr=attr)
|
||||||
|
|
||||||
row = len(data['split_title']) + len(split_text) + 3
|
row = len(data['split_title']) + len(split_text) + 3
|
||||||
attr = self.term.attr('score')
|
attr = self.term.attr('Score')
|
||||||
self.term.add_line(win, '{score}'.format(**data), row, 1, attr=attr)
|
self.term.add_line(win, '{score}'.format(**data), row, 1, attr=attr)
|
||||||
|
|
||||||
arrow, attr = self.term.get_arrow(data['likes'])
|
arrow, attr = self.term.get_arrow(data['likes'])
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, arrow, attr=attr)
|
self.term.add_line(win, arrow, attr=attr)
|
||||||
|
|
||||||
attr = self.term.attr('comment_count')
|
attr = self.term.attr('CommentCount')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '{comments}'.format(**data), attr=attr)
|
self.term.add_line(win, '{comments}'.format(**data), attr=attr)
|
||||||
|
|
||||||
if data['gold']:
|
if data['gold']:
|
||||||
attr = self.term.attr('gold')
|
attr = self.term.attr('Gold')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, self.term.guilded, attr=attr)
|
self.term.add_line(win, self.term.guilded, attr=attr)
|
||||||
|
|
||||||
if data['nsfw']:
|
if data['nsfw']:
|
||||||
attr = self.term.attr('nsfw')
|
attr = self.term.attr('NSFW')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, 'NSFW', attr=attr)
|
self.term.add_line(win, 'NSFW', attr=attr)
|
||||||
|
|
||||||
if data['saved']:
|
if data['saved']:
|
||||||
attr = self.term.attr('saved')
|
attr = self.term.attr('Saved')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '[saved]', attr=attr)
|
self.term.add_line(win, '[saved]', attr=attr)
|
||||||
|
|
||||||
|
|||||||
@@ -304,22 +304,22 @@ class SubredditPage(Page):
|
|||||||
|
|
||||||
n_title = len(data['split_title'])
|
n_title = len(data['split_title'])
|
||||||
for row, text in enumerate(data['split_title'], start=offset):
|
for row, text in enumerate(data['split_title'], start=offset):
|
||||||
attr = self.term.attr('submission_title')
|
attr = self.term.attr('SubmissionTitle')
|
||||||
if row in valid_rows:
|
if row in valid_rows:
|
||||||
self.term.add_line(win, text, row, 1, attr)
|
self.term.add_line(win, text, row, 1, attr)
|
||||||
|
|
||||||
row = n_title + offset
|
row = n_title + offset
|
||||||
if row in valid_rows:
|
if row in valid_rows:
|
||||||
if data['url_full'] in self.config.history:
|
if data['url_full'] in self.config.history:
|
||||||
attr = self.term.attr('url_seen')
|
attr = self.term.attr('LinkSeen')
|
||||||
else:
|
else:
|
||||||
attr = self.term.attr('url')
|
attr = self.term.attr('Link')
|
||||||
self.term.add_line(win, '{url}'.format(**data), row, 1, attr)
|
self.term.add_line(win, '{url}'.format(**data), row, 1, attr)
|
||||||
|
|
||||||
row = n_title + offset + 1
|
row = n_title + offset + 1
|
||||||
if row in valid_rows:
|
if row in valid_rows:
|
||||||
|
|
||||||
attr = self.term.attr('score')
|
attr = self.term.attr('Score')
|
||||||
self.term.add_line(win, '{score}'.format(**data), row, 1, attr)
|
self.term.add_line(win, '{score}'.format(**data), row, 1, attr)
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
|
|
||||||
@@ -327,52 +327,52 @@ class SubredditPage(Page):
|
|||||||
self.term.add_line(win, arrow, attr=attr)
|
self.term.add_line(win, arrow, attr=attr)
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
|
|
||||||
attr = self.term.attr('created')
|
attr = self.term.attr('Created')
|
||||||
self.term.add_line(win, '{created}'.format(**data), attr=attr)
|
self.term.add_line(win, '{created}'.format(**data), attr=attr)
|
||||||
|
|
||||||
if data['comments'] is not None:
|
if data['comments'] is not None:
|
||||||
attr = self.term.attr('separator')
|
attr = self.term.attr('Separator')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '-', attr=attr)
|
self.term.add_line(win, '-', attr=attr)
|
||||||
|
|
||||||
attr = self.term.attr('comment_count')
|
attr = self.term.attr('CommentCount')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '{comments}'.format(**data), attr=attr)
|
self.term.add_line(win, '{comments}'.format(**data), attr=attr)
|
||||||
|
|
||||||
if data['saved']:
|
if data['saved']:
|
||||||
attr = self.term.attr('saved')
|
attr = self.term.attr('Saved')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '[saved]', attr=attr)
|
self.term.add_line(win, '[saved]', attr=attr)
|
||||||
|
|
||||||
if data['stickied']:
|
if data['stickied']:
|
||||||
attr = self.term.attr('stickied')
|
attr = self.term.attr('Stickied')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '[stickied]', attr=attr)
|
self.term.add_line(win, '[stickied]', attr=attr)
|
||||||
|
|
||||||
if data['gold']:
|
if data['gold']:
|
||||||
attr = self.term.attr('gold')
|
attr = self.term.attr('Gold')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, self.term.guilded, attr=attr)
|
self.term.add_line(win, self.term.guilded, attr=attr)
|
||||||
|
|
||||||
if data['nsfw']:
|
if data['nsfw']:
|
||||||
attr = self.term.attr('nsfw')
|
attr = self.term.attr('NSFW')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, 'NSFW', attr=attr)
|
self.term.add_line(win, 'NSFW', attr=attr)
|
||||||
|
|
||||||
row = n_title + offset + 2
|
row = n_title + offset + 2
|
||||||
if row in valid_rows:
|
if row in valid_rows:
|
||||||
attr = self.term.attr('submission_author')
|
attr = self.term.attr('SubmissionAuthor')
|
||||||
self.term.add_line(win, '{author}'.format(**data), row, 1, attr)
|
self.term.add_line(win, '{author}'.format(**data), row, 1, attr)
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
|
|
||||||
attr = self.term.attr('submission_subreddit')
|
attr = self.term.attr('SubmissionSubreddit')
|
||||||
self.term.add_line(win, '/r/{subreddit}'.format(**data), attr=attr)
|
self.term.add_line(win, '/r/{subreddit}'.format(**data), attr=attr)
|
||||||
|
|
||||||
if data['flair']:
|
if data['flair']:
|
||||||
attr = self.term.attr('submission_flair')
|
attr = self.term.attr('SubmissionFlair')
|
||||||
self.term.add_space(win)
|
self.term.add_space(win)
|
||||||
self.term.add_line(win, '{flair}'.format(**data), attr=attr)
|
self.term.add_line(win, '{flair}'.format(**data), attr=attr)
|
||||||
|
|
||||||
attr = self.term.attr('cursor')
|
attr = self.term.attr('CursorBlock')
|
||||||
for y in range(n_rows):
|
for y in range(n_rows):
|
||||||
self.term.addch(win, y, 0, str(' '), attr)
|
self.term.addch(win, y, 0, str(' '), attr)
|
||||||
|
|||||||
@@ -93,20 +93,20 @@ class SubscriptionPage(Page):
|
|||||||
row = offset
|
row = offset
|
||||||
if row in valid_rows:
|
if row in valid_rows:
|
||||||
if data['type'] == 'Multireddit':
|
if data['type'] == 'Multireddit':
|
||||||
attr = self.term.attr('multireddit_name')
|
attr = self.term.attr('MultiredditName')
|
||||||
else:
|
else:
|
||||||
attr = self.term.attr('subscription_name')
|
attr = self.term.attr('SubscriptionName')
|
||||||
self.term.add_line(win, '{name}'.format(**data), row, 1, attr)
|
self.term.add_line(win, '{name}'.format(**data), row, 1, attr)
|
||||||
|
|
||||||
row = offset + 1
|
row = offset + 1
|
||||||
for row, text in enumerate(data['split_title'], start=row):
|
for row, text in enumerate(data['split_title'], start=row):
|
||||||
if row in valid_rows:
|
if row in valid_rows:
|
||||||
if data['type'] == 'Multireddit':
|
if data['type'] == 'Multireddit':
|
||||||
attr = self.term.attr('multireddit_text')
|
attr = self.term.attr('MultiredditText')
|
||||||
else:
|
else:
|
||||||
attr = self.term.attr('subscription_text')
|
attr = self.term.attr('SubscriptionText')
|
||||||
self.term.add_line(win, text, row, 1, attr)
|
self.term.add_line(win, text, row, 1, attr)
|
||||||
|
|
||||||
attr = self.term.attr('cursor')
|
attr = self.term.attr('CursorBlock')
|
||||||
for y in range(n_rows):
|
for y in range(n_rows):
|
||||||
self.term.addch(win, y, 0, str(' '), attr)
|
self.term.addch(win, y, 0, str(' '), attr)
|
||||||
|
|||||||
@@ -191,11 +191,11 @@ class Terminal(object):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if likes is None:
|
if likes is None:
|
||||||
return self.neutral_arrow, self.attr('neutral_vote')
|
return self.neutral_arrow, self.attr('NeutralVote')
|
||||||
elif likes:
|
elif likes:
|
||||||
return self.up_arrow, self.attr('upvote')
|
return self.up_arrow, self.attr('Upvote')
|
||||||
else:
|
else:
|
||||||
return self.down_arrow, self.attr('downvote')
|
return self.down_arrow, self.attr('Downvote')
|
||||||
|
|
||||||
def clean(self, string, n_cols=None):
|
def clean(self, string, n_cols=None):
|
||||||
"""
|
"""
|
||||||
@@ -287,7 +287,7 @@ class Terminal(object):
|
|||||||
|
|
||||||
window.addstr(row, col, ' ')
|
window.addstr(row, col, ' ')
|
||||||
|
|
||||||
def show_notification(self, message, timeout=None, style='info'):
|
def show_notification(self, message, timeout=None, style='Info'):
|
||||||
"""
|
"""
|
||||||
Overlay a message box on the center of the screen and wait for input.
|
Overlay a message box on the center of the screen and wait for input.
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ class Terminal(object):
|
|||||||
notification window
|
notification window
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert style in ('info', 'warning', 'error', 'success')
|
assert style in ('Info', 'Warning', 'Error', 'Success')
|
||||||
|
|
||||||
if isinstance(message, six.string_types):
|
if isinstance(message, six.string_types):
|
||||||
message = message.splitlines()
|
message = message.splitlines()
|
||||||
@@ -319,7 +319,7 @@ class Terminal(object):
|
|||||||
s_col = (n_cols - box_width) // 2 + h_offset
|
s_col = (n_cols - box_width) // 2 + h_offset
|
||||||
|
|
||||||
window = curses.newwin(box_height, box_width, s_row, s_col)
|
window = curses.newwin(box_height, box_width, s_row, s_col)
|
||||||
window.bkgd(str(' '), self.attr('notice_{0}'.format(style)))
|
window.bkgd(str(' '), self.attr('Notice{0}'.format(style)))
|
||||||
window.erase()
|
window.erase()
|
||||||
window.border()
|
window.border()
|
||||||
|
|
||||||
@@ -708,7 +708,7 @@ class Terminal(object):
|
|||||||
|
|
||||||
n_rows, n_cols = self.stdscr.getmaxyx()
|
n_rows, n_cols = self.stdscr.getmaxyx()
|
||||||
v_offset, h_offset = self.stdscr.getbegyx()
|
v_offset, h_offset = self.stdscr.getbegyx()
|
||||||
ch, attr = str(' '), self.attr('prompt')
|
ch, attr = str(' '), self.attr('Prompt')
|
||||||
prompt = self.clean(prompt, n_cols-1)
|
prompt = self.clean(prompt, n_cols-1)
|
||||||
|
|
||||||
# Create a new window to draw the text at the bottom of the screen,
|
# Create a new window to draw the text at the bottom of the screen,
|
||||||
@@ -864,8 +864,7 @@ class Terminal(object):
|
|||||||
theme = Theme()
|
theme = Theme()
|
||||||
|
|
||||||
theme.bind_curses()
|
theme.bind_curses()
|
||||||
|
self.theme = theme
|
||||||
|
|
||||||
# Apply the default color to the whole screen
|
# Apply the default color to the whole screen
|
||||||
self.stdscr.bkgd(str(' '), theme.get('@normal'))
|
self.stdscr.bkgd(str(' '), self.attr('Normal'))
|
||||||
|
|
||||||
self.theme = theme
|
|
||||||
|
|||||||
270
rtv/theme.py
270
rtv/theme.py
@@ -47,66 +47,120 @@ class Theme(object):
|
|||||||
'white': 15,
|
'white': 15,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Add keywords for the 256 ansi color codes
|
|
||||||
for i in range(256):
|
for i in range(256):
|
||||||
COLOR_CODES['ansi_{0}'.format(i)] = i
|
COLOR_CODES['ansi_{0}'.format(i)] = i
|
||||||
|
|
||||||
|
# TODO: Do another pass through these names
|
||||||
|
|
||||||
# For compatibility with as many terminals as possible, the default theme
|
# 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
|
# can only use the 8 basic colors with the default color as the background
|
||||||
DEFAULT_THEME = {
|
DEFAULT_THEME = {
|
||||||
'@normal': (-1, -1, curses.A_NORMAL),
|
'Normal': (None, None, None),
|
||||||
'@highlight': (-1, -1, curses.A_NORMAL),
|
'Selected': (None, None, None),
|
||||||
|
'SelectedCursor': (None, None, curses.A_REVERSE),
|
||||||
|
|
||||||
'bar_level_1': (curses.COLOR_MAGENTA, None, curses.A_NORMAL),
|
'PageTitle': (curses.COLOR_CYAN, None, curses.A_BOLD | curses.A_REVERSE),
|
||||||
'bar_level_1.highlight': (curses.COLOR_MAGENTA, None, curses.A_REVERSE),
|
'PageOrder': (curses.COLOR_YELLOW, None, curses.A_BOLD),
|
||||||
'bar_level_2': (curses.COLOR_CYAN, None, curses.A_NORMAL),
|
'PageOrderHighlight': (curses.COLOR_YELLOW, None, curses.A_BOLD | curses.A_REVERSE),
|
||||||
'bar_level_2.highlight': (curses.COLOR_CYAN, None, curses.A_REVERSE),
|
'Help': (curses.COLOR_CYAN, None, curses.A_BOLD | curses.A_REVERSE),
|
||||||
'bar_level_3': (curses.COLOR_GREEN, None, curses.A_NORMAL),
|
'Prompt': (curses.COLOR_CYAN, None, curses.A_BOLD | curses.A_REVERSE),
|
||||||
'bar_level_3.highlight': (curses.COLOR_GREEN, None, curses.A_REVERSE),
|
'NoticeInfo': (None, None, curses.A_BOLD),
|
||||||
'bar_level_4': (curses.COLOR_YELLOW, None, curses.A_NORMAL),
|
'NoticeLoading': (None, None, curses.A_BOLD),
|
||||||
'bar_level_4.highlight': (curses.COLOR_YELLOW, None, curses.A_REVERSE),
|
'NoticeError': (None, None, curses.A_BOLD),
|
||||||
'comment_author': (curses.COLOR_BLUE, None, curses.A_BOLD),
|
'NoticeSuccess': (None, None, curses.A_BOLD),
|
||||||
'comment_author_self': (curses.COLOR_GREEN, None, curses.A_BOLD),
|
|
||||||
'comment_count': (None, None, curses.A_NORMAL),
|
'CursorBlock': (None, None, None),
|
||||||
'comment_text': (None, None, curses.A_NORMAL),
|
'CursorBar1': (curses.COLOR_MAGENTA, None, None),
|
||||||
'created': (None, None, curses.A_NORMAL),
|
'CursorBar2': (curses.COLOR_CYAN, None, None),
|
||||||
'cursor': (None, None, curses.A_NORMAL),
|
'CursorBar3': (curses.COLOR_GREEN, None, None),
|
||||||
'cursor.highlight': (None, None, curses.A_REVERSE),
|
'CursorBar4': (curses.COLOR_YELLOW, None, None),
|
||||||
'downvote': (curses.COLOR_RED, None, curses.A_BOLD),
|
|
||||||
'gold': (curses.COLOR_YELLOW, None, curses.A_BOLD),
|
'CommentAuthor': (curses.COLOR_BLUE, None, curses.A_BOLD),
|
||||||
'help_bar': (curses.COLOR_CYAN, None, curses.A_BOLD | curses.A_REVERSE),
|
'CommentAuthorSelf': (curses.COLOR_GREEN, None, curses.A_BOLD),
|
||||||
'hidden_comment_expand': (None, None, curses.A_BOLD),
|
'CommentCount': (None, None, None),
|
||||||
'hidden_comment_text': (None, None, curses.A_NORMAL),
|
'CommentText': (None, None, None),
|
||||||
'multireddit_name': (curses.COLOR_YELLOW, None, curses.A_BOLD),
|
'Created': (None, None, None),
|
||||||
'multireddit_text': (None, None, curses.A_NORMAL),
|
'Downvote': (curses.COLOR_RED, None, curses.A_BOLD),
|
||||||
'neutral_vote': (None, None, curses.A_BOLD),
|
'Gold': (curses.COLOR_YELLOW, None, curses.A_BOLD),
|
||||||
'notice_info': (None, None, curses.A_NORMAL),
|
'HiddenCommentExpand': (None, None, curses.A_BOLD),
|
||||||
'notice_loading': (None, None, curses.A_NORMAL),
|
'HiddenCommentText': (None, None, None),
|
||||||
'notice_error': (curses.COLOR_RED, None, curses.A_NORMAL),
|
'MultiredditName': (curses.COLOR_YELLOW, None, curses.A_BOLD),
|
||||||
'notice_success': (curses.COLOR_GREEN, None, curses.A_NORMAL),
|
'MultiredditText': (None, None, None),
|
||||||
'nsfw': (curses.COLOR_RED, None, curses.A_BOLD),
|
'NeutralVote': (None, None, curses.A_BOLD),
|
||||||
'order_bar': (curses.COLOR_YELLOW, None, curses.A_BOLD),
|
'NSFW': (curses.COLOR_RED, None, curses.A_BOLD),
|
||||||
'order_bar.highlight': (curses.COLOR_YELLOW, None, curses.A_BOLD | curses.A_REVERSE),
|
'Saved': (curses.COLOR_GREEN, None, None),
|
||||||
'prompt': (curses.COLOR_CYAN, None, curses.A_BOLD | curses.A_REVERSE),
|
'Score': (None, None, None),
|
||||||
'saved': (curses.COLOR_GREEN, None, curses.A_NORMAL),
|
'Separator': (None, None, curses.A_BOLD),
|
||||||
'score': (None, None, curses.A_NORMAL),
|
'Stickied': (curses.COLOR_GREEN, None, None),
|
||||||
'separator': (None, None, curses.A_BOLD),
|
'SubscriptionName': (curses.COLOR_YELLOW, None, curses.A_BOLD),
|
||||||
'stickied': (curses.COLOR_GREEN, None, curses.A_NORMAL),
|
'SubscriptionText': (None, None, None),
|
||||||
'subscription_name': (curses.COLOR_YELLOW, None, curses.A_BOLD),
|
'SubmissionAuthor': (curses.COLOR_GREEN, None, None),
|
||||||
'subscription_text': (None, None, curses.A_NORMAL),
|
'SubmissionFlair': (curses.COLOR_RED, None, None),
|
||||||
'submission_author': (curses.COLOR_GREEN, None, curses.A_NORMAL),
|
'SubmissionSubreddit': (curses.COLOR_YELLOW, None, None),
|
||||||
'submission_flair': (curses.COLOR_RED, None, curses.A_NORMAL),
|
'SubmissionText': (None, None, None),
|
||||||
'submission_subreddit': (curses.COLOR_YELLOW, None, curses.A_NORMAL),
|
'SubmissionTitle': (None, None, curses.A_BOLD),
|
||||||
'submission_text': (None, None, curses.A_NORMAL),
|
'Upvote': (curses.COLOR_GREEN, None, curses.A_BOLD),
|
||||||
'submission_title': (None, None, curses.A_BOLD),
|
'Link': (curses.COLOR_BLUE, None, curses.A_UNDERLINE),
|
||||||
'title_bar': (curses.COLOR_CYAN, None, curses.A_BOLD | curses.A_REVERSE),
|
'LinkSeen': (curses.COLOR_MAGENTA, None, curses.A_UNDERLINE),
|
||||||
'upvote': (curses.COLOR_GREEN, None, curses.A_BOLD),
|
'UserFlair': (curses.COLOR_YELLOW, None, curses.A_BOLD)
|
||||||
'url': (curses.COLOR_BLUE, None, curses.A_UNDERLINE),
|
|
||||||
'url_seen': (curses.COLOR_MAGENTA, None, curses.A_UNDERLINE),
|
|
||||||
'user_flair': (curses.COLOR_YELLOW, None, curses.A_BOLD)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BAR_LEVELS = ['bar_level_1', 'bar_level_2', 'bar_level_3', 'bar_level_4']
|
# List of elements that might be highlighted by the "Selected" row
|
||||||
|
SELECTED_ELEMENTS = [
|
||||||
|
'CommentAuthor',
|
||||||
|
'CommentAuthorSelf',
|
||||||
|
'CommentCount',
|
||||||
|
'CommentText',
|
||||||
|
'Created',
|
||||||
|
'Downvote',
|
||||||
|
'Gold',
|
||||||
|
'HiddenCommentExpand',
|
||||||
|
'HiddenCommentText',
|
||||||
|
'MultiredditName',
|
||||||
|
'MultiredditText',
|
||||||
|
'NeutralVote',
|
||||||
|
'NSFW',
|
||||||
|
'Saved',
|
||||||
|
'Score',
|
||||||
|
'Separator',
|
||||||
|
'Stickied',
|
||||||
|
'SubscriptionName',
|
||||||
|
'SubscriptionText',
|
||||||
|
'SubmissionAuthor',
|
||||||
|
'SubmissionFlair',
|
||||||
|
'SubmissionSubreddit',
|
||||||
|
'SubmissionText',
|
||||||
|
'SubmissionTitle',
|
||||||
|
'Upvote',
|
||||||
|
'Link',
|
||||||
|
'LinkSeen',
|
||||||
|
'UserFlair'
|
||||||
|
]
|
||||||
|
|
||||||
|
# List of elements that might be highlighted by the "SelectedCursor" row
|
||||||
|
SELECTED_CURSOR_ELEMENTS = [
|
||||||
|
'CursorBlock',
|
||||||
|
'CursorBar1',
|
||||||
|
'CursorBar2',
|
||||||
|
'CursorBar3',
|
||||||
|
'CursorBar4'
|
||||||
|
]
|
||||||
|
|
||||||
|
# List of page elements that cannot be selected
|
||||||
|
PAGE_ELEMENTS = [
|
||||||
|
'PageOrder',
|
||||||
|
'PageOrderHighlight',
|
||||||
|
'PageTitle',
|
||||||
|
'Help',
|
||||||
|
'Prompt',
|
||||||
|
'NoticeInfo',
|
||||||
|
'NoticeLoading',
|
||||||
|
'NoticeError',
|
||||||
|
'NoticeSuccess',
|
||||||
|
]
|
||||||
|
|
||||||
|
# The SubmissionPage uses this to determine which color bar to use
|
||||||
|
CURSOR_BARS = ['CursorBar1', 'CursorBar2', 'CursorBar3', 'CursorBar4']
|
||||||
|
|
||||||
def __init__(self, name=None, source=None, elements=None, use_color=True):
|
def __init__(self, name=None, source=None, elements=None, use_color=True):
|
||||||
"""
|
"""
|
||||||
@@ -131,9 +185,10 @@ class Theme(object):
|
|||||||
self.name = name
|
self.name = name
|
||||||
self.source = source
|
self.source = source
|
||||||
self.use_color = use_color
|
self.use_color = use_color
|
||||||
|
|
||||||
self._color_pair_map = None
|
self._color_pair_map = None
|
||||||
self._attribute_map = None
|
self._attribute_map = None
|
||||||
self._modifier = None
|
self._selected = None
|
||||||
|
|
||||||
self.required_color_pairs = 0
|
self.required_color_pairs = 0
|
||||||
self.required_colors = 0
|
self.required_colors = 0
|
||||||
@@ -141,45 +196,32 @@ class Theme(object):
|
|||||||
if elements is None:
|
if elements is None:
|
||||||
elements = self.DEFAULT_THEME.copy()
|
elements = self.DEFAULT_THEME.copy()
|
||||||
|
|
||||||
# Fill in any keywords that are defined in the default theme but were
|
# Set any elements that weren't defined by the config to fallback to
|
||||||
# not passed into the elements dictionary.
|
# the default color and attributes
|
||||||
for key in self.DEFAULT_THEME.keys():
|
for key in self.DEFAULT_THEME.keys():
|
||||||
|
|
||||||
# The "@normal"/"@highlight" are special elements that act as
|
|
||||||
# fallbacks for all of the other elements. They must always be
|
|
||||||
# defined and can't have the colors/attribute empty by setting
|
|
||||||
# them to "-" or None.
|
|
||||||
if key.startswith('@'):
|
|
||||||
if key not in elements:
|
|
||||||
elements[key] = self.DEFAULT_THEME[key]
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Modifiers are handled below
|
|
||||||
if key.endswith('.highlight'):
|
|
||||||
continue
|
|
||||||
|
|
||||||
# Set undefined elements to fallback to the default color
|
|
||||||
if key not in elements:
|
if key not in elements:
|
||||||
elements[key] = (None, None, None)
|
elements[key] = (None, None, None)
|
||||||
|
|
||||||
# Set undefined highlight elements to match their base element
|
self._set_fallback(elements, 'Normal', (-1, -1, curses.A_NORMAL))
|
||||||
modifier_key = key + '.highlight'
|
self._set_fallback(elements, 'Selected', 'Normal')
|
||||||
if modifier_key not in elements:
|
self._set_fallback(elements, 'SelectedCursor', 'Normal')
|
||||||
elements[modifier_key] = elements[key]
|
|
||||||
|
|
||||||
# At this point all of the possible keys should exist in the element map.
|
# Most elements have two possible attribute states:
|
||||||
# Now we can "bubble up" the undefined attributes to copy the default
|
# 1. The default state - inherits from "Normal"
|
||||||
# of the @normal and @highlight modifiers.
|
# 2. The selected state - inherits from "Selected" and is
|
||||||
for key, val in elements.items():
|
# prefixed by the "@" sign.
|
||||||
if key.endswith('.highlight'):
|
for name in self.SELECTED_ELEMENTS:
|
||||||
default = elements['@highlight']
|
dest = '@{0}'.format(name)
|
||||||
else:
|
self._set_fallback(elements, name, 'Selected', dest)
|
||||||
default = elements['@normal']
|
self._set_fallback(elements, name, 'Normal')
|
||||||
|
|
||||||
elements[key] = (
|
for name in self.SELECTED_CURSOR_ELEMENTS:
|
||||||
default[0] if val[0] is None else val[0],
|
dest = '@{0}'.format(name)
|
||||||
default[1] if val[1] is None else val[1],
|
self._set_fallback(elements, name, 'SelectedCursor', dest)
|
||||||
default[2] if val[2] is None else val[2])
|
self._set_fallback(elements, name, 'Normal')
|
||||||
|
|
||||||
|
for name in self.PAGE_ELEMENTS:
|
||||||
|
self._set_fallback(elements, name, 'Normal')
|
||||||
|
|
||||||
self.elements = elements
|
self.elements = elements
|
||||||
|
|
||||||
@@ -238,47 +280,43 @@ class Theme(object):
|
|||||||
|
|
||||||
self._attribute_map[element] = attrs
|
self._attribute_map[element] = attrs
|
||||||
|
|
||||||
def get(self, element, modifier=None):
|
def get(self, element, selected=False):
|
||||||
"""
|
"""
|
||||||
Returns the curses attribute code for the given element.
|
Returns the curses attribute code for the given element.
|
||||||
|
|
||||||
If element is None, return the background code (e.g. @normal).
|
|
||||||
"""
|
"""
|
||||||
if self._attribute_map is None:
|
if self._attribute_map is None:
|
||||||
raise RuntimeError('Attempted to access theme attribute before '
|
raise RuntimeError('Attempted to access theme attribute before '
|
||||||
'calling initialize_curses_theme()')
|
'calling initialize_curses_theme()')
|
||||||
|
|
||||||
modifier = modifier or self._modifier
|
if selected or self._selected:
|
||||||
|
element = '@{0}'.format(element)
|
||||||
if modifier and not element.startswith('@'):
|
|
||||||
element = element + '.' + modifier
|
|
||||||
|
|
||||||
return self._attribute_map[element]
|
return self._attribute_map[element]
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def set_modifier(self, modifier=None):
|
def turn_on_selected(self):
|
||||||
"""
|
"""
|
||||||
Sets the active modifier inside of context block.
|
Sets the selected modifier inside of context block.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
>>> with theme.set_modifier('highlight'):
|
>>> with theme.turn_on_selected():
|
||||||
>>> attr = theme.get('cursor')
|
>>> attr = theme.get('CursorBlock')
|
||||||
|
|
||||||
Is the same as:
|
Is the same as:
|
||||||
>>> attr = theme.get('cursor', modifier='highlight')
|
>>> attr = theme.get('CursorBlock', selected=True)
|
||||||
|
|
||||||
Is also the same as:
|
Is also the same as:
|
||||||
>>> attr = theme.get('cursor.highlight')
|
>>> attr = theme.get('@CursorBlock')
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# This case is undefined if the context manager is nested
|
# This context manager should never be nested
|
||||||
assert self._modifier is None
|
assert self._selected is None
|
||||||
|
|
||||||
self._modifier = modifier
|
self._selected = True
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
self._modifier = None
|
self._selected = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def list_themes(cls, path=THEMES):
|
def list_themes(cls, path=THEMES):
|
||||||
@@ -378,9 +416,11 @@ class Theme(object):
|
|||||||
filename: The name of the filename to load.
|
filename: The name of the filename to load.
|
||||||
source: A description of where the theme was loaded from.
|
source: A description of where the theme was loaded from.
|
||||||
"""
|
"""
|
||||||
|
_logger.info('Loading theme %s', filename)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
|
config.optionxform = six.text_type # Preserve case
|
||||||
with codecs.open(filename, encoding='utf-8') as fp:
|
with codecs.open(filename, encoding='utf-8') as fp:
|
||||||
config.readfp(fp)
|
config.readfp(fp)
|
||||||
except configparser.ParsingError as e:
|
except configparser.ParsingError as e:
|
||||||
@@ -399,6 +439,7 @@ class Theme(object):
|
|||||||
if element not in cls.DEFAULT_THEME:
|
if element not in cls.DEFAULT_THEME:
|
||||||
# Could happen if using a new config with an older version
|
# Could happen if using a new config with an older version
|
||||||
# of the software
|
# of the software
|
||||||
|
_logger.info('Skipping element %s', element)
|
||||||
continue
|
continue
|
||||||
elements[element] = cls._parse_line(element, line, filename)
|
elements[element] = cls._parse_line(element, line, filename)
|
||||||
|
|
||||||
@@ -453,13 +494,26 @@ class Theme(object):
|
|||||||
else:
|
else:
|
||||||
attrs_code |= attr_code
|
attrs_code |= attr_code
|
||||||
|
|
||||||
if element.startswith('@') and None in (fg_code, bg_code, attrs_code):
|
|
||||||
raise ConfigError(
|
|
||||||
'Error loading {0}, {1} cannot have unspecified attributes:\n'
|
|
||||||
' {1} = {2}'.format(filename, element, line))
|
|
||||||
|
|
||||||
return fg_code, bg_code, attrs_code
|
return fg_code, bg_code, attrs_code
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _set_fallback(elements, src_field, fallback, dest_field=None):
|
||||||
|
"""
|
||||||
|
Helper function used to set the fallback attributes of an element when
|
||||||
|
they are defined by the configuration as "None" or "-".
|
||||||
|
"""
|
||||||
|
|
||||||
|
if dest_field is None:
|
||||||
|
dest_field = src_field
|
||||||
|
if isinstance(fallback, six.string_types):
|
||||||
|
fallback = elements[fallback]
|
||||||
|
|
||||||
|
attrs = elements[src_field]
|
||||||
|
elements[dest_field] = (
|
||||||
|
attrs[0] if attrs[0] is not None else fallback[0],
|
||||||
|
attrs[1] if attrs[1] is not None else fallback[1],
|
||||||
|
attrs[2] if attrs[2] is not None else fallback[2])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def rgb_to_ansi(color):
|
def rgb_to_ansi(color):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
[theme]
|
|
||||||
;<element> = <foreground> <background> <attributes>
|
|
||||||
@normal = default default normal
|
|
||||||
@highlight = default default normal
|
|
||||||
|
|
||||||
bar_level_1 = magenta - -
|
|
||||||
bar_level_1.highlight = magenta - reverse
|
|
||||||
bar_level_2 = cyan - -
|
|
||||||
bar_level_2.highlight = cyan - reverse
|
|
||||||
bar_level_3 = green - -
|
|
||||||
bar_level_3.highlight = green - reverse
|
|
||||||
bar_level_4 = yellow - -
|
|
||||||
bar_level_4.highlight = yellow - reverse
|
|
||||||
comment_author = blue - bold
|
|
||||||
comment_author_self = green - bold
|
|
||||||
comment_count = - - -
|
|
||||||
comment_text = - - -
|
|
||||||
created = - - -
|
|
||||||
cursor = - - -
|
|
||||||
cursor.highlight = - - reverse
|
|
||||||
downvote = red - bold
|
|
||||||
gold = yellow - bold
|
|
||||||
help_bar = cyan - bold+reverse
|
|
||||||
hidden_comment_expand = - - bold
|
|
||||||
hidden_comment_text = - - -
|
|
||||||
multireddit_name = yellow - bold
|
|
||||||
multireddit_text = - - -
|
|
||||||
neutral_vote = - - bold
|
|
||||||
notice_info = - - bold
|
|
||||||
notice_loading = - - bold
|
|
||||||
notice_error = red - bold
|
|
||||||
notice_success = green - bold
|
|
||||||
nsfw = red - bold+reverse
|
|
||||||
order_bar = yellow - bold
|
|
||||||
order_bar.highlight = yellow - bold+reverse
|
|
||||||
prompt = cyan - bold+reverse
|
|
||||||
saved = green - -
|
|
||||||
score = - - -
|
|
||||||
separator = - - bold
|
|
||||||
stickied = green - -
|
|
||||||
subscription_name = yellow - bold
|
|
||||||
subscription_text = - - -
|
|
||||||
submission_author = green - bold
|
|
||||||
submission_flair = red - -
|
|
||||||
submission_subreddit = yellow - -
|
|
||||||
submission_text = - - -
|
|
||||||
submission_title = - - bold
|
|
||||||
title_bar = cyan - bold+reverse
|
|
||||||
upvote = green - bold
|
|
||||||
url = blue - underline
|
|
||||||
url_seen = magenta - underline
|
|
||||||
user_flair = yellow - bold
|
|
||||||
53
rtv/themes/default.cfg.example
Normal file
53
rtv/themes/default.cfg.example
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
# http://www.calmar.ws/vim/256-xterm-24bit-rgb-color-chart.html
|
||||||
|
# https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg
|
||||||
|
|
||||||
|
[theme]
|
||||||
|
;<element> = <foreground> <background> <attributes>
|
||||||
|
Normal = default default -
|
||||||
|
Selected = - - -
|
||||||
|
SelectedCursor = - - reverse
|
||||||
|
|
||||||
|
PageTitle = cyan - bold+reverse
|
||||||
|
PageOrder = yellow - bold
|
||||||
|
PageOrderHighlight = yellow - bold+reverse
|
||||||
|
Help = 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 = blue - 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 = blue - underline
|
||||||
|
LinkSeen = magenta - underline
|
||||||
|
UserFlair = yellow - bold
|
||||||
@@ -19,53 +19,51 @@
|
|||||||
|
|
||||||
[theme]
|
[theme]
|
||||||
;<element> = <foreground> <background> <attributes>
|
;<element> = <foreground> <background> <attributes>
|
||||||
@normal = ansi_244 ansi_234 normal
|
Normal = ansi_244 ansi_234 -
|
||||||
@highlight = ansi_244 ansi_235 normal
|
Selected = ansi_244 ansi_235 -
|
||||||
|
SelectedCursor = ansi_244 ansi_235 bold+reverse
|
||||||
|
|
||||||
bar_level_1 = ansi_125 -
|
PageTitle = ansi_37 - bold+reverse
|
||||||
bar_level_1.highlight = ansi_125 - reverse
|
PageOrder = ansi_240 - bold
|
||||||
bar_level_2 = ansi_160 -
|
PageOrderHighlight = ansi_240 - bold+reverse
|
||||||
bar_level_2.highlight = ansi_125 - reverse
|
Help = ansi_37 - bold+reverse
|
||||||
bar_level_3 = ansi_61 -
|
Prompt = ansi_33 - bold+reverse
|
||||||
bar_level_3.highlight = ansi_125 - reverse
|
NoticeInfo = - - bold
|
||||||
bar_level_4 = ansi_37 -
|
NoticeLoading = - - bold
|
||||||
bar_level_4.highlight = ansi_125 - reverse
|
NoticeError = ansi_160 - bold
|
||||||
comment_author = ansi_33 - bold
|
NoticeSuccess = ansi_64 - bold
|
||||||
comment_author_self = ansi_64 - bold
|
|
||||||
comment_count = - -
|
CursorBlock = ansi_240 - -
|
||||||
comment_text = - -
|
CursorBar1 = ansi_125 - bold
|
||||||
created = - -
|
CursorBar2 = ansi_160 - bold
|
||||||
cursor = - -
|
CursorBar3 = ansi_61 - bold
|
||||||
cursor.highlight = ansi_240 - reverse
|
CursorBar4 = ansi_37 - bold
|
||||||
downvote = ansi_160 - bold
|
|
||||||
gold = ansi_136 - bold
|
CommentAuthor = ansi_33 - bold
|
||||||
help_bar = ansi_37 - bold+reverse
|
CommentAuthorSelf = ansi_64 - bold
|
||||||
hidden_comment_expand = ansi_245 - bold
|
CommentCount = - - -
|
||||||
hidden_comment_text = ansi_245 -
|
CommentText = - - -
|
||||||
multireddit_name = ansi_240 - bold
|
Created = - - -
|
||||||
multireddit_text = ansi_245 -
|
Downvote = ansi_160 - bold
|
||||||
neutral_vote = - - bold
|
Gold = ansi_136 - bold
|
||||||
notice_info = - - bold
|
HiddenCommentExpand = ansi_245 - bold
|
||||||
notice_loading = - - bold
|
HiddenCommentText = ansi_245 - -
|
||||||
notice_error = ansi_160 - bold
|
MultiredditName = ansi_240 - bold
|
||||||
notice_success = ansi_64 - bold
|
MultiredditText = ansi_245 - -
|
||||||
nsfw = ansi_125 - bold+reverse
|
NeutralVote = - - bold
|
||||||
order_bar = ansi_245 - bold
|
NSFW = ansi_125 - bold+reverse
|
||||||
order_bar.highlight = ansi_245 - bold+reverse
|
Saved = ansi_125 - -
|
||||||
prompt = ansi_33 - bold+reverse
|
Score = - - -
|
||||||
saved = ansi_125 -
|
Separator = - - bold
|
||||||
score = - -
|
Stickied = ansi_136 - -
|
||||||
separator = - - bold
|
SubscriptionName = ansi_240 - bold
|
||||||
stickied = ansi_136 -
|
SubscriptionText = ansi_245 - -
|
||||||
subscription_name = ansi_240 - bold
|
SubmissionAuthor = ansi_64 - bold
|
||||||
subscription_text = ansi_245 -
|
SubmissionFlair = ansi_160 - -
|
||||||
submission_author = ansi_64 - bold
|
SubmissionSubreddit = ansi_166 - -
|
||||||
submission_flair = ansi_160 -
|
SubmissionText = - - -
|
||||||
submission_subreddit = ansi_166 -
|
SubmissionTitle = ansi_245 - bold
|
||||||
submission_text = - -
|
Upvote = ansi_64 - bold
|
||||||
submission_title = ansi_244 - bold
|
Link = ansi_33 - underline
|
||||||
title_bar = ansi_37 - bold+reverse
|
LinkSeen = ansi_61 - underline
|
||||||
upvote = ansi_64 - bold
|
UserFlair = ansi_136 - bold
|
||||||
url = ansi_33 - underline
|
|
||||||
url_seen = ansi_61 - underline
|
|
||||||
user_flair = ansi_136 - bold
|
|
||||||
@@ -19,53 +19,51 @@
|
|||||||
|
|
||||||
[theme]
|
[theme]
|
||||||
;<element> = <foreground> <background> <attributes>
|
;<element> = <foreground> <background> <attributes>
|
||||||
@normal = ansi_241 ansi_230 normal
|
Normal = ansi_241 ansi_230 -
|
||||||
@highlight = ansi_241 ansi_254 normal
|
Selected = ansi_241 ansi_254 -
|
||||||
|
SelectedCursor = ansi_241 ansi_254 reverse
|
||||||
|
|
||||||
bar_level_1 = ansi_125 -
|
PageTitle = ansi_37 - bold+reverse
|
||||||
bar_level_1.highlight = ansi_125 - reverse
|
PageOrder = ansi_245 - bold
|
||||||
bar_level_2 = ansi_160 -
|
PageOrderHighlight = ansi_245 - bold+reverse
|
||||||
bar_level_2.highlight = ansi_125 - reverse
|
Help = ansi_37 - bold+reverse
|
||||||
bar_level_3 = ansi_61 -
|
Prompt = ansi_33 - bold+reverse
|
||||||
bar_level_3.highlight = ansi_125 - reverse
|
NoticeInfo = - - bold
|
||||||
bar_level_4 = ansi_37 -
|
NoticeLoading = - - bold
|
||||||
bar_level_4.highlight = ansi_125 - reverse
|
NoticeError = ansi_160 - bold
|
||||||
comment_author = ansi_33 - bold
|
NoticeSuccess = ansi_64 - bold
|
||||||
comment_author_self = ansi_64 - bold
|
|
||||||
comment_count = - -
|
CursorBlock = ansi_245 - -
|
||||||
comment_text = - -
|
CursorBar1 = ansi_125 - -
|
||||||
created = - -
|
CursorBar2 = ansi_160 - -
|
||||||
cursor = - -
|
CursorBar3 = ansi_61 - -
|
||||||
cursor.highlight = ansi_245 - reverse
|
CursorBar4 = ansi_37 - -
|
||||||
downvote = ansi_160 - bold
|
|
||||||
gold = ansi_136 - bold
|
CommentAuthor = ansi_33 - bold
|
||||||
help_bar = ansi_37 - bold+reverse
|
CommentAuthorSelf = ansi_64 - bold
|
||||||
hidden_comment_expand = ansi_245 - bold
|
CommentCount = - - -
|
||||||
hidden_comment_text = ansi_245 -
|
CommentText = - - -
|
||||||
multireddit_name = ansi_240 - bold
|
Created = - - -
|
||||||
multireddit_text = ansi_245 -
|
Downvote = ansi_160 - bold
|
||||||
neutral_vote = - - bold
|
Gold = ansi_136 - bold
|
||||||
notice_info = - - bold
|
HiddenCommentExpand = ansi_245 - bold
|
||||||
notice_loading = - - bold
|
HiddenCommentText = ansi_245 - -
|
||||||
notice_error = ansi_160 - bold
|
MultiredditName = ansi_240 - bold
|
||||||
notice_success = ansi_64 - bold
|
MultiredditText = ansi_245 - -
|
||||||
nsfw = ansi_125 - bold+reverse
|
NeutralVote = - - bold
|
||||||
order_bar = ansi_245 - bold
|
NSFW = ansi_125 - bold+reverse
|
||||||
order_bar.highlight = ansi_245 - bold+reverse
|
Saved = ansi_125 - -
|
||||||
prompt = ansi_33 - bold+reverse
|
Score = - - -
|
||||||
saved = ansi_125 -
|
Separator = - - bold
|
||||||
score = - -
|
Stickied = ansi_136 - -
|
||||||
separator = - - bold
|
SubscriptionName = ansi_240 - bold
|
||||||
stickied = ansi_136 -
|
SubscriptionText = ansi_245 - -
|
||||||
subscription_name = ansi_240 - bold
|
SubmissionAuthor = ansi_64 - bold
|
||||||
subscription_text = ansi_245 -
|
SubmissionFlair = ansi_160 - -
|
||||||
submission_author = ansi_64 - bold
|
SubmissionSubreddit = ansi_166 - -
|
||||||
submission_flair = ansi_160 -
|
SubmissionText = - - -
|
||||||
submission_subreddit = ansi_166 -
|
SubmissionTitle = ansi_240 - bold
|
||||||
submission_text = - -
|
Upvote = ansi_64 - bold
|
||||||
submission_title = ansi_240 - bold
|
Link = ansi_33 - underline
|
||||||
title_bar = ansi_37 - bold+reverse
|
LinkSeen = ansi_61 - underline
|
||||||
upvote = ansi_64 - bold
|
UserFlair = ansi_136 - bold
|
||||||
url = ansi_33 - underline
|
|
||||||
url_seen = ansi_61 - underline
|
|
||||||
user_flair = ansi_136 - bold
|
|
||||||
Reference in New Issue
Block a user