Browse Source

sometimes you just herp the derp so hard it herpderps

master
John ShaggyTwoDope Jenkins 5 years ago
parent
commit
18f16a144a
64 changed files with 774 additions and 337 deletions
  1. 2
    2
      rtv-git/PKGBUILD
  2. BIN
      rtv-git/pkg/rtv-git/.MTREE
  3. 5
    4
      rtv-git/pkg/rtv-git/.PKGINFO
  4. 3
    3
      rtv-git/pkg/rtv-git/usr/bin/rtv
  5. 100
    61
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/PKG-INFO
  6. 1
    0
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/SOURCES.txt
  7. 0
    0
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/dependency_links.txt
  8. 0
    0
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/entry_points.txt
  9. 1
    0
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/requires.txt
  10. 0
    0
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/top_level.txt
  11. 8
    7
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__main__.py
  12. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/__main__.cpython-34.pyc
  13. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/__main__.cpython-34.pyo
  14. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/__version__.cpython-34.pyc
  15. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/__version__.cpython-34.pyo
  16. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/config.cpython-34.pyc
  17. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/config.cpython-34.pyo
  18. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/content.cpython-34.pyc
  19. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/content.cpython-34.pyo
  20. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/curses_helpers.cpython-34.pyc
  21. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/curses_helpers.cpython-34.pyo
  22. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/docs.cpython-34.pyc
  23. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/docs.cpython-34.pyo
  24. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/helpers.cpython-34.pyc
  25. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/helpers.cpython-34.pyo
  26. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/history.cpython-34.pyc
  27. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/history.cpython-34.pyo
  28. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/page.cpython-34.pyc
  29. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/page.cpython-34.pyo
  30. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/submission.cpython-34.pyc
  31. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/submission.cpython-34.pyo
  32. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/subreddit.cpython-34.pyc
  33. BIN
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/subreddit.cpython-34.pyo
  34. 1
    1
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__version__.py
  35. 1
    1
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/config.py
  36. 42
    24
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/content.py
  37. 88
    11
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/curses_helpers.py
  38. 29
    18
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/docs.py
  39. 78
    33
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/helpers.py
  40. 68
    0
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/history.py
  41. 218
    47
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/page.py
  42. 53
    64
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/submission.py
  43. 46
    55
      rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/subreddit.py
  44. BIN
      rtv-git/rtv-git-r345.2a93592-1-any.pkg.tar.xz
  45. BIN
      rtv-git/rtv-git-r345.2a93592-1.src.tar.gz
  46. 15
    3
      rtv-git/rtv/FETCH_HEAD
  47. BIN
      rtv-git/rtv/objects/pack/pack-d2b6062f1840e56ceb1df98ec97bcfab9ca37062.idx
  48. BIN
      rtv-git/rtv/objects/pack/pack-d2b6062f1840e56ceb1df98ec97bcfab9ca37062.pack
  49. 1
    0
      rtv-git/rtv/refs/heads/Brobin-edit_delete
  50. 1
    1
      rtv-git/rtv/refs/heads/master
  51. 1
    0
      rtv-git/rtv/refs/heads/morecomment-speed
  52. 1
    0
      rtv-git/rtv/refs/heads/unicode_kitchen
  53. 1
    0
      rtv-git/rtv/refs/pull/106/head
  54. 1
    0
      rtv-git/rtv/refs/pull/106/merge
  55. 1
    1
      rtv-git/rtv/refs/pull/83/head
  56. 0
    1
      rtv-git/rtv/refs/pull/83/merge
  57. 1
    0
      rtv-git/rtv/refs/pull/86/head
  58. 1
    0
      rtv-git/rtv/refs/pull/87/head
  59. 1
    0
      rtv-git/rtv/refs/pull/92/head
  60. 1
    0
      rtv-git/rtv/refs/pull/95/head
  61. 1
    0
      rtv-git/rtv/refs/pull/97/head
  62. 1
    0
      rtv-git/rtv/refs/pull/97/merge
  63. 1
    0
      rtv-git/rtv/refs/tags/v1.3
  64. 1
    0
      rtv-git/rtv/refs/tags/v1.4

+ 2
- 2
rtv-git/PKGBUILD View File

@@ -1,7 +1,7 @@
# Maintainer: John Jenkins twodopeshaggy@gmail.com

pkgname=rtv-git
pkgver=r293.9153fdd
pkgver=r345.2a93592
pkgrel=1
pkgdesc="Browse Reddit from your terminal"
arch=('any')
@@ -9,7 +9,7 @@ url="https://github.com/michael-lazar/rtv"
license=('MIT')
conflicts=('rtv')
makedepends=('git')
depends=('ncurses' 'python' 'python-six' 'python-requests' 'python-praw' 'python-setuptools')
depends=('python3-kitchen' 'ncurses' 'python' 'python-six' 'python-requests' 'python-praw' 'python-setuptools')
source=('git+https://github.com/michael-lazar/rtv.git')
sha256sums=('SKIP')


BIN
rtv-git/pkg/rtv-git/.MTREE View File


+ 5
- 4
rtv-git/pkg/rtv-git/.PKGINFO View File

@@ -1,16 +1,17 @@
# Generated by makepkg 4.2.1
# using fakeroot version 1.20.2
# Wed Apr 8 02:51:37 UTC 2015
# Fri May 29 09:00:52 UTC 2015
pkgname = rtv-git
pkgver = r293.9153fdd-1
pkgver = r345.2a93592-1
pkgdesc = Browse Reddit from your terminal
url = https://github.com/michael-lazar/rtv
builddate = 1428461497
builddate = 1432890052
packager = Unknown Packager
size = 231424
size = 266240
arch = any
license = MIT
conflict = rtv
depend = python3-kitchen
depend = ncurses
depend = python
depend = python-six

+ 3
- 3
rtv-git/pkg/rtv-git/usr/bin/rtv View File

@@ -1,10 +1,10 @@
#!/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'rtv==1.2.2','console_scripts','rtv'
__requires__ = 'rtv==1.2.2'
# EASY-INSTALL-ENTRY-SCRIPT: 'rtv==1.4','console_scripts','rtv'
__requires__ = 'rtv==1.4'
import sys
from pkg_resources import load_entry_point

if __name__ == '__main__':
sys.exit(
load_entry_point('rtv==1.2.2', 'console_scripts', 'rtv')()
load_entry_point('rtv==1.4', 'console_scripts', 'rtv')()
)

rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.2.2-py3.4.egg-info/PKG-INFO → rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/PKG-INFO View File

