Refactored page initialization, content initialization, and loading.

This commit is contained in:
Michael Lazar
2015-02-01 02:02:22 -08:00
parent 66dd4c5bd4
commit b8794e3599
6 changed files with 91 additions and 80 deletions

View File

@@ -135,7 +135,7 @@ class SubmissionContent(BaseContent):
def __init__(
self,
submission,
loader=default_loader(),
loader=default_loader,
indent_size=2,
max_indent_level=4):
@@ -143,26 +143,35 @@ class SubmissionContent(BaseContent):
self.max_indent_level = max_indent_level
self._loader = loader
self._submissin = submission
self._submission_data = self.strip_praw_submission(submission)
self.name = self._submission_data['permalink']
with loader:
with self._loader():
comments = self.flatten_comments(submission.comments)
self._comment_data = [self.strip_praw_comment(c) for c in comments]
@classmethod
def from_url(
cls,
r,
reddit,
url,
loader=default_loader(),
loader=default_loader,
indent_size=2,
max_indent_level=4):
with loader:
submission = r.get_submission(url)
with loader():
submission = reddit.get_submission(url)
return cls(submission, loader, indent_size, max_indent_level)
def reset(self):
self._submissin.refresh()
self._submission_data = self.strip_praw_submission(submission)
self.name = self._submission_data['permalink']
comments = self.flatten_comments(submission.comments)
self._comment_data = [self.strip_praw_comment(c) for c in comments]
def get(self, index, n_cols=70):
"""
Grab the `i`th submission, with the title field formatted to fit inside
@@ -227,7 +236,7 @@ class SubmissionContent(BaseContent):
elif data['type'] == 'MoreComments':
with self._loader:
with self._loader():
comments = data['object'].comments()
comments = self.flatten_comments(comments, root_level=data['level'])
comment_data = [self.strip_praw_comment(c) for c in comments]
@@ -249,23 +258,24 @@ class SubredditContent(BaseContent):
list for repeat access.
"""
def __init__(self, name, submission_generator, loader=default_loader()):
def __init__(self, name, submissions, loader=default_loader):
self.name = name
self._loader = loader
self._submissions = submission_generator
self._submissions = submissions
self._submission_data = []
@classmethod
def from_name(cls, r, name, loader=default_loader()):
def from_name(cls, reddit, name, loader=default_loader):
if name == 'front':
return cls('Front Page', r.get_front_page(limit=None), loader)
return cls('Front Page', reddit.get_front_page(limit=None), loader)
if name == 'all':
sub = r.get_subreddit(name)
sub = reddit.get_subreddit(name)
else:
sub = r.get_subreddit(name, fetch=True)
with loader():
sub = reddit.get_subreddit(name, fetch=True)
return cls('/r/'+sub.display_name, sub.get_hot(limit=None), loader)
@@ -281,7 +291,7 @@ class SubredditContent(BaseContent):
while index >= len(self._submission_data):
try:
with self._loader:
with self._loader():
submission = self._submissions.next()
except StopIteration:
raise IndexError

View File

@@ -1,7 +1,7 @@
import argparse
import praw
from utils import curses_session, LoadScreen
from content import SubredditContent
from utils import curses_session
from subreddit import SubredditPage
parser = argparse.ArgumentParser(description='Reddit Terminal Viewer')
@@ -13,17 +13,15 @@ group.add_argument('-p', dest='password', help='reddit password')
def main(args):
r = praw.Reddit(user_agent='reddit terminal viewer v0.0')
r.config.decode_html_entities = True
reddit = praw.Reddit(user_agent='reddit terminal viewer v0.0')
reddit.config.decode_html_entities = True
if args.username and args.password:
r.login(args.username, args.password)
reddit.login(args.username, args.password)
with curses_session() as stdscr:
loader = LoadScreen(stdscr)
content = SubredditContent(r, subreddit=args.subreddit, loader=loader)
page = SubredditPage(stdscr, content)
page = SubredditPage(stdscr, reddit, args.subreddit)
page.loop()
if __name__ == '__main__':

View File

