From eabfb6ad88e5b64e857016220dd884272fbf197d Mon Sep 17 00:00:00 2001 From: Brobin Date: Mon, 27 Apr 2015 17:36:05 -0500 Subject: [PATCH 1/5] implemented hsitory logging accross sessions witha history.log file remove unnecessary variable return an empty set if the file doesn't exist xrange is range in python3 --- rtv/history.py | 37 +++++++++++++++++++++++++++++++++++++ rtv/subreddit.py | 24 +++++++++++++++--------- 2 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 rtv/history.py diff --git a/rtv/history.py b/rtv/history.py new file mode 100644 index 0000000..ffcd245 --- /dev/null +++ b/rtv/history.py @@ -0,0 +1,37 @@ +import os + + +__all__ = ['load_history', 'save_history'] + + +def history_path(): + """ + Create the path to the history log + """ + HOME = os.path.expanduser('~') + XDG_CONFIG_HOME = os.getenv('XDG_CACHE_HOME', os.path.join(HOME, '.config')) + path = os.path.join(XDG_CONFIG_HOME, 'rtv', 'history.log') + return path + + +def load_history(): + """ + Load the history file into memory if it exists + """ + path = history_path() + if os.path.exists(path): + with open(path) as history_file: + return set([line.replace('\n', '') for line in history_file]) + return set() + + +def save_history(history): + """ + Save the visited links to the history log + """ + path = history_path() + with open(path, 'w+') as history_file: + for i in range(200): + if not history: + break + history_file.write(history.pop() + '\n') \ No newline at end of file diff --git a/rtv/subreddit.py b/rtv/subreddit.py index d1f7ff3..9ce4322 100644 --- a/rtv/subreddit.py +++ b/rtv/subreddit.py @@ -1,7 +1,7 @@ import curses import time import logging - +import atexit import requests import praw @@ -10,16 +10,22 @@ from .page import BasePage, Navigator, BaseController from .submission import SubmissionPage from .content import SubredditContent from .helpers import clean, open_browser, open_editor +from .history import load_history, save_history from .docs import SUBMISSION_FILE from .curses_helpers import (BULLET, UARROW, DARROW, GOLD, Color, LoadScreen, show_notification, prompt_input) -__all__ = ['opened_links', 'SubredditController', 'SubredditPage'] +__all__ = ['history', 'SubredditController', 'SubredditPage'] _logger = logging.getLogger(__name__) -# Used to keep track of browsing history across the current session -opened_links = set() +history = load_history() + + +@atexit.register +def save_links(): + global history + save_history(history) class SubredditController(BaseController): @@ -96,8 +102,8 @@ class SubredditPage(BasePage): page.loop() if data['url'] == 'selfpost': - global opened_links - opened_links.add(data['url_full']) + global history + history.add(data['url_full']) @SubredditController.register(curses.KEY_ENTER, 10, 'o') def open_link(self): @@ -106,8 +112,8 @@ class SubredditPage(BasePage): url = self.content.get(self.nav.absolute_index)['url_full'] open_browser(url) - global opened_links - opened_links.add(url) + global history + history.add(url) @SubredditController.register('p') def post_submission(self): @@ -168,7 +174,7 @@ class SubredditPage(BasePage): row = n_title + offset if row in valid_rows: - seen = (data['url_full'] in opened_links) + seen = (data['url_full'] in history) link_color = Color.MAGENTA if seen else Color.BLUE attr = curses.A_UNDERLINE | link_color text = clean(u'{url}'.format(**data)) From 1ca5f0a64932a56dcbd7ca8fa2e464cec5e3ebc8 Mon Sep 17 00:00:00 2001 From: Brobin Date: Tue, 28 Apr 2015 00:25:21 -0500 Subject: [PATCH 2/5] refactored to an ordered set, make config directory if it doens't exist. remove item from set and list when pop is called remove occasionaly throws an error --- rtv/history.py | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/rtv/history.py b/rtv/history.py index ffcd245..a91e391 100644 --- a/rtv/history.py +++ b/rtv/history.py @@ -10,8 +10,10 @@ def history_path(): """ HOME = os.path.expanduser('~') XDG_CONFIG_HOME = os.getenv('XDG_CACHE_HOME', os.path.join(HOME, '.config')) - path = os.path.join(XDG_CONFIG_HOME, 'rtv', 'history.log') - return path + path = os.path.join(XDG_CONFIG_HOME, 'rtv') + if not os.path.exists(path): + os.makedirs(path) + return os.path.join(path, 'history.log') def load_history(): @@ -21,8 +23,9 @@ def load_history(): path = history_path() if os.path.exists(path): with open(path) as history_file: - return set([line.replace('\n', '') for line in history_file]) - return set() + history = [line.strip() for line in history_file] + return OrderedSet(history) + return OrderedSet() def save_history(history): @@ -34,4 +37,28 @@ def save_history(history): for i in range(200): if not history: break - history_file.write(history.pop() + '\n') \ No newline at end of file + history_file.write(history.pop() + '\n') + + +class OrderedSet(object): + """ + A simple implementation of an ordered set. A set is used to check + for membership, and a list is used to maintain ordering. + """ + + def __init__(self, elements=[]): + self._set = set(elements) + self._list = elements + + def __contains__(self, item): + return item in self._set + + def __len__(self): + return len(self._list) + + def add(self, item): + self._set.add(item) + self._list.append(item) + + def pop(self): + return self._list.pop() From 15f15c9302aa96759028c457f3b6b8b87371336d Mon Sep 17 00:00:00 2001 From: Brobin Date: Tue, 28 Apr 2015 22:23:28 -0500 Subject: [PATCH 3/5] retain history order by reversing the list --- rtv/history.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rtv/history.py b/rtv/history.py index a91e391..8db031e 100644 --- a/rtv/history.py +++ b/rtv/history.py @@ -23,7 +23,8 @@ def load_history(): path = history_path() if os.path.exists(path): with open(path) as history_file: - history = [line.strip() for line in history_file] + # reverse the list so the newest ones are first + history = [line.strip() for line in history_file][::-1] return OrderedSet(history) return OrderedSet() From b375fb71e7f34cd67be080ff0db7e1daa4ce184c Mon Sep 17 00:00:00 2001 From: Michael Lazar Date: Tue, 12 May 2015 01:47:03 -0700 Subject: [PATCH 4/5] Fixed cursor out of bounds error with window resize. --- rtv/page.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/rtv/page.py b/rtv/page.py index f38ee7b..2cbfb3a 100644 --- a/rtv/page.py +++ b/rtv/page.py @@ -533,26 +533,21 @@ class BasePage(object): def _move_cursor(self, direction): self._remove_cursor() valid, redraw = self.nav.move(direction, len(self._subwindows)) - if not valid: curses.flash() # Note: ACS_VLINE doesn't like changing the attribute, so always redraw. - # if redraw: self._draw_content() self._draw_content() self._add_cursor() def _move_page(self, direction): self._remove_cursor() - valid, redraw = self.nav.move_page(direction, - len(self._subwindows)-1) + valid, redraw = self.nav.move_page(direction, len(self._subwindows)-1) if not valid: curses.flash() + # Note: ACS_VLINE doesn't like changing the attribute, so always redraw. self._draw_content() - # Don't allow the cursor to go over the subwindow number - if self.nav.cursor_index >= len(self._subwindows): - self.nav.cursor_index = len(self._subwindows)-1 self._add_cursor() def _edit_cursor(self, attribute=None): @@ -561,6 +556,12 @@ class BasePage(object): if self.nav.absolute_index < 0: return + # Don't allow the cursor to go over the number of subwindows + # This could happen if the window is resized and the cursor index is + # pushed out of bounds + if self.nav.cursor_index >= len(self._subwindows): + self.nav.cursor_index = len(self._subwindows)-1 + window, attr = self._subwindows[self.nav.cursor_index] if attr is not None: attribute |= attr From c608e35b1e3bdb183b5bceaf7b37ba3f496c66ba Mon Sep 17 00:00:00 2001 From: Michael Lazar Date: Tue, 12 May 2015 22:16:55 -0700 Subject: [PATCH 5/5] Fixed crash when saving history with unicode URLs. --- rtv/history.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rtv/history.py b/rtv/history.py index 8db031e..1ca48fa 100644 --- a/rtv/history.py +++ b/rtv/history.py @@ -38,8 +38,11 @@ def save_history(history): for i in range(200): if not history: break - history_file.write(history.pop() + '\n') - + try: + history_file.write(history.pop() + '\n') + except UnicodeEncodeError: + # Ignore unicode URLS, may want to handle this at some point + continue class OrderedSet(object): """