@@ -1,13 +1,12 @@
Metadata-Version: 1.1
Name: rtv
Version: 1.2.2
Version: 1.4
Summary: A simple terminal viewer for Reddit (Reddit Terminal Viewer)
Home-page: https://github.com/michael-lazar/rtv
Author: Michael Lazar
Author-email: lazar.michael22@gmail.com
License: MIT
Description:
===========================
Description: ===========================
RTV: Reddit Terminal Viewer
===========================
@@ -24,8 +23,8 @@ Description:
---------------
* `Installation`_
* `Configuration`_
* `Usage`_
* `Configuration`_
* `Changelog`_
* `Contributors`_
* `License`_
@@ -55,61 +54,44 @@ Description:
$ rtv
$ rtv --help
=====
Usage
=====
=============
Configuration
=============
RTV will read a configuration file located at ``$XDG_CONFIG_HOME/rtv/rtv.cfg`` or ``~/.config/rtv/rtv.cfg`` if ``$XDG_CONFIG_HOME`` is not set.
This can be used to avoid having to re-enter login credentials every time the program is launched.
Each line in the file will replace the corresponding default argument in the launch script.
Example config:
.. code-block:: ini
[rtv]
username=MyUsername
password=MySecretPassword
# Log file location
log=/tmp/rtv.log
# Default subreddit
subreddit=CollegeBasketball
# Default submission link - will be opened every time the program starts
# link=http://www.reddit.com/r/CollegeBasketball/comments/31irjq
# Enable unicode characters (experimental)
# This is known to be unstable with east asian wide character sets
# unicode=true
RTV supports browsing both subreddits and submission comments.
RTV allows users to compose comments and replys using their preferred text editor (**vi**, **nano**, **gedit**, etc).
Set the environment variable ``RTV_EDITOR`` to specify which editor the program should use.
Navigating is simple and intuitive.
Move the cursor using either the arrow keys or *Vim* style movement.
Move **up** and **down** to scroll through the page.
Move **right** to view the selected submission, and **left** to exit the submission.
.. code-block:: bash
--------------
Basic Commands
--------------
$ export RTV_EDITOR=gedit
:``j``/``k`` or ``▲``/``▼``: Move the cursor up/down
:``m``/``n`` or ``PgUp``/``PgDn``: Jump to the previous/next page
:``o`` or ``ENTER``: Open the selected item as a webpage
:``r`` or ``F5``: Refresh page content
:``u``: Log in or switch accounts
:``?``: Show the help screen
:``q``: Quit
----------------------
Authenticated Commands
----------------------
=====
Usage
=====
Some actions require that you be logged in to your reddit account. To log in you can either:
RTV currently supports browsing both subreddits and individual submissions. In each mode the controls are slightly different.
1. provide your username as a command line argument ``-u`` (your password will be securely prompted), or
2. press ``u`` while inside of the program
---------------
Global Commands
---------------
Once you are logged in your username will appear in the top-right corner of the screen.
:``▲``/``▼`` or ``j``/``k``: Scroll to the prev/next item
:``a``/``z``: Upvote/downvote the selected item
:``ENTER`` or ``o``: Open the selected item in the default web browser
:``r``: Refresh the current page
:``u``: Login and logout of your user account
:``?``: Show the help screen
:``q``: Quit
:``a``/``z``: Upvote/downvote
:``c``: Compose a new post or comment
:``e``: Edit an existing post or comment
:``d``: Delete an existing post or comment
--------------
Subreddit Mode
@@ -117,13 +99,12 @@ Description:
In subreddit mode you can browse through the top submissions on either the front page or a specific subreddit.
:``►`` or ``l``: View comments for the selected submission
:``l`` or ``►``: Enter the selected submission
:``/``: Open a prompt to switch subreddits
:``f``: Open a prompt to search the current subreddit
:``p``: Post a new submission to the current subreddit
The ``/`` prompt accepts subreddits in the following formats
* ``/r/python``
* ``/r/python/new``
* ``/r/python+linux`` supports multireddits
@@ -136,9 +117,68 @@ Description:
In submission mode you can view the self text for a submission and browse comments.
:``◄`` or ``h``: Return to subreddit mode
:``►`` or ``l``: Fold the selected comment, or load additional comments
:``c``: Post a new comment on the selected item
:``h`` or ``◄``: Return to the subreddit
:``SPACE``: Fold the selected comment, or load additional comments
=============
Configuration
=============
------
Editor
------
RTV allows users to compose comments and replies using their preferred text editor (**vi**, **nano**, **gedit**, etc).
You can specify which text editor you would like to use by setting the ``$RTV_EDITOR`` environment variable.
.. code-block:: bash
$ export RTV_EDITOR=gedit
If no editor is specified, RTV will fallback to the system's default ``$EDITOR``, and finally to ``nano``.
-----------
Web Browser
-----------
RTV has the capability to open links inside of your web browser.
By default RTV will use the system's browser.
On most systems this corresponds to a graphical browser such as Firefox of Chrome.
If you prefer to stay in the terminal, use ``$BROWSER`` to specify a console-based web browser.
`w3m <http://w3m.sourceforge.net/>`_, `lynx <http://lynx.isc.org/>`_, and `elinks <http://elinks.or.cz/>`_ are all good choices.
.. code-block:: bash
$ export BROWSER=w3m
-----------
Config File
-----------
RTV will read a configuration placed at ``~/.config/rtv/rtv.cfg`` (or ``$XDG_CONFIG_HOME``).
Each line in the file will replace the corresponding default argument in the launch script.
This can be used to avoid having to re-enter login credentials every time the program is launched.
Example config:
.. code-block:: ini
[rtv]
username=MyUsername
password=MySecretPassword
# Log file location
log=/tmp/rtv.log
# Default subreddit
subreddit=CollegeBasketball
# Default submission link - will be opened every time the program starts
# link=http://www.reddit.com/r/CollegeBasketball/comments/31irjq
# Turn on ascii-only mode and disable all unicode characters
# This may be necessary for compatibility with some terminal browsers
# ascii=True
=========
@@ -159,18 +199,17 @@ Description:
Please see `LICENSE <https://github.com/michael-lazar/rtv/blob/master/LICENSE>`_.
.. |python| image:: https://pypip.in/py_versions/rtv/badge.svg?style=flat-square
.. |python| image:: https://img.shields.io/badge/python-2.7%2C%203.4-blue.svg?style=flat-square
:target: https://pypi.python.org/pypi/rtv/
:alt: Supported Python versions
.. |pypi| image:: https://pypip.in/version/rtv/badge.svg?text=version&style=flat-square
.. |pypi| image:: https://img.shields.io/pypi/v/rtv.svg?label=version&style=flat-square
:target: https://pypi.python.org/pypi/rtv/
:alt: Latest Version
.. |downloads| image:: https://pypip.in/download/rtv/badge.svg?period=month&style=flat-square
.. |downloads| image:: https://img.shields.io/pypi/dm/rtv.svg?period=month&style=flat-square
:target: https://pypi.python.org/pypi/rtv/
:alt: Downloads
Keywords: reddit terminal praw curses
Platform: UNKNOWN
Classifier: Intended Audience :: End Users/Desktop

rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.2.2-py3.4.egg-info/SOURCES.txt → rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/SOURCES.txt View File

@@ -15,6 +15,7 @@ rtv/curses_helpers.py
rtv/docs.py
rtv/exceptions.py
rtv/helpers.py
rtv/history.py
rtv/page.py
rtv/submission.py
rtv/subreddit.py

rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.2.2-py3.4.egg-info/dependency_links.txt → rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/dependency_links.txt View File


rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.2.2-py3.4.egg-info/entry_points.txt → rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/entry_points.txt View File


rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.2.2-py3.4.egg-info/requires.txt → rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/requires.txt View File

@@ -1,3 +1,4 @@
praw>=2.1.6
six
requests
kitchen

rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.2.2-py3.4.egg-info/top_level.txt → rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv-1.4-py3.4.egg-info/top_level.txt View File


+ 8
- 7
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__main__.py View File

@@ -19,7 +19,6 @@ from .__version__ import __version__

__all__ = []


def load_config():
"""
Search for a configuration file at the location ~/.rtv and attempt to load
@@ -45,8 +44,8 @@ def load_config():
if config.has_section('rtv'):
defaults = dict(config.items('rtv'))

if 'unicode' in defaults:
defaults['unicode'] = config.getboolean('rtv', 'unicode')
if 'ascii' in defaults:
defaults['ascii'] = config.getboolean('rtv', 'ascii')

return defaults

@@ -60,8 +59,8 @@ def command_line():

parser.add_argument('-s', dest='subreddit', help='subreddit name')
parser.add_argument('-l', dest='link', help='full link to a submission')
parser.add_argument('--unicode', action='store_true',
help='enable unicode (experimental)')
parser.add_argument('--ascii', action='store_true',
help='enable ascii-only mode')
parser.add_argument('--log', metavar='FILE', action='store',
help='Log HTTP requests')

@@ -96,15 +95,17 @@ def main():
if getattr(args, key, None) is None:
setattr(args, key, val)

config.unicode = args.unicode
config.unicode = (not args.ascii)

# Squelch SSL warnings for Ubuntu
logging.captureWarnings(True)
if args.log:
logging.basicConfig(level=logging.DEBUG, filename=args.log)

try:
print('Connecting...')
reddit = praw.Reddit(user_agent=AGENT)
reddit.config.decode_html_entities = True
reddit.config.decode_html_entities = False
if args.username:
# PRAW will prompt for password if it is None
reddit.login(args.username, args.password)

BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/__main__.cpython-34.pyc View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/__main__.cpython-34.pyo View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/__version__.cpython-34.pyc View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/__version__.cpython-34.pyo View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/config.cpython-34.pyc View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/config.cpython-34.pyo View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/content.cpython-34.pyc View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/content.cpython-34.pyo View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/curses_helpers.cpython-34.pyc View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/curses_helpers.cpython-34.pyo View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/docs.cpython-34.pyc View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/docs.cpython-34.pyo View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/helpers.cpython-34.pyc View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/helpers.cpython-34.pyo View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/history.cpython-34.pyc View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/history.cpython-34.pyo View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/page.cpython-34.pyc View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/page.cpython-34.pyo View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/submission.cpython-34.pyc View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/submission.cpython-34.pyo View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/subreddit.cpython-34.pyc View File


BIN
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__pycache__/subreddit.cpython-34.pyo View File


+ 1
- 1
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/__version__.py View File

@@ -1 +1 @@
__version__ = '1.2.2'
__version__ = '1.4'

+ 1
- 1
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/config.py View File

@@ -2,4 +2,4 @@
Global configuration settings
"""

