Merge branch 'TheoPib-master'

This commit is contained in:
Michael Lazar
2015-08-12 10:13:25 -07:00
8 changed files with 166 additions and 9 deletions

View File

@@ -84,6 +84,7 @@ Once you are logged in your username will appear in the top-right corner of the
:``c``: Compose a new post or comment :``c``: Compose a new post or comment
:``e``: Edit an existing post or comment :``e``: Edit an existing post or comment
:``d``: Delete an existing post or comment :``d``: Delete an existing post or comment
:``s``: Open/close subscribed subreddits list
-------------- --------------
Subreddit Mode Subreddit Mode

View File

@@ -10,7 +10,7 @@ import praw.errors
from six.moves import configparser from six.moves import configparser
from . import config from . import config
from .exceptions import SubmissionError, SubredditError, ProgramError from .exceptions import SubmissionError, SubredditError, SubscriptionError, ProgramError
from .curses_helpers import curses_session from .curses_helpers import curses_session
from .submission import SubmissionPage from .submission import SubmissionPage
from .subreddit import SubredditPage from .subreddit import SubredditPage

View File

@@ -4,10 +4,10 @@ import praw
import requests import requests
import re import re
from .exceptions import SubmissionError, SubredditError, AccountError from .exceptions import SubmissionError, SubredditError, SubscriptionError, AccountError
from .helpers import humanize_timestamp, wrap_text, strip_subreddit_url from .helpers import humanize_timestamp, wrap_text, strip_subreddit_url
__all__ = ['SubredditContent', 'SubmissionContent'] __all__ = ['SubredditContent', 'SubmissionContent', 'SubscriptionContent']
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -149,6 +149,20 @@ class BaseContent(object):
return data return data
@staticmethod
def strip_praw_subscription(subscription):
"""
Parse through a subscription and return a dict with data ready to be
displayed through the terminal.
"""
data = {}
data['object'] = subscription
data['type'] = 'Subscription'
data['name'] = "/r/" + subscription.display_name
data['title'] = subscription.title
return data
class SubmissionContent(BaseContent): class SubmissionContent(BaseContent):
""" """
@@ -369,3 +383,49 @@ class SubredditContent(BaseContent):
data['offset'] = 0 data['offset'] = 0
return data return data
class SubscriptionContent(BaseContent):
def __init__(self, subscriptions, loader):
self.name = "Subscriptions"
self.order = None
self._loader = loader
self._subscriptions = subscriptions
self._subscription_data = []
@classmethod
def from_user(cls, reddit, loader):
try:
with loader():
subscriptions = reddit.get_my_subreddits(limit=None)
except praw.errors.APIException:
raise SubscriptionError()
return cls(subscriptions, loader)
def get(self, index, n_cols=70):
"""
Grab the `i`th subscription, with the title field formatted to fit inside
of a window of width `n_cols`
"""
if index < 0:
raise IndexError
while index >= len(self._subscription_data):
try:
with self._loader():
subscription = next(self._subscriptions)
except StopIteration:
raise IndexError
else:
data = self.strip_praw_subscription(subscription)
self._subscription_data.append(data)
data = self._subscription_data[index]
data['split_title'] = wrap_text(data['title'], width=n_cols)
data['n_rows'] = len(data['split_title']) + 1
data['offset'] = 0
return data

View File

@@ -24,7 +24,7 @@ ESCAPE = 27
def get_gold(): def get_gold():
""" """
Return the guilded symbol. Return the gilded symbol.
""" """
symbol = u'\u272A' if config.unicode else '*' symbol = u'\u272A' if config.unicode else '*'

View File

@@ -42,6 +42,7 @@ Authenticated Commands
`c` : Compose a new post or comment `c` : Compose a new post or comment
`e` : Edit an existing post or comment `e` : Edit an existing post or comment
`d` : Delete an existing post or comment `d` : Delete an existing post or comment
`s` : Open/close subscribed subreddits list
Subreddit Mode Subreddit Mode
`l` or `RIGHT` : Enter the selected submission `l` or `RIGHT` : Enter the selected submission

