diff options
Diffstat (limited to '')
-rw-r--r-- | utils/utils.py | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/utils/utils.py b/utils/utils.py index f8a756c5..11d806f5 100644 --- a/utils/utils.py +++ b/utils/utils.py @@ -19,6 +19,8 @@ import multiprocessing import os import sys +import string + from config.config import * from rss import * @@ -298,3 +300,142 @@ def list_posts(): posts.sort(key=lambda post: post[0], reverse=True) return posts + + +class PostSelector: + + def __init__(self, term, posts): + self._term = term + self.posts_per_page = term.height - 2 + self.pages = [posts[i:i+self.posts_per_page] + for i in range(0, len(posts), self.posts_per_page)] + self.num_pages = len(self.pages) + self.pagepos = 0 + self.postpos = 0 + self.inserting = False # True if in the middle of inserting a post #, False otherwise + term.enter_fullscreen() + print(term.clear(), end="") + sys.stdout.flush() + self.selection = "" + self.quit = False + + self.display_page() + + def _clear_to_eol(self): + term = self._term + print(term.clear_eol, end="") + sys.stdout.flush() + + def _print_line(self, line, linenum, highlight=False): + term = self._term + width = term.width + with term.location(0, linenum): + if highlight: + print(term.reverse(line[:width]), end="") + else: + print(line[:width], end="") + self._clear_to_eol() + + def _print_post(self, page, pos, highlight=False): + if pos >= len(page): + # if position out of range, just clear the line + self._print_line("", pos + 1, highlight) + else: + date, title, path = page[pos] + line = "%3d: %s %s" % (pos, date.strftime("%m/%d/%y"), title) + self._print_line(line, pos + 1, highlight) + + def display_page(self): + term = self._term + page = self.pages[self.pagepos] + + with term.hidden_cursor(): + topline = " PAGE %d/%d POST %d" % (self.pagepos + 1, self.num_pages, self.postpos) + if self.inserting: + topline += term.blink("_") + self._print_line(topline, 0, highlight=True) + + for i in range(self.posts_per_page): + self._print_post(page, i) + # highlight selected post + self._print_post(page, self.postpos, highlight=True) + + bottomline = " Press h for help." + self._print_line(bottomline, term.height - 1, highlight=True) + + def dispatch(self, key): + term = self._term + if key in string.digits: + # insert + if self.inserting: + newpostpos = 10 * self.postpos + int(key) + if newpostpos < len(self.pages[self.pagepos]): + self.postpos = newpostpos + else: + self.postpos = int(key) + self.inserting = True + elif key.name == "KEY_DELETE": + self.postpos //= 10 + self.inserting = True + else: + self.inserting = False + if key.name == "KEY_ENTER": + self.selection = self.pages[self.pagepos][self.postpos][2] + if key in {"q", "Q"}: + self.quit = True + elif key.name == "KEY_DOWN" or key in {"n", "N"}: + if self.postpos + 1 < len(self.pages[self.pagepos]): + self.postpos += 1 + elif key.name == "KEY_UP" or key in {"p", "P"}: + if self.postpos > 0: + self.postpos -= 1 + elif key.name == "KEY_RIGHT" or key in {".", ">"}: + if self.pagepos + 1 < self.num_pages: + self.pagepos += 1 + self.postpos = 0 + elif key.name == "KEY_LEFT" or key in {",", "<"}: + if self.pagepos > 0: + self.pagepos -= 1 + self.postpos = 0 + elif key in {"h", "H"}: + print(term.clear_eol, end="") + sys.stdout.flush() + help_text_lines = [ + "Next post: n or <down>", + "Previous post: p or <up>", + "Next page: . or > or <right>", + "Previous page: , or < or <left>", + "Select post: <enter> or <return>", + "Select by number: type number as shown (delete or backspace to edit)", + "Get help: h", + "Quit program: q", + ] + for i in range(term.height - 1): + self._print_line(help_text_lines[i] if i < len(help_text_lines) else "", i) + bottomline = " Press any key to continue." + self._print_line(bottomline, term.height - 1, highlight=True) + + with term.raw(): + term.inkey() + + def restore(self): + term = self._term + term.exit_fullscreen() + print(term.clear(), end="") + sys.stdout.flush() + + def select(self): + term = self._term + try: + while True: + with term.raw(): + self.dispatch(term.inkey()) + if self.selection or self.quit: + break + self.display_page() + except Exception: + raise + finally: + self.restore() + + return self.selection |