unicode = False
unicode = True

+ 42
- 24
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/content.py View File

@@ -1,4 +1,4 @@
import textwrap
import logging

import praw
import requests
@@ -8,6 +8,7 @@ from .helpers import humanize_timestamp, wrap_text, strip_subreddit_url

__all__ = ['SubredditContent', 'SubmissionContent']

_logger = logging.getLogger(__name__)

class BaseContent(object):

@@ -41,14 +42,22 @@ class BaseContent(object):
retval = []
while stack:
item = stack.pop(0)
if isinstance(item, praw.objects.MoreComments) and (
item.count == 0):
continue
nested = getattr(item, 'replies', None)
if nested:
for n in nested:
n.nested_level = item.nested_level + 1
stack[0:0] = nested
if isinstance(item, praw.objects.MoreComments):
if item.count == 0:
# MoreComments item count should never be zero, but if it
# is then discard the MoreComment object. Need to look into
# this further.
continue
else:
if item._replies is None:
# Attach children MoreComment replies to parents
# https://github.com/praw-dev/praw/issues/391
item._replies = [stack.pop(0)]
nested = getattr(item, 'replies', None)
if nested:
for n in nested:
n.nested_level = item.nested_level + 1
stack[0:0] = nested
retval.append(item)
return retval

@@ -68,18 +77,24 @@ class BaseContent(object):
data['count'] = comment.count
data['body'] = 'More comments'.format(comment.count)
else:
author = getattr(comment, 'author', '[deleted]')
name = getattr(author, 'name', '[deleted]')
sub = getattr(comment, 'submission', '[deleted]')
sub_author = getattr(sub, 'author', '[deleted]')
sub_name = getattr(sub_author, 'name', '[deleted]')
flair = getattr(comment, 'author_flair_text', '')
permalink = getattr(comment, 'permalink', None)

data['type'] = 'Comment'
data['body'] = comment.body
data['created'] = humanize_timestamp(comment.created_utc)
data['score'] = '{} pts'.format(comment.score)
author = getattr(comment, 'author')
data['author'] = (author.name if author else '[deleted]')
sub_author = getattr(comment.submission.author, 'name')
data['is_author'] = (data['author'] == sub_author)
flair = comment.author_flair_text
data['flair'] = (flair if flair else '')
data['author'] = name
data['is_author'] = (name == sub_name)
data['flair'] = flair
data['likes'] = comment.likes
data['gold'] = comment.gilded > 0
data['permalink'] = permalink

return data

@@ -91,6 +106,9 @@ class BaseContent(object):
"""

is_selfpost = lambda s: s.startswith('http://www.reddit.com/r/')
author = getattr(sub, 'author', '[deleted]')
name = getattr(author, 'name', '[deleted]')
flair = getattr(sub, 'link_flair_text', '')

data = {}
data['object'] = sub
@@ -100,15 +118,15 @@ class BaseContent(object):
data['created'] = humanize_timestamp(sub.created_utc)
data['comments'] = '{} comments'.format(sub.num_comments)
data['score'] = '{} pts'.format(sub.score)
author = getattr(sub, 'author')
data['author'] = (author.name if author else '[deleted]')
data['author'] = name
data['permalink'] = sub.permalink
data['subreddit'] = strip_subreddit_url(sub.permalink)
data['flair'] = (sub.link_flair_text if sub.link_flair_text else '')
data['flair'] = flair
data['url_full'] = sub.url
data['url'] = ('selfpost' if is_selfpost(sub.url) else sub.url)
data['likes'] = sub.likes
data['gold'] = sub.gilded > 0
data['nsfw'] = sub.over_18

return data

@@ -119,7 +137,7 @@ class SubmissionContent(BaseContent):
list for repeat access.
"""

def __init__(self, submission, loader, indent_size=2, max_indent_level=4):
def __init__(self, submission, loader, indent_size=2, max_indent_level=8):

self.indent_size = indent_size
self.max_indent_level = max_indent_level
@@ -132,7 +150,7 @@ class SubmissionContent(BaseContent):
self._comment_data = [self.strip_praw_comment(c) for c in comments]

@classmethod
def from_url(cls, reddit, url, loader, indent_size=2, max_indent_level=4):
def from_url(cls, reddit, url, loader, indent_size=2, max_indent_level=8):

try:
with loader():
@@ -153,8 +171,8 @@ class SubmissionContent(BaseContent):

elif index == -1:
data = self._submission_data
data['split_title'] = textwrap.wrap(data['title'], width=n_cols -2)
data['split_text'] = wrap_text(data['text'], width=n_cols - 2)
data['split_title'] = wrap_text(data['title'], width=n_cols-2)
data['split_text'] = wrap_text(data['text'], width=n_cols-2)
data['n_rows'] = len(data['split_title'] + data['split_text']) + 5
data['offset'] = 0

@@ -209,7 +227,7 @@ class SubmissionContent(BaseContent):

elif data['type'] == 'MoreComments':
with self._loader():
comments = data['object'].comments(update=False)
comments = data['object'].comments(update=True)
comments = self.flatten_comments(comments,
root_level=data['level'])
comment_data = [self.strip_praw_comment(c) for c in comments]
@@ -315,7 +333,7 @@ class SubredditContent(BaseContent):

# Modifies the original dict, faster than copying
data = self._submission_data[index]
data['split_title'] = textwrap.wrap(data['title'], width=n_cols)
data['split_title'] = wrap_text(data['title'], width=n_cols)
data['n_rows'] = len(data['split_title']) + 3
data['offset'] = 0


+ 88
- 11
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/curses_helpers.py View File

@@ -5,24 +5,76 @@ import curses
from curses import textpad, ascii
from contextlib import contextmanager

from . import config
from .docs import HELP
from .helpers import strip_textpad
from .helpers import strip_textpad, clean
from .exceptions import EscapeInterrupt

__all__ = ['ESCAPE', 'UARROW', 'DARROW', 'BULLET', 'show_notification',
'show_help', 'LoadScreen', 'Color', 'text_input', 'curses_session']
__all__ = ['ESCAPE', 'get_gold', 'show_notification', 'show_help',
'LoadScreen', 'Color', 'text_input', 'curses_session',
'prompt_input', 'add_line', 'get_arrow']

ESCAPE = 27

# Curses does define constants for these (e.g. curses.ACS_BULLET)
# Curses does define constants for symbols (e.g. curses.ACS_BULLET)
# However, they rely on using the curses.addch() function, which has been
# found to be buggy and a PITA to work with. By defining them as unicode
# points they can be added via the more reliable curses.addstr().
# http://bugs.python.org/issue21088
UARROW = u'\u25b2'.encode('utf-8')
DARROW = u'\u25bc'.encode('utf-8')
BULLET = u'\u2022'.encode('utf-8')
GOLD = u'\u272A'.encode('utf-8')
ESCAPE = 27

def get_gold():
"""
Return the guilded symbol.
"""

symbol = u'\u272A' if config.unicode else '*'
attr = curses.A_BOLD | Color.YELLOW
return symbol, attr

def get_arrow(likes):
"""
Return the vote symbol to display, based on the `likes` paramater.
"""

if likes is None:
symbol = u'\u2022' if config.unicode else 'o'
attr = curses.A_BOLD
elif likes:
symbol = u'\u25b2' if config.unicode else '^'
attr = curses.A_BOLD | Color.GREEN
else:
symbol = u'\u25bc' if config.unicode else 'v'
attr = curses.A_BOLD | Color.RED
return symbol, attr


def add_line(window, text, row=None, col=None, attr=None):
"""
Unicode aware version of curses's built-in addnstr method.

Safely draws a line of text on the window starting at position (row, col).
Checks the boundaries of the window and cuts off the text if it exceeds
the length of the window.
"""

