Raise NotImplemetedError.
This commit is contained in:
@@ -15,9 +15,17 @@ from . import exceptions
|
||||
class Content(object):
|
||||
|
||||
def get(self, index, n_cols):
|
||||
"""
|
||||
Grab the item at the given index, and format the text to fit a width of
|
||||
n columns.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def iterate(self, index, step, n_cols=70):
|
||||
"""
|
||||
Return an iterator that starts and the current index and increments
|
||||
by the given step.
|
||||
"""
|
||||
|
||||
while True:
|
||||
if step < 0 and index < 0:
|
||||
@@ -30,6 +38,13 @@ class Content(object):
|
||||
break
|
||||
index += step
|
||||
|
||||
@property
|
||||
def range(self):
|
||||
"""
|
||||
Return the minimm and maximum valid indicies.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
@staticmethod
|
||||
def flatten_comments(comments, root_level=0):
|
||||
"""
|
||||
@@ -305,6 +320,10 @@ class SubmissionContent(Content):
|
||||
submission = reddit.get_submission(url, comment_sort=order)
|
||||
return cls(submission, loader, indent_size, max_indent_level, order)
|
||||
|
||||
@property
|
||||
def range(self):
|
||||
return -1, len(self._comment_data) - 1
|
||||
|
||||
def get(self, index, n_cols=70):
|
||||
"""
|
||||
Grab the `i`th submission, with the title field formatted to fit inside
|
||||
@@ -559,6 +578,13 @@ class SubredditContent(Content):
|
||||
# We made it!
|
||||
return cls(display_name, submissions, loader, order=display_order)
|
||||
|
||||
@property
|
||||
def range(self):
|
||||
# Note that for subreddits, the submissions are generated lazily and
|
||||
# there is no actual "end" index. Instead, we return the bottom index
|
||||
# that we have loaded so far.
|
||||
return 0, len(self._submission_data) - 1
|
||||
|
||||
def get(self, index, n_cols=70):
|
||||
"""
|
||||
Grab the `i`th submission, with the title field formatted to fit inside
|
||||
@@ -615,6 +641,15 @@ class SubscriptionContent(Content):
|
||||
except IndexError:
|
||||
raise exceptions.SubscriptionError('No content')
|
||||
|
||||
# Load 1024 subscriptions up front (one http request's worth)
|
||||
# For most people this should be all of their subscriptions. Doing thi
|
||||
# allows the user to jump to the end of the page with `G`.
|
||||
if name != 'Popular Subreddits':
|
||||
try:
|
||||
self.get(1023)
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def from_user(cls, reddit, loader, content_type='subreddit'):
|
||||
if content_type == 'subreddit':
|
||||
@@ -632,6 +667,10 @@ class SubscriptionContent(Content):
|
||||
|
||||
return cls(name, items, loader)
|
||||
|
||||
@property
|
||||
def range(self):
|
||||
return 0, len(self._subscription_data) - 1
|
||||
|
||||
def get(self, index, n_cols=70):
|
||||
"""
|
||||
Grab the `i`th object, with the title field formatted to fit
|
||||
|
||||
@@ -519,11 +519,6 @@ class Controller(object):
|
||||
>>> def upvote(self, *args)
|
||||
>> ...
|
||||
|
||||
Register a default behavior by using `None`.
|
||||
>>> @Controller.register(None)
|
||||
>>> def default_func(self, *args)
|
||||
>>> ...
|
||||
|
||||
Bind the controller to a class instance and trigger a key. Additional
|
||||
arguments will be passed to the function.
|
||||
>>> controller = Controller(self)
|
||||
@@ -538,6 +533,8 @@ class Controller(object):
|
||||
# Build a list of parent controllers that follow the object's MRO
|
||||
# to check if any parent controllers have registered the keypress
|
||||
self.parents = inspect.getmro(type(self))[:-1]
|
||||
# Keep track of last key press for doubles like `gg`
|
||||
self.last_char = None
|
||||
|
||||
if not keymap:
|
||||
return
|
||||
@@ -551,6 +548,18 @@ class Controller(object):
|
||||
if isinstance(command, Command):
|
||||
for key in keymap.get(command):
|
||||
val = keymap.parse(key)
|
||||
# If a double key press is defined, the first half
|
||||
# must be unbound
|
||||
if isinstance(val, tuple):
|
||||
if controller.character_map.get(val[0]) is not None:
|
||||
raise exceptions.ConfigError(
|
||||
"Invalid configuration! `%s` is bound to "
|
||||
"duplicate commands in the "
|
||||
"%s" % (key, controller.__name__))
|
||||
# Mark the first half of the double with None so
|
||||
# that no other command can use it
|
||||
controller.character_map[val[0]] = None
|
||||
|
||||
# Check if the key is already programmed to trigger a
|
||||
# different function.
|
||||
if controller.character_map.get(val, func) != func:
|
||||
@@ -569,16 +578,19 @@ class Controller(object):
|
||||
# Check if the controller (or any of the controller's parents) have
|
||||
# registered a function to the given key
|
||||
for controller in self.parents:
|
||||
func = controller.character_map.get((self.last_char, char))
|
||||
if func:
|
||||
break
|
||||
func = controller.character_map.get(char)
|
||||
# If the controller has not registered the key, check if there is a
|
||||
# default function registered
|
||||
for controller in self.parents:
|
||||
if func:
|
||||
break
|
||||
func = controller.character_map.get(None)
|
||||
return func(self.instance, *args, **kwargs) if func else None
|
||||
|
||||
if func:
|
||||
self.last_char = None
|
||||
return func(self.instance, *args, **kwargs)
|
||||
else:
|
||||
self.last_char = char
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def register(cls, *chars):
|
||||
@@ -645,8 +657,8 @@ class KeyMap(object):
|
||||
raise exceptions.ConfigError('Invalid configuration! `%s` key is '
|
||||
'undefined' % command.val)
|
||||
|
||||
@staticmethod
|
||||
def parse(key):
|
||||
@classmethod
|
||||
def parse(cls, key):
|
||||
"""
|
||||
Parse a key represented by a string and return its character code.
|
||||
"""
|
||||
@@ -663,6 +675,9 @@ class KeyMap(object):
|
||||
elif key.startswith('0x'):
|
||||
# Ascii hex code
|
||||
return int(key, 16)
|
||||
elif len(key) == 2:
|
||||
# Double presses
|
||||
return tuple(cls.parse(k) for k in key)
|
||||
else:
|
||||
# Ascii character
|
||||
code = ord(key)
|
||||
|
||||
16
rtv/page.py
16
rtv/page.py
@@ -124,6 +124,22 @@ class Page(object):
|
||||
self._move_page(1)
|
||||
self.clear_input_queue()
|
||||
|
||||
@PageController.register(Command('PAGE_TOP'))
|
||||
def move_page_top(self):
|
||||
self._remove_cursor()
|
||||
self.nav.page_index = self.content.range[0]
|
||||
self.nav.cursor_index = 0
|
||||
self.nav.inverted = False
|
||||
self._add_cursor()
|
||||
|
||||
@PageController.register(Command('PAGE_BOTTOM'))
|
||||
def move_page_bottom(self):
|
||||
self._remove_cursor()
|
||||
self.nav.page_index = self.content.range[1]
|
||||
self.nav.cursor_index = 0
|
||||
self.nav.inverted = True
|
||||
self._add_cursor()
|
||||
|
||||
@PageController.register(Command('UPVOTE'))
|
||||
@logged_in
|
||||
def upvote(self):
|
||||
|
||||
@@ -101,6 +101,8 @@ MOVE_UP = k, <KEY_UP>
|
||||
MOVE_DOWN = j, <KEY_DOWN>
|
||||
PAGE_UP = m, <KEY_PPAGE>, <NAK>
|
||||
PAGE_DOWN = n, <KEY_NPAGE>, <EOT>
|
||||
PAGE_TOP = gg
|
||||
PAGE_BOTTOM = G
|
||||
UPVOTE = a
|
||||
DOWNVOTE = z
|
||||
LOGIN = u
|
||||
|
||||
Reference in New Issue
Block a user