@@ -79,14 +79,12 @@ class BasePage(object):
self.stdscr = stdscr
self.content = content
self.nav = Navigator(self.content.get, **kwargs)
self._header_window = None
self._content_window = None
self._subwindows = None
def draw(self):
raise NotImplementedError
def move_cursor_up(self):
self._move_cursor(-1)
@@ -106,12 +104,22 @@ class BasePage(object):
continue
self.stdscr.nodelay(0)
def draw(self):
n_rows, n_cols = self.stdscr.getmaxyx()
self._header_window = self.stdscr.derwin(1, n_cols, 0, 0)
self._content_window = self.stdscr.derwin(1, 0)
self.draw_header()
self.draw_content()
self.add_cursor()
def draw_header(self):
n_rows, n_cols = self._header_window.getmaxyx()
self._header_window.erase()
self._header_window.addnstr(0, 0, self.content.display_name, n_cols-1)
self._header_window.addnstr(0, 0, self.content.name, n_cols-1)
def draw_content(self):
"""

View File

@@ -1,18 +1,25 @@
import praw
import curses
import sys
from content import SubmissionContent
from page import BasePage
from utils import curses_session
from utils import LoadScreen
class SubmissionPage(BasePage):
def __init__(self, stdscr, content):
def __init__(self, stdscr, reddit, url=None, submission=None):
self.loader = LoadScreen(stdscr)
if url is not None:
content = SubmissionContent.from_url(reddit, url, self.loader)
elif submission is not None:
content = SubmissionContent(submission, self.loader)
else:
raise ValueError('Must specify url or submission')
page_index, cursor_index = -1, 1
super(SubmissionPage, self).__init__(
stdscr, content,
page_index=page_index, cursor_index=cursor_index)
stdscr, content, page_index=-1, cursor_index=1)
def loop(self):
@@ -61,16 +68,6 @@ class SubmissionPage(BasePage):
self.stdscr.clear()
self.draw()
def draw(self):
n_rows, n_cols = self.stdscr.getmaxyx()
self._header_window = self.stdscr.derwin(1, n_cols, 0, 0)
self._content_window = self.stdscr.derwin(1, 0)
self.draw_header()
self.draw_content()
self.add_cursor()
def draw_item(self, win, data, inverted=False):
if data['type'] == 'MoreComments':

View File

@@ -1,15 +1,22 @@
import praw
import textwrap
import curses
import sys
from page import BasePage
from submission import SubmissionPage
from content import SubmissionContent
from utils import curses_session, text_input
from content import SubredditContent
from utils import LoadScreen, text_input
class SubredditPage(BasePage):
def __init__(self, stdscr, reddit, name):
self.reddit = reddit
self.name = name
self.loader = LoadScreen(stdscr)
content = SubredditContent.from_name(reddit, name, self.loader)
super(SubredditPage, self).__init__(stdscr, content)
def loop(self):
self.draw()
@@ -47,11 +54,12 @@ class SubredditPage(BasePage):
else:
curses.beep()
def refresh_content(self, subreddit=None):
def refresh_content(self, name=None):
self.nav.page_index, self.nav.cursor_index = 0, 0
self.nav.inverted = False
self.content.reset(subreddit=subreddit)
self.name = name if name else self.name
self.content = SubredditContent.from_name(self.reddit, self.name, self.loader)
self.stdscr.clear()
self.draw()
@@ -67,26 +75,15 @@ class SubredditPage(BasePage):
if out is None:
self.draw()
else:
self.refresh_content(subreddit=out)
self.refresh_content(name=out)
def open_submission(self):
"Select the current submission to view posts"
submission = self.content.get(self.nav.absolute_index)['object']
content = SubmissionContent(submission, loader=self.content.loader)
page = SubmissionPage(self.stdscr, content)
page = SubmissionPage(self.stdscr, self.reddit, submission=submission)
page.loop()
def draw(self):
n_rows, n_cols = self.stdscr.getmaxyx()
self._header_window = self.stdscr.derwin(1, n_cols, 0, 0)
self._content_window = self.stdscr.derwin(1, 0)
self.draw_header()
self.draw_content()
self.add_cursor()
@staticmethod
def draw_item(win, data, inverted=False):

View File

@@ -42,26 +42,27 @@ def text_input(window):
class LoadScreen(object):
def __init__(
self,
stdscr,
message='Downloading',
trail='...',
delay=0.5,
interval=0.4):
def __init__(self, stdscr):
self._stdscr = stdscr
self.message = message
self.delay = delay
self.interval=interval
self.trail = trail
self._args = None
self._animator = None
self._is_running = None
def __call__(
self,
delay=0.5,
interval=0.4,
message='Downloading',
trail='...'):
self._args = (delay, interval, message, trail)
return self
def __enter__(self):
self._animator = threading.Thread(target=self.animate)
self._animator = threading.Thread(target=self.animate, args=self._args)
self._animator.daemon = True
self._is_running = True
@@ -72,23 +73,23 @@ class LoadScreen(object):
self._is_running = False
self._animator.join()
def animate(self):
def animate(self, delay, interval, message, trail):
# Delay before starting animation to avoid wasting resources if the
# wait time is very short
start = time.time()
while (time.time() - start) < self.delay:
while (time.time() - start) < delay:
if not self._is_running:
return
message_len = len(self.message) + len(self.trail)
message_len = len(message) + len(trail)
n_rows, n_cols = self._stdscr.getmaxyx()
s_row = (n_rows - 2) / 2
s_col = (n_cols - message_len - 1) / 2
window = self._stdscr.derwin(3, message_len+2, s_row, s_col)
while True:
for i in xrange(len(self.trail)+1):
for i in xrange(len(trail)+1):
if not self._is_running:
# TODO: figure out why this isn't removing the screen
@@ -98,9 +99,9 @@ class LoadScreen(object):
window.erase()
window.border()
window.addstr(1, 1, self.message + self.trail[:i])
window.addstr(1, 1, message + trail[:i])
window.refresh()
time.sleep(self.interval)
time.sleep(interval)
@contextmanager