# The following arg combinations must be supported to conform with addnstr
# (window, text)
# (window, text, attr)
# (window, text, row, col)
# (window, text, row, col, attr)

cursor_row, cursor_col = window.getyx()
row = row if row is not None else cursor_row
col = col if col is not None else cursor_col

max_rows, max_cols = window.getmaxyx()
n_cols = max_cols - col - 1
if n_cols <= 0:
# Trying to draw outside of the screen bounds
return

text = clean(text, n_cols)
params = [] if attr is None else [attr]
window.addstr(row, col, text, *params)


def show_notification(stdscr, message):
@@ -51,7 +103,7 @@ def show_notification(stdscr, message):
window.border()

for index, line in enumerate(message, start=1):
window.addnstr(index, 1, line, box_width - 2)
add_line(window, line, index, 1)
window.refresh()
ch = stdscr.getch()

@@ -235,6 +287,31 @@ def text_input(window, allow_resize=True):
return strip_textpad(out)


def prompt_input(window, prompt, hide=False):
"""
Display a prompt where the user can enter text at the bottom of the screen

Set hide to True to make the input text invisible.
"""

attr = curses.A_BOLD | Color.CYAN
n_rows, n_cols = window.getmaxyx()

if hide:
prompt += ' ' * (n_cols - len(prompt) - 1)
window.addstr(n_rows-1, 0, prompt, attr)
out = window.getstr(n_rows-1, 1)
else:
window.addstr(n_rows - 1, 0, prompt, attr)
window.refresh()
subwin = window.derwin(1, n_cols - len(prompt),
n_rows - 1, len(prompt))
subwin.attrset(attr)
out = text_input(subwin)

return out


@contextmanager
def curses_session():
"""

+ 29
- 18
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/docs.py View File

@@ -1,7 +1,7 @@
from .__version__ import __version__

__all__ = ['AGENT', 'SUMMARY', 'AUTH', 'CONTROLS', 'HELP', 'COMMENT_FILE',
'SUBMISSION_FILE']
'SUBMISSION_FILE', 'COMMENT_EDIT_FILE']

AGENT = """\
desktop:https://github.com/michael-lazar/rtv:{} (by /u/civilization_phaze_3)\
@@ -28,28 +28,32 @@ browse comments.
"""

HELP = """
Global Commands
`UP/DOWN` or `j/k` : Scroll to the prev/next item
`a/z` : Upvote/downvote the selected item
`ENTER` or `o` : Open the selected item in the default web browser
`r` : Refresh the current page
`u` : Login/logout of your user account
`?` : Show this help message
`q` : Quit the program
Basic Commands
`j/k` or `UP/DOWN` : Move the cursor up/down
`m/n` or `PgUp/PgDn`: Jump to the previous/next page
`o` or `ENTER` : Open the selected item as a webpage
`r` or `F5` : Refresh page content
`u` : Log in or switch accounts
`?` : Show the help screen
`q` : Quit

Authenticated Commands
`a/z` : Upvote/downvote
`c` : Compose a new post or comment
`e` : Edit an existing post or comment
`d` : Delete an existing post or comment

Subreddit Mode
`RIGHT` or `l` : View comments for the selected submission
`l` or `RIGHT` : Enter the selected submission
`/` : Open a prompt to switch subreddits
`f` : Open a prompt to search the current subreddit
`p` : Post a new submission to the current subreddit

Submission Mode
`LEFT` or `h` : Return to subreddit mode
`RIGHT` or `l` : Fold the selected comment, or load additional comments
`c` : Post a new comment on the selected item
`h` or `LEFT` : Return to subreddit mode
`SPACE` : Fold the selected comment, or load additional comments
"""

COMMENT_FILE = """
COMMENT_FILE = u"""
# Please enter a comment. Lines starting with '#' will be ignored,
# and an empty message aborts the comment.
#
@@ -57,12 +61,19 @@ COMMENT_FILE = """
{content}
"""

SUBMISSION_FILE = """
COMMENT_EDIT_FILE = u"""{content}
# Please enter a comment. Lines starting with '#' will be ignored,
# and an empty message aborts the comment.
#
# Editing your comment
"""

SUBMISSION_FILE = u"""{content}
# Please enter your submission. Lines starting with '#' will be ignored,
# and an empty field aborts the submission.
#
# The first line will be interpreted as the title
# The following lines will be interpreted as the content
#
# Posting to /r/{name}
"""
# Posting to {name}
"""

+ 78
- 33
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/helpers.py View File

@@ -1,16 +1,53 @@
import sys
import os
import textwrap
import curses
import webbrowser
import subprocess
from datetime import datetime
from tempfile import NamedTemporaryFile

# kitchen solves deficiencies in textwrap's handling of unicode characters
from kitchen.text.display import wrap, textual_width_chop
import six

from . import config
from .exceptions import ProgramError

__all__ = ['open_browser', 'clean', 'wrap_text', 'strip_textpad',
'strip_subreddit_url', 'humanize_timestamp', 'open_editor']

def clean(string, n_cols=None):
"""
Required reading!
http://nedbatchelder.com/text/unipain.html

Python 2 input string will be a unicode type (unicode code points). Curses
will accept unicode if all of the points are in the ascii range. However, if
any of the code points are not valid ascii curses will throw a
UnicodeEncodeError: 'ascii' codec can't encode character, ordinal not in
range(128). If we encode the unicode to a utf-8 byte string and pass that to
curses, it will render correctly.

Python 3 input string will be a string type (unicode code points). Curses
will accept that in all cases. However, the n character count in addnstr
will not be correct. If code points are passed to addnstr, curses will treat
each code point as one character and will not account for wide characters.
If utf-8 is passed in, addnstr will treat each 'byte' as a single character.
"""

if n_cols is not None and n_cols <= 0:
return ''

if not config.unicode:
if six.PY3 or isinstance(string, unicode):
string = string.encode('ascii', 'replace')
return string[:n_cols] if n_cols else string
else:
if n_cols:
string = textual_width_chop(string, n_cols)
if six.PY3 or isinstance(string, unicode):
string = string.encode('utf-8')
return string

def open_editor(data=''):
"""
@@ -21,15 +58,17 @@ def open_editor(data=''):
read and and lines starting with '#' will be stripped.
"""

with NamedTemporaryFile(prefix='rtv-', suffix='.txt', mode='w') as fp:
fp.write(data)
with NamedTemporaryFile(prefix='rtv-', suffix='.txt', mode='wb') as fp:
fp.write(clean(data))
fp.flush()
editor = os.getenv('RTV_EDITOR') or os.getenv('EDITOR') or 'nano'

curses.endwin()
try:
subprocess.Popen([editor, fp.name]).wait()
except OSError as e:
raise ProgramError(editor)
curses.doupdate()

# Open a second file object to read. This appears to be necessary in
# order to read the changes made by some editors (gedit). w+ mode does
@@ -43,41 +82,47 @@ def open_editor(data=''):

def open_browser(url):
"""
Call webbrowser.open_new_tab(url) and redirect stdout/stderr to devnull.

This is a workaround to stop firefox from spewing warning messages to the
console. See http://bugs.python.org/issue22277 for a better description
of the problem.
Open the given url using the default webbrowser. The preferred browser can
specified with the $BROWSER environment variable. If not specified, python
webbrowser will try to determine the default to use based on your system.

For browsers requiring an X display, we call webbrowser.open_new_tab(url)
and redirect stdout/stderr to devnull. This is a workaround to stop firefox
from spewing warning messages to the console. See
http://bugs.python.org/issue22277 for a better description of the problem.

For console browsers (e.g. w3m), RTV will suspend and display the browser
window within the same terminal. This mode is triggered either when
1. $BROWSER is set to a known console browser, or
2. $DISPLAY is undefined, indicating that the terminal is running headless

There may be other cases where console browsers are opened (xdg-open?) but
are not detected here.
"""
command = "import webbrowser; webbrowser.open_new_tab('%s')" % url
args = [sys.executable, '-c', command]
with open(os.devnull, 'ab+', 0) as null:
subprocess.check_call(args, stdout=null, stderr=null)

console_browsers = ['www-browser', 'links', 'links2', 'elinks', 'lynx', 'w3m']

def clean(string):
"""
Required reading!
http://nedbatchelder.com/text/unipain.html

