Merge pull request #287 from michael-lazar/help_footer

Help footer
This commit is contained in:
Michael Lazar
2016-08-15 21:48:21 -07:00
committed by GitHub
8 changed files with 100 additions and 54 deletions

View File

@@ -16,47 +16,49 @@ Move the cursor using either the arrow keys or *Vim* style movement.
Press `?` to open the help screen.
"""
HELP = """
HELP = """\
====================================
Reddit Terminal Viewer
https://github.com/michael-lazar/rtv
====================================
[Basic Commands]
j/k or ▲/▼ : Move the cursor up/down
m/n or PgUp/PgDn : Jump to the previous/next page
gg/G : Jump to the top/bottom of the page
1-5 : Toggle post order
r or F5 : Refresh page content
u : Log in or switch accounts
/ : Open a prompt to switch subreddits
? : Show the help screen
q/Q : Quit/Force quit
[Commands]
j : Move the cursor up
k : Move the cursor down
m : Move up one page
n : Move down one page
gg : Jump to the first post
G : Jump to the last post
1 : Sort by hot
2 : Sort by top
3 : Sort by rising
4 : Sort by new
5 : Sort by controversial
p : Return to the front page
r : Refresh page
u : Login or logout
/ : Open the subreddit prompt
f : Open the search prompt
? : Show the help screen
q : Quit
Q : Force quit
a : Upvote
z : Downvote
c : Compose a new submission/comment
e : Edit a submission/comment
d : Delete a submission/comment
i : Display new messages
s : Show subscribed subreddits
S : Show subscribed multireddits
w : Save a submission/comment
l : View comments, or open comment in pager
h : Return to subreddit
o : Open the submission or comment url
SPACE : Fold or expand the selected comment tree
b : Display urls with urlview
[Authenticated Commands]
a/z : Upvote/downvote
c : Compose a new post or comment
e : Edit an existing post or comment
d : Delete an existing post or comment
i : Display new messages prompt
s : View a list of subscribed subreddits
S : View a list of subscribed multireddits
w : Save a submission
[Subreddit Commands]
l or ► : Enter the selected submission
o or ENTER : Open the submission link with your web browser
f : Open a prompt to search the current subreddit
p : Return to the front page
[Submission Commands]
h or ◄ : Return to the subreddit
l or ► : Open the selected comment in a new window
o or ENTER : Open the comment permalink with your web browser
SPACE : Fold the selected comment, or load additional comments
b : Display URLs with urlview
[Navigating]
[Prompt]
The `/` prompt accepts subreddits in the following formats
- python
@@ -72,6 +74,22 @@ https://github.com/michael-lazar/rtv
- /domain/python.org (search by domain)
"""
BANNER = """
[1]hot [2]top [3]rising [4]new [5]controversial
"""
FOOTER_SUBREDDIT = """
[?]Help [q]Quit [l]Comments [/]Prompt [u]Login [o]Open [c]Post [a/z]Vote
"""
FOOTER_SUBMISSION = """
[?]Help [q]Quit [h]Return [space]Fold/Expand [o]Open [c]Comment [a/z]Vote
"""
FOOTER_SUBSCRIPTION = """
[?]Help [q]Quit [h]Return [l]Select
"""
COMMENT_FILE = """
# Please enter a comment. Lines starting with '#' will be ignored,
# and an empty message aborts the comment.

View File

@@ -34,6 +34,8 @@ class PageController(Controller):
class Page(object):
FOOTER = None
def __init__(self, reddit, term, config, oauth):
self.reddit = reddit
@@ -299,6 +301,7 @@ class Page(object):
self._draw_header()
self._draw_banner()
self._draw_content()
self._draw_footer()
self._add_cursor()
self.term.stdscr.touchwin()
self.term.stdscr.refresh()
@@ -306,6 +309,7 @@ class Page(object):
def _draw_header(self):
n_rows, n_cols = self.term.stdscr.getmaxyx()
# Note: 2 argument form of derwin breaks PDcurses on Windows 7!
window = self.term.stdscr.derwin(1, n_cols, self._row, 0)
window.erase()
@@ -351,7 +355,7 @@ class Page(object):
ch, attr = str(' '), curses.A_BOLD | Color.YELLOW
window.bkgd(ch, attr)
items = ['[1]hot', '[2]top', '[3]rising', '[4]new', '[5]controversial']
items = docs.BANNER.strip().split(' ')
distance = (n_cols - sum(len(t) for t in items) - 1) / (len(items) - 1)
spacing = max(1, int(distance)) * ' '
text = spacing.join(items)
@@ -370,7 +374,7 @@ class Page(object):
n_rows, n_cols = self.term.stdscr.getmaxyx()
window = self.term.stdscr.derwin(
n_rows - self._row, n_cols, self._row, 0)
n_rows - self._row - 1, n_cols, self._row, 0)
window.erase()
win_n_rows, win_n_cols = window.getmaxyx()
@@ -383,7 +387,7 @@ class Page(object):
# and draw upwards.
cancel_inverted = True
current_row = (win_n_rows - 1) if inverted else 0
available_rows = (win_n_rows - 1) if inverted else win_n_rows
available_rows = win_n_rows
top_item_height = None if inverted else self.nav.top_item_height
for data in self.content.iterate(page_index, step, win_n_cols - 2):
subwin_n_rows = min(available_rows, data['n_rows'])
@@ -396,7 +400,7 @@ class Page(object):
subwin_inverted = True
top_item_height = None
subwin_n_cols = win_n_cols - data['offset']
start = current_row - subwin_n_rows if inverted else current_row
start = current_row - subwin_n_rows + 1 if inverted else current_row
subwindow = window.derwin(
subwin_n_rows, subwin_n_cols, start, data['offset'])
attr = self._draw_item(subwindow, data, subwin_inverted)
@@ -420,9 +424,21 @@ class Page(object):
# if the content will fill up the page, given that it is dependent
# on the size of the terminal.
self.nav.flip((len(self._subwindows) - 1))
self._draw_content()
return self._draw_content()
self._row = n_rows
self._row += win_n_rows
def _draw_footer(self):
n_rows, n_cols = self.term.stdscr.getmaxyx()
window = self.term.stdscr.derwin(1, n_cols, self._row, 0)
window.erase()
ch, attr = str(' '), curses.A_REVERSE | curses.A_BOLD | Color.CYAN
window.bkgd(ch, attr)
text = self.FOOTER.strip()
self.term.add_line(window, text, 0, 0)
self._row += 1
def _add_cursor(self):
self._edit_cursor(curses.A_REVERSE)

View File

@@ -17,6 +17,8 @@ class SubmissionController(PageController):
class SubmissionPage(Page):
FOOTER = docs.FOOTER_SUBMISSION
def __init__(self, reddit, term, config, oauth, url=None, submission=None):
super(SubmissionPage, self).__init__(reddit, term, config, oauth)

View File

@@ -19,6 +19,8 @@ class SubredditController(PageController):
class SubredditPage(Page):
FOOTER = docs.FOOTER_SUBREDDIT
def __init__(self, reddit, term, config, oauth, name):
"""
Params:
@@ -265,7 +267,7 @@ class SubredditPage(Page):
row = n_title + offset + 2
if row in valid_rows:
text = '{author}'.format(**data)
self.term.add_line(win, text, row, 1, curses.A_BOLD)
self.term.add_line(win, text, row, 1, Color.GREEN)
text = ' /r/{subreddit}'.format(**data)
self.term.add_line(win, text, attr=Color.YELLOW)
if data['flair']:

