Added urlview keybinding

1.  A shortcut of 'b' was used as the default binding for passing
comment body text to urlview (this is similar to the default of C-b in
the 'mutt' text email client)
2.  The `comment_urlview` SubmissionController function was added to
recieve the SUBMISSION_OPEN_IN_URLVIEWER keypress request.
3.  The `open_urlview` terminal function was added to handle the urlview
request.  It passes the comment body data to urlview via a Popen
process.
4.  A test case was added to ensure this new code path is executed
5.  Small formatting changes, mostly line length
This commit is contained in:
Matt Smith
2016-07-04 22:42:30 -07:00
committed by Matt Smith
parent fb837bafc7
commit 749ad11171
9 changed files with 343 additions and 9 deletions

View File

@@ -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

View File

@@ -136,6 +136,34 @@ If you prefer the complete terminal experience, set ``$BROWSER`` to a console-ba
`w3m <http://w3m.sourceforge.net/>`_, `lynx <http://lynx.isc.org/>`_, and `elinks <http://elinks.or.cz/>`_ 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 <https://github.com/sigpipe/urlview>`_, `urlscan <https://github.com/firecat53/urlscan>`_, are known to be compatible, but any program that accepts text via a stdin pipe will do
===
FAQ
===

View File

@@ -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 = """

View File

@@ -112,6 +112,7 @@ SUBMISSION_OPEN_IN_BROWSER = o, <LF>, <KEY_ENTER>
SUBMISSION_POST = c
SUBMISSION_EXIT = h, <KEY_LEFT>
SUBMISSION_OPEN_IN_PAGER = l, <KEY_RIGHT>
SUBMISSION_OPEN_IN_URLVIEWER = b
; Subreddit page
SUBREDDIT_SEARCH = f

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -254,3 +254,28 @@ def test_submission_edit(submission_page, terminal, refresh_token):
submission_page.controller.trigger('e')
assert open_editor.called
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