Python 2 input string will be a unicode type (unicode code points). Curses
will accept unicode if all of the points are in the ascii range. However, if
any of the code points are not valid ascii curses will throw a
UnicodeEncodeError: 'ascii' codec can't encode character, ordinal not in
range(128). If we encode the unicode to a utf-8 byte string and pass that to
curses, it will render correctly.
display = bool(os.environ.get("DISPLAY"))

Python 3 input string will be a string type (unicode code points). Curses
will accept that in all cases. However, the n character count in addnstr
will not be correct. If code points are passed to addnstr, curses will treat
each code point as one character and will not account for wide characters.
If utf-8 is passed in, addnstr will treat each 'byte' as a single character.
"""
# Use the convention defined here to parse $BROWSER
# https://docs.python.org/2/library/webbrowser.html
if "BROWSER" in os.environ:
user_browser = os.environ["BROWSER"].split(os.pathsep)[0]
if user_browser in console_browsers:
display = False

encoding = 'utf-8' if config.unicode else 'ascii'
string = string.encode(encoding, 'replace')
return string
if webbrowser._tryorder and webbrowser._tryorder[0] in console_browsers:
display = False

if display:
command = "import webbrowser; webbrowser.open_new_tab('%s')" % url
args = [sys.executable, '-c', command]
with open(os.devnull, 'ab+', 0) as null:
subprocess.check_call(args, stdout=null, stderr=null)
else:
curses.endwin()
webbrowser.open_new_tab(url)
curses.doupdate()

def wrap_text(text, width):
"""
@@ -87,7 +132,7 @@ def wrap_text(text, width):
for paragraph in text.splitlines():
# Wrap returns an empty list when paragraph is a newline. In order to
# preserve newlines we substitute a list containing an empty string.
lines = textwrap.wrap(paragraph, width=width) or ['']
lines = wrap(paragraph, width=width) or ['']
out.extend(lines)
return out


+ 68
- 0
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/history.py View File

@@ -0,0 +1,68 @@
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')
if not os.path.exists(path):
os.makedirs(path)
return os.path.join(path, 'history.log')


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:
# reverse the list so the newest ones are first
history = [line.strip() for line in history_file][::-1]
return OrderedSet(history)
return OrderedSet()


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
try:
history_file.write(history.pop() + '\n')
except UnicodeEncodeError:
# Ignore unicode URLS, may want to handle this at some point
continue

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

+ 218
- 47
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/page.py View File

@@ -1,15 +1,22 @@
import curses
import time
import six
import sys
import logging
from contextlib import contextmanager

import praw.errors
import requests
from kitchen.text.display import textual_width

from .helpers import clean
from .curses_helpers import Color, show_notification, show_help, text_input
from .docs import AGENT
from .helpers import open_editor
from .curses_helpers import (Color, show_notification, show_help, text_input,
prompt_input, add_line)
from .docs import COMMENT_EDIT_FILE, SUBMISSION_FILE

__all__ = ['Navigator']
__all__ = ['Navigator', 'BaseController', 'BasePage']

_logger = logging.getLogger(__name__)

class Navigator(object):
"""
@@ -84,6 +91,53 @@ class Navigator(object):

return valid, redraw

def move_page(self, direction, n_windows):
"""
Move page down (positive direction) or up (negative direction).
"""

# top of subreddit/submission page or only one
# submission/reply on the screen: act as normal move
if (self.absolute_index < 0) | (n_windows == 0):
valid, redraw = self.move(direction, n_windows)
else:
# first page
if self.absolute_index < n_windows and direction < 0:
self.page_index = -1
self.cursor_index = 0
self.inverted = False

# not submission mode: starting index is 0
if not self._is_valid(self.absolute_index):
self.page_index = 0
valid = True
else:
# flip to the direction of movement
if ((direction > 0) & (self.inverted is True))\
| ((direction < 0) & (self.inverted is False)):
self.page_index += (self.step * (n_windows-1))
self.inverted = not self.inverted
self.cursor_index \
= (n_windows-(direction<0)) - self.cursor_index

valid = False
adj = 0
# check if reached the bottom
while not valid:
n_move = n_windows - adj
if n_move == 0:
break

self.page_index += n_move * direction
valid = self._is_valid(self.absolute_index)
if not valid:
self.page_index -= n_move * direction
adj += 1

redraw = True

return valid, redraw

def flip(self, n_windows):
"Flip the orientation of the page"

@@ -101,6 +155,36 @@ class Navigator(object):
else:
return True

class SafeCaller(object):

def __init__(self, window):
self.window = window
self.catch = True

def __enter__(self):
return self

def __exit__(self, exc_type, e, exc_tb):

if self.catch:
if isinstance(e, praw.errors.APIException):
message = ['Error: {}'.format(e.error_type), e.message]
show_notification(self.window, message)
_logger.exception(e)
return True
elif isinstance(e, praw.errors.ClientException):
message = ['Error: Client Exception', e.message]
show_notification(self.window, message)
_logger.exception(e)
return True
elif isinstance(e, requests.HTTPError):
show_notification(self.window, ['Unexpected Error'])
_logger.exception(e)
return True
elif isinstance(e, requests.ConnectionError):
show_notification(self.window, ['Unexpected Error'])
_logger.exception(e)
return True

class BaseController(object):
"""
@@ -170,6 +254,13 @@ class BasePage(object):
self._content_window = None
self._subwindows = None

def refresh_content(self):
raise NotImplementedError

@staticmethod
def draw_item(window, data, inverted):
raise NotImplementedError

@BaseController.register('q')
def exit(self):
sys.exit()
@@ -188,13 +279,15 @@ class BasePage(object):
self._move_cursor(1)
self.clear_input_queue()

def clear_input_queue(self):
"Clear excessive input caused by the scroll wheel or holding down a key"
@BaseController.register('n', curses.KEY_NPAGE)
def move_page_down(self):
self._move_page(1)
self.clear_input_queue()

self.stdscr.nodelay(1)
while self.stdscr.getch() != -1:
continue
self.stdscr.nodelay(0)
@BaseController.register('m', curses.KEY_PPAGE)
def move_page_up(self):
self._move_page(-1)
self.clear_input_queue()

@BaseController.register('a')
def upvote(self):
@@ -237,49 +330,120 @@ class BasePage(object):
self.logout()
return

username = self.prompt_input('Enter username:')
password = self.prompt_input('Enter password:', hide=True)
username = prompt_input(self.stdscr, 'Enter username:')
password = prompt_input(self.stdscr, 'Enter password:', hide=True)
if not username or not password:
curses.flash()
return

try:
with self.loader():
with self.loader(message='Logging in'):
self.reddit.login(username, password)
except praw.errors.InvalidUserPass:
show_notification(self.stdscr, ['Invalid user/pass'])
else:
show_notification(self.stdscr, ['Welcome {}'.format(username)])

@BaseController.register('d')
def delete(self):
"""
Delete a submission or comment.
"""

if not self.reddit.is_logged_in():
show_notification(self.stdscr, ['Not logged in'])
return

data = self.content.get(self.nav.absolute_index)
if data.get('author') != self.reddit.user.name:
curses.flash()
return

prompt = 'Are you sure you want to delete this? (y/n):'
char = prompt_input(self.stdscr, prompt)
if char != 'y':
show_notification(self.stdscr, ['Aborted'])
return

with self.safe_call as s:
with self.loader(message='Deleting', delay=0):
data['object'].delete()
time.sleep(2.0)
s.catch = False
self.refresh_content()

@BaseController.register('e')
def edit(self):
"""
Edit a submission or comment.
"""

if not self.reddit.is_logged_in():
show_notification(self.stdscr, ['Not logged in'])
return

data = self.content.get(self.nav.absolute_index)
if data.get('author') != self.reddit.user.name:
curses.flash()
return

if data['type'] == 'Submission':
subreddit = self.reddit.get_subreddit(self.content.name)
content = data['text']
info = SUBMISSION_FILE.format(content=content, name=subreddit)
elif data['type'] == 'Comment':
content = data['body']
info = COMMENT_EDIT_FILE.format(content=content)
else:
curses.flash()
return

text = open_editor(info)
if text == content:
show_notification(self.stdscr, ['Aborted'])
return