View File

@@ -24,6 +24,10 @@ class SubredditError(RTVError):
self.name = name self.name = name
class SubscriptionError(RTVError):
"Subscriptions could not be fetched"
class ProgramError(RTVError): class ProgramError(RTVError):
"Problem executing an external program" "Problem executing an external program"

View File

@@ -8,6 +8,7 @@ import requests
from .exceptions import SubredditError, AccountError from .exceptions import SubredditError, AccountError
from .page import BasePage, Navigator, BaseController from .page import BasePage, Navigator, BaseController
from .submission import SubmissionPage from .submission import SubmissionPage
from .subscriptions import SubscriptionPage
from .content import SubredditContent from .content import SubredditContent
from .helpers import open_browser, open_editor, strip_subreddit_url from .helpers import open_browser, open_editor, strip_subreddit_url
from .docs import SUBMISSION_FILE from .docs import SUBMISSION_FILE
@@ -164,6 +165,23 @@ class SubredditPage(BasePage):
page.loop() page.loop()
self.refresh_content() self.refresh_content()
@SubredditController.register('s')
def open_subscriptions(self):
"Open user subscriptions page"
if not self.reddit.is_logged_in():
show_notification(self.stdscr, ['Not logged in'])
return
# Open subscriptions page
page = SubscriptionPage(self.stdscr, self.reddit)
page.loop()
# When user has chosen a subreddit in the subscriptions list,
# refresh content with the selected subreddit
if page.selected_subreddit_data is not None:
self.refresh_content(name=page.selected_subreddit_data['name'])
@staticmethod @staticmethod
def draw_item(win, data, inverted=False): def draw_item(win, data, inverted=False):

73
rtv/subscriptions.py Normal file
View File

@@ -0,0 +1,73 @@
import curses
import sys
import time
import logging
from .content import SubscriptionContent
from .page import BasePage, Navigator, BaseController
from .curses_helpers import (Color, LoadScreen, add_line)
__all__ = ['SubscriptionController', 'SubscriptionPage']
_logger = logging.getLogger(__name__)
class SubscriptionController(BaseController):
character_map = {}
class SubscriptionPage(BasePage):
def __init__(self, stdscr, reddit):
self.controller = SubscriptionController(self)
self.loader = LoadScreen(stdscr)
self.selected_subreddit_data = None
content = SubscriptionContent.from_user(reddit, self.loader)
super(SubscriptionPage, self).__init__(stdscr, reddit, content)
def loop(self):
"Main control loop"
self.active = True
while self.active:
self.draw()
cmd = self.stdscr.getch()
self.controller.trigger(cmd)
@SubscriptionController.register(curses.KEY_F5, 'r')
def refresh_content(self):
"Re-download all subscriptions and reset the page index"
self.content = SubscriptionContent.get_list(self.reddit, self.loader)
self.nav = Navigator(self.content.get)
@SubscriptionController.register(curses.KEY_ENTER, 10, curses.KEY_RIGHT)
def store_selected_subreddit(self):
"Store the selected subreddit and return to the subreddit page"
self.selected_subreddit_data = self.content.get(self.nav.absolute_index)
self.active = False
@SubscriptionController.register(curses.KEY_LEFT, 'h', 's')
def close_subscriptions(self):
"Close subscriptions and return to the subreddit page"
self.active = False
@staticmethod
def draw_item(win, data, inverted=False):
n_rows, n_cols = win.getmaxyx()
n_cols -= 1 # Leave space for the cursor in the first column
# Handle the case where the window is not large enough to fit the data.
valid_rows = range(0, n_rows)
offset = 0 if not inverted else -(data['n_rows'] - n_rows)
row = offset
if row in valid_rows:
attr = curses.A_BOLD | Color.YELLOW
add_line(win, u'{name}'.format(**data), row, 1, attr)
row = offset + 1
for row, text in enumerate(data['split_title'], start=row):
if row in valid_rows:
add_line(win, text, row, 1)