View File

@@ -3,6 +3,7 @@ from __future__ import unicode_literals
import curses
from . import docs
from .page import Page, PageController
from .content import SubscriptionContent, SubredditContent
from .objects import Color, Navigator, Command
@@ -14,6 +15,8 @@ class SubscriptionController(PageController):
class SubscriptionPage(Page):
FOOTER = docs.FOOTER_SUBSCRIPTION
def __init__(self, reddit, term, config, oauth, content_type='subreddit'):
super(SubscriptionPage, self).__init__(reddit, term, config, oauth)

View File

@@ -664,18 +664,20 @@ class Terminal(object):
"""
n_rows, n_cols = self.stdscr.getmaxyx()
attr = curses.A_BOLD | Color.CYAN
ch, attr = str(' '), curses.A_BOLD | curses.A_REVERSE | Color.CYAN
prompt = self.clean(prompt, n_cols-1)
# Create a new window to draw the text at the bottom of the screen,
# so we can erase it when we're done.
prompt_win = curses.newwin(1, len(prompt)+1, n_rows-1, 0)
self.add_line(prompt_win, prompt, attr=attr)
prompt_win.bkgd(ch, attr)
self.add_line(prompt_win, prompt)
prompt_win.refresh()
# Create a separate window for text input
input_win = curses.newwin(1, n_cols-len(prompt), n_rows-1, len(prompt))
input_win.attrset(attr)
input_win.bkgd(ch, attr)
input_win.refresh()
if key:
curses.curs_set(1)

View File

@@ -51,6 +51,11 @@ def test_submission_page_construct(reddit, terminal, config, oauth):
'[5]controversial').encode('utf-8')
window.addstr.assert_any_call(0, 0, menu)
# Footer
text = ('[?]Help [q]Quit [h]Return [space]Fold/Expand [o]Open [c]Comment '
'[a/z]Vote'.encode('utf-8'))
window.addstr.assert_any_call(0, 0, text)
# Submission
submission_data = page.content.get(-1)
text = submission_data['title'].encode('utf-8')
@@ -181,7 +186,7 @@ def test_submission_comment_not_enough_space(submission_page, terminal):
text = '(Not enough space to display)'.encode('ascii')
window = terminal.stdscr.subwin
window.subwin.addstr.assert_any_call(7, 1, text)
window.subwin.addstr.assert_any_call(6, 1, text)
def test_submission_vote(submission_page, refresh_token):

View File

@@ -236,8 +236,7 @@ def test_prompt_input(terminal, stdscr, use_ascii):
window.getch.side_effect = [ord('h'), ord('i'), terminal.RETURN]
assert isinstance(terminal.prompt_input('hi'), six.text_type)
attr = Color.CYAN | curses.A_BOLD
stdscr.subwin.addstr.assert_called_with(0, 0, 'hi'.encode('ascii'), attr)
stdscr.subwin.addstr.assert_called_with(0, 0, 'hi'.encode('ascii'))
assert window.nlines == 1
assert window.ncols == 78
@@ -254,27 +253,26 @@ def test_prompt_input(terminal, stdscr, use_ascii):
def test_prompt_y_or_n(terminal, stdscr):
stdscr.getch.side_effect = [ord('y'), ord('N'), terminal.ESCAPE, ord('a')]
attr = Color.CYAN | curses.A_BOLD
text = 'hi'.encode('ascii')
# Press 'y'
assert terminal.prompt_y_or_n('hi')
stdscr.subwin.addstr.assert_called_with(0, 0, text, attr)
stdscr.subwin.addstr.assert_called_with(0, 0, text)
assert not curses.flash.called
# Press 'N'
assert not terminal.prompt_y_or_n('hi')
stdscr.subwin.addstr.assert_called_with(0, 0, text, attr)
stdscr.subwin.addstr.assert_called_with(0, 0, text)
assert not curses.flash.called
# Press Esc
assert not terminal.prompt_y_or_n('hi')
stdscr.subwin.addstr.assert_called_with(0, 0, text, attr)
stdscr.subwin.addstr.assert_called_with(0, 0, text)
assert not curses.flash.called
# Press an invalid key
assert not terminal.prompt_y_or_n('hi')
stdscr.subwin.addstr.assert_called_with(0, 0, text, attr)
stdscr.subwin.addstr.assert_called_with(0, 0, text)
assert curses.flash.called