with self.safe_call as s:
with self.loader(message='Editing', delay=0):
data['object'].edit(text)
time.sleep(2.0)
s.catch = False
self.refresh_content()

def clear_input_queue(self):
"Clear excessive input caused by the scroll wheel or holding down a key"

self.stdscr.nodelay(1)
while self.stdscr.getch() != -1:
continue
self.stdscr.nodelay(0)

def logout(self):
"Prompt to log out of the user's account."

ch = self.prompt_input("Log out? (y/n):")
ch = prompt_input(self.stdscr, "Log out? (y/n):")
if ch == 'y':
self.reddit.clear_authentication()
show_notification(self.stdscr, ['Logged out'])
elif ch != 'n':
curses.flash()

def prompt_input(self, prompt, hide=False):
"Prompt the user for input"

attr = curses.A_BOLD | Color.CYAN
n_rows, n_cols = self.stdscr.getmaxyx()

if hide:
prompt += ' ' * (n_cols - len(prompt) - 1)
self.stdscr.addstr(n_rows-1, 0, prompt, attr)
out = self.stdscr.getstr(n_rows-1, 1)
else:
self.stdscr.addstr(n_rows - 1, 0, prompt, attr)
self.stdscr.refresh()
window = self.stdscr.derwin(1, n_cols - len(prompt),
n_rows - 1, len(prompt))
window.attrset(attr)
out = text_input(window)

return out
@property
def safe_call(self):
"""
Wrap praw calls with extended error handling.
If a PRAW related error occurs inside of this context manager, a
notification will be displayed on the screen instead of the entire
application shutting down. This function will return a callback that
can be used to check the status of the call.

Usage:
#>>> with self.safe_call as s:
#>>> self.reddit.submit(...)
#>>> s.catch = False
#>>> on_success()
"""
return SafeCaller(self.stdscr)

def draw(self):

@@ -296,10 +460,6 @@ class BasePage(object):
self._draw_content()
self._add_cursor()

@staticmethod
def draw_item(window, data, inverted):
raise NotImplementedError

def _draw_header(self):

n_rows, n_cols = self._header_window.getmaxyx()
@@ -309,16 +469,14 @@ class BasePage(object):
self._header_window.bkgd(' ', attr)

sub_name = self.content.name.replace('/r/front', 'Front Page ')
self._header_window.addnstr(0, 0, clean(sub_name), n_cols - 1)
add_line(self._header_window, sub_name, 0, 0)

if self.reddit.user is not None:
username = self.reddit.user.name
s_col = (n_cols - len(username) - 1)
# Only print the username if it fits in the empty space on the
# right
if (s_col - 1) >= len(sub_name):
n = (n_cols - s_col - 1)
self._header_window.addnstr(0, s_col, clean(username), n)
s_col = (n_cols - textual_width(username) - 1)
# Only print username if it fits in the empty space on the right
if (s_col - 1) >= textual_width(sub_name):
add_line(self._header_window, username, 0, s_col)

self._header_window.refresh()

@@ -370,15 +528,22 @@ class BasePage(object):
self._edit_cursor(curses.A_NORMAL)

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)
if not valid:
curses.flash()

# Note: ACS_VLINE doesn't like changing the attribute, so always redraw.
self._draw_content()
self._add_cursor()

@@ -388,6 +553,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

+ 53
- 64
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/submission.py View File

@@ -7,8 +7,8 @@ import praw.errors

