diff --git a/rtv/config.py b/rtv/config.py index 81cf04b..84c1182 100644 --- a/rtv/config.py +++ b/rtv/config.py @@ -1,10 +1,13 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals +import re import os +import curses import codecs import shutil import argparse +from curses import ascii from functools import partial import six @@ -195,12 +198,12 @@ class Config(object): return cls._parse_rtv_file(config) - @staticmethod - def _parse_rtv_file(config): + @classmethod + def _parse_rtv_file(cls, config): - out = {} + rtv = {} if config.has_section('rtv'): - out = dict(config.items('rtv')) + rtv = dict(config.items('rtv')) params = { 'ascii': partial(config.getboolean, 'rtv'), @@ -208,13 +211,41 @@ class Config(object): 'persistent': partial(config.getboolean, 'rtv'), 'history_size': partial(config.getint, 'rtv'), 'oauth_redirect_port': partial(config.getint, 'rtv'), - 'oauth_scope': lambda x: out[x].split(',') + 'oauth_scope': lambda x: rtv[x].split(',') } for key, func in params.items(): - if key in out: - out[key] = func(key) - return out + if key in rtv: + rtv[key] = func(key) + + bindings = {} + if config.has_section('bindings'): + bindings = dict(config.items('bindings')) + + for name, keys in bindings.items(): + bindings[name] = [cls._parse_key(key) for key in keys.split(',')] + + return rtv, bindings + + @staticmethod + def _parse_key(key): + """ + Parse a key represented by a string return its character code. + """ + + key = key.strip() + if re.match('[<]KEY_.*[>]', key): + # Curses control character + return getattr(curses, key[1:-1]) + elif re.match('[<].*[>]', key): + # Ascii control character + return getattr(ascii, key[1:-1]) + elif key.startswith('0x'): + # Ascii hex code + return int(key, 16) + else: + # Ascii character + return ord(key) @staticmethod def _ensure_filepath(filename): diff --git a/rtv/rtv.cfg b/rtv/rtv.cfg index 540ee7a..5d01cf5 100644 --- a/rtv/rtv.cfg +++ b/rtv/rtv.cfg @@ -49,4 +49,69 @@ oauth_redirect_uri = http://127.0.0.1:65000/ oauth_redirect_port = 65000 ; Access permissions that will be requested. -oauth_scope = edit,history,identity,mysubreddits,privatemessages,read,report,save,submit,subscribe,vote \ No newline at end of file +oauth_scope = edit,history,identity,mysubreddits,privatemessages,read,report,save,submit,subscribe,vote + +[bindings] +############## +# Key Bindings +############## +; Multiple keys that represent the same command should be listed as a comma +; seperated list. The a mixture of the following notations should be used to +; describe keys. +; +; 1.) Plain keys can be represented by either uppercase/lowercase characters +; or the hexadecimal codes referring their ascii codes. For reference, see +; https://en.wikipedia.org/wiki/ASCII#ASCII_printable_code_chart +; e.g. Q, q, 1, ? +; e.g. 0x20 (space), 0x3c (less-than sign) +; +; 2.) Special ascii control codes should be surrounded with <>. For reference, +; see https://en.wikipedia.org/wiki/ASCII#ASCII_control_code_chart +; e.g. (enter), (escape) +; +; 3.) Other special keys are defined by curses, they should be surrounded by <> +; and prefixed with KEY_. For reference, see +; https://docs.python.org/2/library/curses.html#constants +; e.g. (left arrow), , (page down) +; +; Notes: +; - Curses is unreliable and should always be used in conjunction +; with . + +; General keys +EXIT = q +FORCE_EXIT = Q +HELP = ? +SORT_HOT = 1 +SORT_TOP = 2 +SORT_RISING = 3 +SORT_NEW = 4 +SORT_CONTROVERSIAL = 5 +MOVE_UP = k, +MOVE_DOWN = j, +PAGE_UP = m, +PAGE_DOWN = n, +UPVOTE = a +DOWNVOTE = z +LOGIN = u +DELETE = d +EDIT = e +INBOX = i +REFRESH = r, + +; Submission page +SUBMISSION_TOGGLE_COMMENTS = l, 0x20, +SUBMISSION_OPEN_IN_BROWSER = o, , +SUBMISSION_POST = c +SUBMISSION_EXIT = h, + +; Subreddit page +SUBREDDIT_SEARCH = f +SUBREDDIT_PROMPT = / +SUBREDDIT_POST = c +SUBREDDIT_OPEN = l, +SUBREDDIT_OPEN_IN_BROWSER = o, , , + +; Subscription page +SUBSCRIPTION_SELECT = l, , , +SUBSCRIPTION_EXIT = h, s, , \ No newline at end of file diff --git a/tests/test_config.py b/tests/test_config.py index 734a592..ade7da5 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -103,6 +103,12 @@ def test_config_from_file(): assert config.config == args +def test_config_keys(): + + config = Config() + pass + + def test_config_refresh_token(): "Ensure that the refresh token can be loaded, saved, and removed"