diff --git a/CONTROLS.rst b/CONTROLS.rst
index f5075f4..c3cfa63 100644
--- a/CONTROLS.rst
+++ b/CONTROLS.rst
@@ -60,3 +60,4 @@ In submission mode you can view the self text for a submission and browse commen
:``l`` or ``►``: Open the selected comment in a new window
:``o`` or ``ENTER``: Open the comment permalink with your web browser
:``SPACE``: Fold the selected comment, or load additional comments
+:``b``: Displays URLs with urlview
diff --git a/README.rst b/README.rst
index 32309e2..b9230d5 100644
--- a/README.rst
+++ b/README.rst
@@ -136,6 +136,34 @@ If you prefer the complete terminal experience, set ``$BROWSER`` to a console-ba
`w3m `_, `lynx `_, and `elinks `_ are all good choices.
+----------
+Url Viewer
+----------
+
+You can open comment links using a url extraction binary.
+The ``$RTV_URLVIEWER`` environment variable can be used to set the url viewer.
+
+.. code-block:: bash
+
+ $ export RTV_URLVIEWER=urlview
+
+The default program is ``urlview``, but most systems do not come with it installed by default.
+
+Ubuntu
+------
+.. code-block:: bash
+
+ $ sudo apt-get install urlview
+
+Mac with Homebrew
+-----------------
+.. code-block:: bash
+
+ $ brew install urlview
+
+
+`urlview `_, `urlscan `_, are known to be compatible, but any program that accepts text via a stdin pipe will do
+
===
FAQ
===
diff --git a/rtv/docs.py b/rtv/docs.py
index bb9eab8..c1542a8 100644
--- a/rtv/docs.py
+++ b/rtv/docs.py
@@ -44,6 +44,7 @@ HELP = """
`h` or `LEFT` : Return to subreddit mode
`l` or `RIGHT` : Open the selected comment in a new window
`SPACE` : Fold the selected comment, or load additional comments
+ `b` : Display URLs with urlview
"""
COMMENT_FILE = """
diff --git a/rtv/rtv.cfg b/rtv/rtv.cfg
index b7ad320..cb15877 100644
--- a/rtv/rtv.cfg
+++ b/rtv/rtv.cfg
@@ -112,6 +112,7 @@ SUBMISSION_OPEN_IN_BROWSER = o, ,
SUBMISSION_POST = c
SUBMISSION_EXIT = h,
SUBMISSION_OPEN_IN_PAGER = l,
+SUBMISSION_OPEN_IN_URLVIEWER = b
; Subreddit page
SUBREDDIT_SEARCH = f
diff --git a/rtv/submission.py b/rtv/submission.py
index a70dd3a..39fa3a7 100644
--- a/rtv/submission.py
+++ b/rtv/submission.py
@@ -35,11 +35,11 @@ class SubmissionPage(Page):
current_index = self.nav.absolute_index
self.content.toggle(current_index)
- # This logic handles a display edge case after a comment toggle. We want
- # to make sure that when we re-draw the page, the cursor stays at its
- # current absolute position on the screen. In order to do this, apply
- # a fixed offset if, while inverted, we either try to hide the bottom
- # comment or toggle any of the middle comments.
+ # This logic handles a display edge case after a comment toggle. We
+ # want to make sure that when we re-draw the page, the cursor stays at
+ # its current absolute position on the screen. In order to do this,
+ # apply a fixed offset if, while inverted, we either try to hide the
+ # bottom comment or toggle any of the middle comments.
if self.nav.inverted:
data = self.content.get(current_index)
if data['hidden'] or self.nav.cursor_index != 0:
@@ -147,6 +147,15 @@ class SubmissionPage(Page):
else:
self.term.flash()
+ @SubmissionController.register(Command('SUBMISSION_OPEN_IN_URLVIEWER'))
+ def comment_urlview(self):
+ data = self.content.get(self.nav.absolute_index)
+ comment = data.get('body', '')
+ if comment:
+ self.term.open_urlview(comment)
+ else:
+ self.term.flash()
+
def _draw_item(self, win, data, inverted):
if data['type'] == 'MoreComments':
@@ -219,7 +228,8 @@ class SubmissionPage(Page):
n_cols -= 1
self.term.add_line(win, '{body}'.format(**data), 0, 1)
- self.term.add_line(win, ' [{count}]'.format(**data), attr=curses.A_BOLD)
+ self.term.add_line(
+ win, ' [{count}]'.format(**data), attr=curses.A_BOLD)
attr = Color.get_level(data['level'])
self.term.addch(win, 0, 0, self.term.vline, attr)
diff --git a/rtv/terminal.py b/rtv/terminal.py
index d7fa38e..90dc698 100644
--- a/rtv/terminal.py
+++ b/rtv/terminal.py
@@ -349,7 +349,8 @@ class Terminal(object):
'Browser exited with status=%s' % code)
time.sleep(0.01)
else:
- raise exceptions.BrowserError('Timeout opening browser')
+ raise exceptions.BrowserError(
+ 'Timeout opening browser')
finally:
# Can't check the loader exception because the oauth module
# supersedes this loader and we need to always kill the
@@ -438,6 +439,20 @@ class Terminal(object):
else:
_logger.info('File deleted: %s', filepath)
+ def open_urlview(self, data):
+ urlview = os.getenv('RTV_URLVIEWER') or 'urlview'
+ try:
+ with self.suspend():
+ p = subprocess.Popen([urlview],
+ stdin=subprocess.PIPE)
+ try:
+ p.communicate(input=six.b(data))
+ except KeyboardInterrupt:
+ p.terminate()
+ except OSError:
+ self.show_notification(
+ 'Could not open urls with {}'.format(urlview))
+
def text_input(self, window, allow_resize=False):
"""
Transform a window into a text box that will accept user input and loop
@@ -574,4 +589,4 @@ class Terminal(object):
break
out = '\n'.join(stack)
- return out
\ No newline at end of file
+ return out
diff --git a/scripts/rtv.1.template b/scripts/rtv.1.template
index 02831dd..6ca82a8 100644
--- a/scripts/rtv.1.template
+++ b/scripts/rtv.1.template
@@ -28,6 +28,10 @@ for future sessions. You can disable this behavior by setting the option
Text editor to use when editing comments and submissions. Will fallback to
\fI$EDITOR\fR.
.TP
+.BR RTV_URLVIEWER
+Url Viewer to use to extract links from comments. Requires a compatible
+Url Viewer to be installed
+.TP
.BR BROWSER
Web browser to use when opening links.
.TP
diff --git a/tests/cassettes/test_submission_urlview.yaml b/tests/cassettes/test_submission_urlview.yaml
new file mode 100644
index 0000000..23af475
--- /dev/null
+++ b/tests/cassettes/test_submission_urlview.yaml
@@ -0,0 +1,249 @@
+interactions:
+- request:
+ body: !!binary |
+ cmVkaXJlY3RfdXJpPWh0dHAlM0ElMkYlMkYxMjcuMC4wLjElM0E2NTAwMCUyRiZncmFudF90eXBl
+ PXJlZnJlc2hfdG9rZW4mcmVmcmVzaF90b2tlbj0qKioqKioqKioq
+ headers:
+ Accept: ['*/*']
+ Accept-Encoding: ['gzip, deflate']
+ Authorization: ['**********']
+ Connection: [keep-alive]
+ Content-Length: ['122']
+ Content-Type: [application/x-www-form-urlencoded]
+ Cookie: [__cfduid=d963647719488322ce24aaf79235c3d6e1449042300]
+ User-Agent: [rtv test suite PRAW/3.3.0 Python/3.4.0 b'Linux-3.13.0-24-generic-x86_64-with-Ubuntu-14.04-trusty']
+ method: POST
+ uri: https://api.reddit.com/api/v1/access_token/
+ response:
+ body:
+ string: !!binary |
+ H4sIAAAAAAAAAyWMsQrCQBAFf2W5WiFqDGqb0lYQq3DJPXSReMfuJvEU/12i1YNh5r2d7zqoNhbv
+ eLgDubKsdsVqtV0iDedjf/GvNJzzaR/qqeZ1XW72084tyP2CxnLCXLXwApk5nokF2vD8tqmKYkFO
+ u/jXENjoxmpRMnHAw9gy9VmHVhACm1ISHr2hh6q/QkngAwlSFCP1I0iHtmebRzvhFjRGg/t8AYx9
+ Bq7KAAAA
+ headers:
+ CF-RAY: [24e569649f492816-SJC]
+ Connection: [keep-alive]
+ Content-Encoding: [gzip]
+ Content-Type: [application/json; charset=UTF-8]
+ Date: ['Wed, 02 Dec 2015 07:45:20 GMT']
+ Server: [cloudflare-nginx]
+ Strict-Transport-Security: [max-age=15552000; includeSubDomains; preload]
+ X-Moose: [majestic]
+ cache-control: ['max-age=0, must-revalidate']
+ x-content-type-options: [nosniff]
+ x-frame-options: [SAMEORIGIN]
+ x-xss-protection: [1; mode=block]
+ status: {code: 200, message: OK}
+- request:
+ body: null
+ headers:
+ Accept: ['*/*']
+ Accept-Encoding: ['gzip, deflate']
+ Authorization: ['**********']
+ Connection: [keep-alive]
+ User-Agent: [rtv test suite PRAW/3.3.0 Python/3.4.0 b'Linux-3.13.0-24-generic-x86_64-with-Ubuntu-14.04-trusty']
+ method: GET
+ uri: https://oauth.reddit.com/api/v1/me.json
+ response:
+ body:
+ string: !!binary |
+ H4sIAAAAAAAAA12QwWrDMBBEf0Xs2YTYuLTxZ5TSq5CtdbNE2k1XUhoI/fei1C5xjxp23ozmBkeX
+ bHQUYDCzCwkbA+wiwmDgFb2n/IYaiV14J/xChcbApOgyehhM2/fd89O+Oxx2+8bAkTzaWSValVFy
+ emBSsqmkM7K/G1d5QdmSpxXXtf2Kq9XE/68XiE/25DS6aqkQiRE5/2nVKxdU275sG3xI8Fslykao
+ D/gMjGP9Zz23eD2TukzCMBguIdQ7HuVqJymcl7ha9YJKM6G3uBTOWnDFTHofMy33v1skEn4IWFao
+ Id8/dZfx5JkBAAA=
+ headers:
+ CF-RAY: [24e56971a0f811a7-SJC]
+ Connection: [keep-alive]
+ Content-Encoding: [gzip]
+ Content-Type: [application/json; charset=UTF-8]
+ Date: ['Wed, 02 Dec 2015 07:45:22 GMT']
+ Server: [cloudflare-nginx]
+ Set-Cookie: ['__cfduid=d667511ab17e019fb769e680b9cab23071449042322; expires=Thu,
+ 01-Dec-16 07:45:22 GMT; path=/; domain=.reddit.com; HttpOnly']
+ Strict-Transport-Security: [max-age=15552000; includeSubDomains; preload]
+ X-Moose: [majestic]
+ cache-control: ['private, s-maxage=0, max-age=0, must-revalidate', 'max-age=0,
+ must-revalidate']
+ expires: ['-1']
+ x-content-type-options: [nosniff]
+ x-frame-options: [SAMEORIGIN]
+ x-ratelimit-remaining: ['586.0']
+ x-ratelimit-reset: ['278']
+ x-ratelimit-used: ['14']
+ x-xss-protection: [1; mode=block]
+ status: {code: 200, message: OK}
+- request:
+ body: null
+ headers:
+ Accept: ['*/*']
+ Accept-Encoding: ['gzip, deflate']
+ Authorization: ['**********']
+ Connection: [keep-alive]
+ Cookie: [__cfduid=d667511ab17e019fb769e680b9cab23071449042322]
+ User-Agent: [rtv test suite PRAW/3.3.0 Python/3.4.0 b'Linux-3.13.0-24-generic-x86_64-with-Ubuntu-14.04-trusty']
+ method: GET
+ uri: https://oauth.reddit.com/r/Python/comments/2xmo63/a_python_terminal_viewer_for_browsing_reddit/.json
+ response:
+ body:
+ string: !!binary |
+ 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
+ AA==
+ headers:
+ CF-RAY: [24e56974010611a7-SJC]
+ Connection: [keep-alive]
+ Content-Encoding: [gzip]
+ Content-Length: ['7639']
+ Content-Type: [application/json; charset=UTF-8]
+ Date: ['Wed, 02 Dec 2015 07:45:22 GMT']
+ Server: [cloudflare-nginx]
+ Strict-Transport-Security: [max-age=15552000; includeSubDomains; preload]
+ Vary: [accept-encoding]
+ X-Moose: [majestic]
+ cache-control: ['private, s-maxage=0, max-age=0, must-revalidate', 'max-age=0,
+ must-revalidate']
+ expires: ['-1']
+ x-content-type-options: [nosniff]
+ x-frame-options: [SAMEORIGIN]
+ x-ratelimit-remaining: ['585.0']
+ x-ratelimit-reset: ['278']
+ x-ratelimit-used: ['15']
+ x-reddit-tracking: ['https://pixel.redditmedia.com/pixel/of_destiny.png?v=x7Hgtcci0o4lZvWWI68HSCYaPfSu8AoLGJymDPfSvXaVLHrXHOY314V%2FS7aiBGPeCNk%2FdOqa1ik%3D']
+ x-ua-compatible: [IE=edge]
+ x-xss-protection: [1; mode=block]
+ status: {code: 200, message: OK}
+version: 1
diff --git a/tests/test_submission.py b/tests/test_submission.py
index e224bd7..77825a1 100644
--- a/tests/test_submission.py
+++ b/tests/test_submission.py
@@ -253,4 +253,29 @@ def test_submission_edit(submission_page, terminal, refresh_token):
submission_page.controller.trigger('e')
assert open_editor.called
- edit.assert_called_with('comment text')
\ No newline at end of file
+ edit.assert_called_with('comment text')
+
+
+def test_submission_urlview(submission_page, terminal, refresh_token):
+
+ # Log in
+ submission_page.config.refresh_token = refresh_token
+ submission_page.oauth.authorize()
+
+ # Positive Case
+ data = submission_page.content.get(submission_page.nav.absolute_index)
+ TEST_BODY = 'test comment body'
+ data['body'] = TEST_BODY
+ with mock.patch.object(terminal, 'open_urlview') as open_urlview, \
+ mock.patch('subprocess.Popen'):
+ submission_page.controller.trigger('b')
+ open_urlview.assert_called_with(TEST_BODY)
+
+ # Negative Case
+ data = submission_page.content.get(submission_page.nav.absolute_index)
+ TEST_NO_BODY = ''
+ data['body'] = TEST_NO_BODY
+ with mock.patch.object(terminal, 'open_urlview') as open_urlview, \
+ mock.patch('subprocess.Popen'):
+ submission_page.controller.trigger('b')
+ assert not open_urlview.called