from .content import SubmissionContent
from .page import BasePage, Navigator, BaseController
from .helpers import clean, open_browser, open_editor
from .curses_helpers import (BULLET, UARROW, DARROW, GOLD, Color, LoadScreen,
from .helpers import open_browser, open_editor
from .curses_helpers import (Color, LoadScreen, get_arrow, get_gold, add_line,
show_notification, text_input)
from .docs import COMMENT_FILE

@@ -45,7 +45,7 @@ class SubmissionPage(BasePage):
cmd = self.stdscr.getch()
self.controller.trigger(cmd)

@SubmissionController.register(curses.KEY_RIGHT, 'l')
@SubmissionController.register(curses.KEY_RIGHT, 'l', ' ')
def toggle_comment(self):
"Toggle the selected comment tree between visible and hidden"

@@ -77,9 +77,12 @@ class SubmissionPage(BasePage):
def open_link(self):
"Open the current submission page with the webbrowser"

# May want to expand at some point to open comment permalinks
url = self.content.get(-1)['permalink']
open_browser(url)
data = self.content.get(self.nav.absolute_index)
url = data.get('permalink')
if url:
open_browser(url)
else:
curses.flash()

@SubmissionController.register('c')
def add_comment(self):
@@ -89,7 +92,7 @@ class SubmissionPage(BasePage):
"""

if not self.reddit.is_logged_in():
show_notification(self.stdscr, ['Login to post'])
show_notification(self.stdscr, ['Not logged in'])
return

data = self.content.get(self.nav.absolute_index)
@@ -108,30 +111,30 @@ class SubmissionPage(BasePage):
type=data['type'].lower(),
content=content)

curses.endwin()
comment_text = open_editor(comment_info)
curses.doupdate()
if not comment_text:
show_notification(self.stdscr, ['Comment canceled'])
show_notification(self.stdscr, ['Aborted'])
return

try:
if data['type'] == 'Submission':
data['object'].add_comment(comment_text)
else:
data['object'].reply(comment_text)
except praw.errors.APIException as e:
message = ['Error: {}'.format(e.error_type), e.message]
show_notification(self.stdscr, message)
_logger.exception(e)
except requests.HTTPError as e:
show_notification(self.stdscr, ['Unexpected Error'])
_logger.exception(e)
else:
with self.loader(delay=0, message='Posting'):
with self.safe_call as s:
with self.loader(message='Posting', delay=0):
if data['type'] == 'Submission':
data['object'].add_comment(comment_text)
else:
data['object'].reply(comment_text)
time.sleep(2.0)
s.catch = False
self.refresh_content()

@SubmissionController.register('d')
def delete_comment(self):
"Delete a comment as long as it is not the current submission"

if self.nav.absolute_index != -1:
self.delete()
else:
curses.flash()

def draw_item(self, win, data, inverted=False):

if data['type'] == 'MoreComments':
@@ -156,36 +159,26 @@ class SubmissionPage(BasePage):
row = offset
if row in valid_rows:

text = clean(u'{author} '.format(**data))
attr = curses.A_BOLD
attr |= (Color.BLUE if not data['is_author'] else Color.GREEN)
win.addnstr(row, 1, text, n_cols - 1, attr)
add_line(win, u'{author} '.format(**data), row, 1, attr)

if data['flair']:
text = clean(u'{flair} '.format(**data))
attr = curses.A_BOLD | Color.YELLOW
win.addnstr(text, n_cols - win.getyx()[1], attr)

if data['likes'] is None:
text, attr = BULLET, curses.A_BOLD
elif data['likes']:
text, attr = UARROW, (curses.A_BOLD | Color.GREEN)
else:
text, attr = DARROW, (curses.A_BOLD | Color.RED)
win.addnstr(text, n_cols - win.getyx()[1], attr)
add_line(win, u'{flair} '.format(**data), attr=attr)

text = clean(u' {score} {created} '.format(**data))
win.addnstr(text, n_cols - win.getyx()[1])
text, attr = get_arrow(data['likes'])
add_line(win, text, attr=attr)
add_line(win, u' {score} {created} '.format(**data))

if data['gold']:
text, attr = GOLD, (curses.A_BOLD | Color.YELLOW)
win.addnstr(text, n_cols - win.getyx()[1], attr)
text, attr = get_gold()
add_line(win, text, attr=attr)

n_body = len(data['split_body'])
for row, text in enumerate(data['split_body'], start=offset + 1):
if row in valid_rows:
text = clean(text)
win.addnstr(row, 1, text, n_cols - 1)
add_line(win, text, row, 1)

# Unfortunately vline() doesn't support custom color so we have to
# build it one segment at a time.
@@ -208,13 +201,9 @@ class SubmissionPage(BasePage):
n_rows, n_cols = win.getmaxyx()
n_cols -= 1

text = clean(u'{body}'.format(**data))
win.addnstr(0, 1, text, n_cols - 1)
text = clean(u' [{count}]'.format(**data))
win.addnstr(text, n_cols - win.getyx()[1], curses.A_BOLD)
add_line(win, u'{body}'.format(**data), 0, 1)
add_line(win, u' [{count}]'.format(**data), attr=curses.A_BOLD)

# Unfortunately vline() doesn't support custom color so we have to
# build it one segment at a time.
attr = Color.get_level(data['level'])
win.addch(0, 0, curses.ACS_VLINE, attr)

@@ -227,23 +216,18 @@ class SubmissionPage(BasePage):
n_cols -= 3 # one for each side of the border + one for offset

for row, text in enumerate(data['split_title'], start=1):
text = clean(text)
win.addnstr(row, 1, text, n_cols, curses.A_BOLD)
add_line(win, text, row, 1, curses.A_BOLD)

row = len(data['split_title']) + 1
attr = curses.A_BOLD | Color.GREEN
text = clean(u'{author}'.format(**data))
win.addnstr(row, 1, text, n_cols, attr)
add_line(win, u'{author}'.format(**data), row, 1, attr)
attr = curses.A_BOLD | Color.YELLOW
text = clean(u' {flair}'.format(**data))
win.addnstr(text, n_cols - win.getyx()[1], attr)
text = clean(u' {created} {subreddit}'.format(**data))
win.addnstr(text, n_cols - win.getyx()[1])
add_line(win, u' {flair}'.format(**data), attr=attr)
add_line(win, u' {created} {subreddit}'.format(**data))

row = len(data['split_title']) + 2
attr = curses.A_UNDERLINE | Color.BLUE
text = clean(u'{url}'.format(**data))
win.addnstr(row, 1, text, n_cols, attr)
add_line(win, u'{url}'.format(**data), row, 1, attr)
offset = len(data['split_title']) + 3

# Cut off text if there is not enough room to display the whole post
@@ -254,15 +238,20 @@ class SubmissionPage(BasePage):
split_text.append('(Not enough space to display)')

for row, text in enumerate(split_text, start=offset):
text = clean(text)
win.addnstr(row, 1, text, n_cols)
add_line(win, text, row, 1)

row = len(data['split_title']) + len(split_text) + 3
text = clean(u'{score} {comments} '.format(**data))
win.addnstr(row, 1, text, n_cols, curses.A_BOLD)
add_line(win, u'{score} '.format(**data), row, 1)
text, attr = get_arrow(data['likes'])
add_line(win, text, attr=attr)
add_line(win, u' {comments} '.format(**data))

if data['gold']:
text, attr = GOLD, (curses.A_BOLD | Color.YELLOW)
win.addnstr(text, n_cols - win.getyx()[1], attr)
text, attr = get_gold()
add_line(win, text, attr=attr)

if data['nsfw']:
text, attr = 'NSFW', (curses.A_BOLD | Color.RED)
add_line(win, text, attr=attr)

win.border()

+ 46
- 55
rtv-git/pkg/rtv-git/usr/lib/python3.4/site-packages/rtv/subreddit.py View File

@@ -1,6 +1,7 @@
import curses
import time
import logging
import atexit

import requests
import praw
@@ -9,17 +10,22 @@ from .exceptions import SubredditError, AccountError
from .page import BasePage, Navigator, BaseController
from .submission import SubmissionPage
from .content import SubredditContent
from .helpers import clean, open_browser, open_editor
from .helpers import open_browser, open_editor
from .docs import SUBMISSION_FILE
from .curses_helpers import (BULLET, UARROW, DARROW, GOLD, Color,
LoadScreen, show_notification)
from .history import load_history, save_history
from .curses_helpers import (Color, LoadScreen, add_line, get_arrow, get_gold,
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):
@@ -67,7 +73,7 @@ class SubredditPage(BasePage):

name = name or self.content.name
prompt = 'Search {}:'.format(name)
query = self.prompt_input(prompt)
query = prompt_input(self.stdscr, prompt)
if query is None:
return

@@ -83,7 +89,7 @@ class SubredditPage(BasePage):
def prompt_subreddit(self):
"Open a prompt to navigate to a different subreddit"
prompt = 'Enter Subreddit: /r/'
name = self.prompt_input(prompt)
name = prompt_input(self.stdscr, prompt)
if name is not None:
self.refresh_content(name=name)

@@ -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,15 +112,15 @@ 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')
@SubredditController.register('c')
def post_submission(self):
"Post a new submission to the given subreddit"

if not self.reddit.is_logged_in():
show_notification(self.stdscr, ['Login to post'])
show_notification(self.stdscr, ['Not logged in'])
return

# Strips the subreddit to just the name
@@ -126,33 +132,28 @@ class SubredditPage(BasePage):
return

# Open the submission window
submission_info = SUBMISSION_FILE.format(name=sub)
submission_info = SUBMISSION_FILE.format(name=subreddit, content='')
curses.endwin()
submission_text = open_editor(submission_info)
curses.doupdate()

# Validate the submission content
if not submission_text:
show_notification(self.stdscr, ['Post canceled'])
show_notification(self.stdscr, ['Aborted'])
return

if '\n' not in submission_text:
show_notification(self.stdscr, ['No content'])
return

try:
title, content = submission_text.split('\n', 1)
self.reddit.submit(sub, title, text=content)
except praw.errors.APIException as e:
message = ['Error: {}'.format(e.error_type), e.message]
show_notification(self.stdscr, message)
_logger.exception(e)
except requests.HTTPError as e:
show_notification(self.stdscr, ['Unexpected Error'])
_logger.exception(e)
else:
with self.loader(delay=0, message='Posting'):
title, content = submission_text.split('\n', 1)
with self.safe_call as s:
with self.loader(message='Posting', delay=0):
post = self.reddit.submit(sub, title, text=content)
time.sleep(2.0)
# Open the newly created post
s.catch = False
page = SubmissionPage(self.stdscr, self.reddit, submission=post)
page.loop()
self.refresh_content()

@staticmethod
@@ -168,42 +169,32 @@ class SubredditPage(BasePage):
n_title = len(data['split_title'])
for row, text in enumerate(data['split_title'], start=offset):
if row in valid_rows:
text = clean(text)
win.addnstr(row, 1, text, n_cols - 1, curses.A_BOLD)
add_line(win, text, row, 1, curses.A_BOLD)

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))
win.addnstr(row, 1, text, n_cols - 1, attr)
add_line(win, u'{url}'.format(**data), row, 1, attr)

row = n_title + offset + 1
if row in valid_rows:
text = clean(u'{score} '.format(**data))
win.addnstr(row, 1, text, n_cols - 1)

if data['likes'] is None:
text, attr = BULLET, curses.A_BOLD
elif data['likes']:
text, attr = UARROW, curses.A_BOLD | Color.GREEN
else:
text, attr = DARROW, curses.A_BOLD | Color.RED
win.addnstr(text, n_cols - win.getyx()[1], attr)

text = clean(u' {created} {comments} '.format(**data))
win.addnstr(text, n_cols - win.getyx()[1])
add_line(win, u'{score} '.format(**data), row, 1)
text, attr = get_arrow(data['likes'])
add_line(win, text, attr=attr)
add_line(win, u' {created} {comments} '.format(**data))

if data['gold']:
text, attr = GOLD, (curses.A_BOLD | Color.YELLOW)
win.addnstr(text, n_cols - win.getyx()[1], attr)
text, attr = get_gold()
add_line(win, text, attr=attr)

if data['nsfw']:
text, attr = 'NSFW', (curses.A_BOLD | Color.RED)
add_line(win, text, attr=attr)

row = n_title + offset + 2
if row in valid_rows:
text = clean(u'{author}'.format(**data))
win.addnstr(row, 1, text, n_cols - 1, curses.A_BOLD)
text = clean(u' {subreddit}'.format(**data))
win.addnstr(text, n_cols - win.getyx()[1], Color.YELLOW)
text = clean(u' {flair}'.format(**data))
win.addnstr(text, n_cols - win.getyx()[1], Color.RED)
add_line(win, u'{author}'.format(**data), row, 1, curses.A_BOLD)
add_line(win, u' {subreddit}'.format(**data), attr=Color.YELLOW)
add_line(win, u' {flair}'.format(**data), attr=Color.RED)

BIN
rtv-git/rtv-git-r345.2a93592-1-any.pkg.tar.xz View File


BIN
rtv-git/rtv-git-r345.2a93592-1.src.tar.gz View File


+ 15
- 3
rtv-git/rtv/FETCH_HEAD View File

@@ -1,7 +1,12 @@
fa63247f5fc1ff5e7a291e85a8e7959c8d8a1027 not-for-merge branch 'Brobin-edit_delete' of https://github.com/michael-lazar/rtv
c4d97f939fad823f6575a9e812f3dc54fad3ad5b not-for-merge branch 'controller' of https://github.com/michael-lazar/rtv
9153fdd20f2e05edecebd056c2c9aaaf29f97df3 not-for-merge branch 'master' of https://github.com/michael-lazar/rtv
2a935922bf9b97cc2358a35963c0b4dada7a9f6c not-for-merge branch 'master' of https://github.com/michael-lazar/rtv
5146244c26a979e38c59adc42ce89834d45512cd not-for-merge branch 'morecomment-speed' of https://github.com/michael-lazar/rtv
d5f68215cdbc5906c19a64c0bab2e3b737a9bb29 not-for-merge branch 'pypi' of https://github.com/michael-lazar/rtv
bf2d464081f64412a90ec67439b055c51499baed not-for-merge branch 'unicode_kitchen' of https://github.com/michael-lazar/rtv
7c7606d288b0ec306577cb1c79b3ea9cb90e4caf not-for-merge 'refs/pull/1/head' of https://github.com/michael-lazar/rtv
2842a829a1881e55ee58134480bca46df799eda3 not-for-merge 'refs/pull/106/head' of https://github.com/michael-lazar/rtv
dbd9fd44fe9938bd823f9a53441c96559af54ed8 not-for-merge 'refs/pull/106/merge' of https://github.com/michael-lazar/rtv
98fc02e28e0147509ddfe4e601a97859a0e47cfc not-for-merge 'refs/pull/11/head' of https://github.com/michael-lazar/rtv
6a5da9f1ec1305ce2fdf4a1e3ec3f90afc6772cb not-for-merge 'refs/pull/13/head' of https://github.com/michael-lazar/rtv
9fcb16b3e48467566140db4a37817cbe82116eb9 not-for-merge 'refs/pull/14/head' of https://github.com/michael-lazar/rtv
@@ -52,8 +57,15 @@ a294010e27568460f65d556709a1cfb1c5df5dc5 not-for-merge 'refs/pull/73/head' of ht
4b326cf218292910a98db62a66edc488d71efba0 not-for-merge 'refs/pull/74/head' of https://github.com/michael-lazar/rtv
b0124560be42f7c4f85ffb7d467dff7b2ac63cf3 not-for-merge 'refs/pull/75/head' of https://github.com/michael-lazar/rtv
161fe186dd4d83248d7a50513030c747be3a67ba not-for-merge 'refs/pull/79/head' of https://github.com/michael-lazar/rtv
f31ad72f921f84d31ab664c4e53366af7eef57fd not-for-merge 'refs/pull/83/head' of https://github.com/michael-lazar/rtv
02e82686c977ecceafeed878dce1ca0832d658f8 not-for-merge 'refs/pull/83/merge' of https://github.com/michael-lazar/rtv
68ae4570dc98d9854a1891e094fd609e1275950c not-for-merge 'refs/pull/83/head' of https://github.com/michael-lazar/rtv
6025fc24c40a2200b613e7ce6efdd24ee5b56e4f not-for-merge 'refs/pull/86/head' of https://github.com/michael-lazar/rtv
9edbd9317f983f30a001f667a9d162f8790447fb not-for-merge 'refs/pull/87/head' of https://github.com/michael-lazar/rtv
bdd55d3da2683dc07842f9d2b451ae23ebf57dc2 not-for-merge 'refs/pull/92/head' of https://github.com/michael-lazar/rtv
15f15c9302aa96759028c457f3b6b8b87371336d not-for-merge 'refs/pull/95/head' of https://github.com/michael-lazar/rtv
794e2972949066f3a0961b3cb639b743715c9cd5 not-for-merge 'refs/pull/97/head' of https://github.com/michael-lazar/rtv
30eaa7521d4594ecbc29a289efa101903fd3306a not-for-merge 'refs/pull/97/merge' of https://github.com/michael-lazar/rtv
6036d90e127e1f0fe96ecff31957b7c30946d2d7 not-for-merge tag 'v1.2' of https://github.com/michael-lazar/rtv
f9f955deb0150cca26250754132f547237811451 not-for-merge tag 'v1.2.1' of https://github.com/michael-lazar/rtv
9153fdd20f2e05edecebd056c2c9aaaf29f97df3 not-for-merge tag 'v1.2.2' of https://github.com/michael-lazar/rtv
ff0e9bc6770d59cab830084ca142b0e26e32dbdc not-for-merge tag 'v1.3' of https://github.com/michael-lazar/rtv
2a935922bf9b97cc2358a35963c0b4dada7a9f6c not-for-merge tag 'v1.4' of https://github.com/michael-lazar/rtv

BIN
rtv-git/rtv/objects/pack/pack-d2b6062f1840e56ceb1df98ec97bcfab9ca37062.idx View File


BIN
rtv-git/rtv/objects/pack/pack-d2b6062f1840e56ceb1df98ec97bcfab9ca37062.pack View File


+ 1
- 0
rtv-git/rtv/refs/heads/Brobin-edit_delete View File

@@ -0,0 +1 @@
fa63247f5fc1ff5e7a291e85a8e7959c8d8a1027

+ 1
- 1
rtv-git/rtv/refs/heads/master View File

@@ -1 +1 @@
9153fdd20f2e05edecebd056c2c9aaaf29f97df3
2a935922bf9b97cc2358a35963c0b4dada7a9f6c

+ 1
- 0
rtv-git/rtv/refs/heads/morecomment-speed View File

@@ -0,0 +1 @@
5146244c26a979e38c59adc42ce89834d45512cd

+ 1
- 0
rtv-git/rtv/refs/heads/unicode_kitchen View File

@@ -0,0 +1 @@
bf2d464081f64412a90ec67439b055c51499baed

+ 1
- 0
rtv-git/rtv/refs/pull/106/head View File

@@ -0,0 +1 @@
2842a829a1881e55ee58134480bca46df799eda3

+ 1
- 0
rtv-git/rtv/refs/pull/106/merge View File

@@ -0,0 +1 @@
dbd9fd44fe9938bd823f9a53441c96559af54ed8

+ 1
- 1
rtv-git/rtv/refs/pull/83/head View File

@@ -1 +1 @@
f31ad72f921f84d31ab664c4e53366af7eef57fd
68ae4570dc98d9854a1891e094fd609e1275950c

+ 0
- 1
rtv-git/rtv/refs/pull/83/merge View File

@@ -1 +0,0 @@
02e82686c977ecceafeed878dce1ca0832d658f8

+ 1
- 0
rtv-git/rtv/refs/pull/86/head View File

@@ -0,0 +1 @@
6025fc24c40a2200b613e7ce6efdd24ee5b56e4f

+ 1
- 0
rtv-git/rtv/refs/pull/87/head View File

@@ -0,0 +1 @@
9edbd9317f983f30a001f667a9d162f8790447fb

+ 1
- 0
rtv-git/rtv/refs/pull/92/head View File

@@ -0,0 +1 @@
bdd55d3da2683dc07842f9d2b451ae23ebf57dc2

+ 1
- 0
rtv-git/rtv/refs/pull/95/head View File

@@ -0,0 +1 @@
15f15c9302aa96759028c457f3b6b8b87371336d

+ 1
- 0
rtv-git/rtv/refs/pull/97/head View File

@@ -0,0 +1 @@
794e2972949066f3a0961b3cb639b743715c9cd5

+ 1
- 0
rtv-git/rtv/refs/pull/97/merge View File

@@ -0,0 +1 @@
30eaa7521d4594ecbc29a289efa101903fd3306a

+ 1
- 0
rtv-git/rtv/refs/tags/v1.3 View File

@@ -0,0 +1 @@
ff0e9bc6770d59cab830084ca142b0e26e32dbdc

+ 1
- 0
rtv-git/rtv/refs/tags/v1.4 View File

@@ -0,0 +1 @@
2a935922bf9b97cc2358a35963c0b4dada7a9f6c

Loading…
Cancel
Save