[tor-commits] [stem/master] Moving autocompletion to its own module
atagar at torproject.org
atagar at torproject.org
Tue May 6 01:21:13 UTC 2014
commit 278994377919bef35dcf6fef604d7bf5ef3be6da
Author: Damian Johnson <atagar at torproject.org>
Date: Sat Apr 19 16:23:01 2014 -0700
Moving autocompletion to its own module
I bundled autocompletion with commands.py because it used one of its globals.
However, we've since dropped those bits so this can be nicely moved back to its
own file.
---
stem/interpretor/__init__.py | 7 +--
stem/interpretor/autocomplete.py | 98 ++++++++++++++++++++++++++++++++++++++
stem/interpretor/commands.py | 93 ------------------------------------
3 files changed, 102 insertions(+), 96 deletions(-)
diff --git a/stem/interpretor/__init__.py b/stem/interpretor/__init__.py
index 59c89c8..5e03c2c 100644
--- a/stem/interpretor/__init__.py
+++ b/stem/interpretor/__init__.py
@@ -6,7 +6,7 @@ Interactive interpretor for interacting with Tor directly. This adds usability
features such as tab completion, history, and IRC-style functions (like /help).
"""
-__all__ = ['arguments', 'commands', 'msg']
+__all__ = ['arguments', 'autocomplete', 'commands', 'msg']
import os
import sys
@@ -39,6 +39,7 @@ def main():
import readline
import stem.interpretor.arguments
+ import stem.interpretor.autocomplete
import stem.interpretor.commands
try:
@@ -64,9 +65,9 @@ def main():
sys.exit(1)
with controller:
- autocomplete = stem.interpretor.commands.Autocomplete(controller)
+ autocompleter = stem.interpretor.autocomplete.Autocompleter(controller)
readline.parse_and_bind('tab: complete')
- readline.set_completer(autocomplete.complete)
+ readline.set_completer(autocompleter.complete)
readline.set_completer_delims('\n')
interpretor = stem.interpretor.commands.ControlInterpretor(controller)
diff --git a/stem/interpretor/autocomplete.py b/stem/interpretor/autocomplete.py
new file mode 100644
index 0000000..09c5365
--- /dev/null
+++ b/stem/interpretor/autocomplete.py
@@ -0,0 +1,98 @@
+"""
+Tab completion for our interpretor prompt.
+"""
+
+from stem.interpretor import uses_settings
+
+
+ at uses_settings
+def _get_commands(config, controller):
+ """
+ Provides commands recognized by tor.
+ """
+
+ commands = config.get('autocomplete', [])
+
+ # GETINFO commands
+
+ getinfo_options = controller.get_info('info/names', None)
+
+ if getinfo_options:
+ # Lines are of the form '[option] -- [description]'. This strips '*' from
+ # options that accept values.
+
+ options = [line.split(' ', 1)[0].rstrip('*') for line in getinfo_options.splitlines()]
+
+ commands += ['GETINFO %s' % opt for opt in options]
+ else:
+ commands.append('GETINFO ')
+
+ # GETCONF, SETCONF, and RESETCONF commands
+
+ config_options = controller.get_info('config/names', None)
+
+ if config_options:
+ # individual options are '[option] [type]' pairs
+
+ entries = [opt.split(' ', 1)[0] for opt in config_options.splitlines()]
+
+ commands += ['GETCONF %s' % opt for opt in entries]
+ commands += ['SETCONF %s ' % opt for opt in entries]
+ commands += ['RESETCONF %s' % opt for opt in entries]
+ else:
+ commands += ['GETCONF ', 'SETCONF ', 'RESETCONF ']
+
+ # SETEVENT commands
+
+ events = controller.get_info('events/names', None)
+
+ if events:
+ commands += ['SETEVENTS %s' % event for event in events.split(' ')]
+ else:
+ commands.append('SETEVENTS ')
+
+ # USEFEATURE commands
+
+ features = controller.get_info('features/names', None)
+
+ if features:
+ commands += ['USEFEATURE %s' % feature for feature in features.split(' ')]
+ else:
+ commands.append('USEFEATURE ')
+
+ # SIGNAL commands
+
+ signals = controller.get_info('signal/names', None)
+
+ if signals:
+ commands += ['SIGNAL %s' % signal for signal in signals.split(' ')]
+ else:
+ commands.append('SIGNAL ')
+
+ # adds help options for the previous commands
+
+ base_cmd = set([cmd.split(' ')[0].replace('+', '').replace('/', '') for cmd in commands])
+
+ for cmd in base_cmd:
+ commands.append('/help ' + cmd)
+
+ return commands
+
+
+class Autocompleter(object):
+ def __init__(self, controller):
+ self._commands = _get_commands(controller)
+
+ def complete(self, text, state):
+ """
+ Provides case insensetive autocompletion options, acting as a functor for
+ the readlines set_completer function.
+ """
+
+ lowercase_text = text.lower()
+ prefix_matches = [cmd for cmd in self._commands if cmd.lower().startswith(lowercase_text)]
+
+ if state < len(prefix_matches):
+ return prefix_matches[state]
+ else:
+ return None
diff --git a/stem/interpretor/commands.py b/stem/interpretor/commands.py
index 833918f..e5b3e97 100644
--- a/stem/interpretor/commands.py
+++ b/stem/interpretor/commands.py
@@ -16,99 +16,6 @@ BOLD_OUTPUT_FORMAT = (Color.BLUE, Attr.BOLD)
ERROR_FORMAT = (Attr.BOLD, Color.RED)
- at uses_settings
-def _get_commands(config, controller):
- """
- Provides commands recognized by tor.
- """
-
- commands = config.get('autocomplete', [])
-
- # GETINFO commands
-
- getinfo_options = controller.get_info('info/names', None)
-
- if getinfo_options:
- # Lines are of the form '[option] -- [description]'. This strips '*' from
- # options that accept values.
-
- options = [line.split(' ', 1)[0].rstrip('*') for line in getinfo_options.splitlines()]
-
- commands += ['GETINFO %s' % opt for opt in options]
- else:
- commands.append('GETINFO ')
-
- # GETCONF, SETCONF, and RESETCONF commands
-
- config_options = controller.get_info('config/names', None)
-
- if config_options:
- # individual options are '[option] [type]' pairs
-
- entries = [opt.split(' ', 1)[0] for opt in config_options.splitlines()]
-
- commands += ['GETCONF %s' % opt for opt in entries]
- commands += ['SETCONF %s ' % opt for opt in entries]
- commands += ['RESETCONF %s' % opt for opt in entries]
- else:
- commands += ['GETCONF ', 'SETCONF ', 'RESETCONF ']
-
- # SETEVENT commands
-
- events = controller.get_info('events/names', None)
-
- if events:
- commands += ['SETEVENTS %s' % event for event in events.split(' ')]
- else:
- commands.append('SETEVENTS ')
-
- # USEFEATURE commands
-
- features = controller.get_info('features/names', None)
-
- if features:
- commands += ['USEFEATURE %s' % feature for feature in features.split(' ')]
- else:
- commands.append('USEFEATURE ')
-
- # SIGNAL commands
-
- signals = controller.get_info('signal/names', None)
-
- if signals:
- commands += ['SIGNAL %s' % signal for signal in signals.split(' ')]
- else:
- commands.append('SIGNAL ')
-
- # adds help options for the previous commands
-
- base_cmd = set([cmd.split(' ')[0].replace('+', '').replace('/', '') for cmd in commands])
-
- for cmd in base_cmd:
- commands.append('/help ' + cmd)
-
- return commands
-
-
-class Autocomplete(object):
- def __init__(self, controller):
- self._commands = _get_commands(controller)
-
- def complete(self, text, state):
- """
- Provides case insensetive autocompletion options, acting as a functor for
- the readlines set_completer function.
- """
-
- lowercase_text = text.lower()
- prefix_matches = [cmd for cmd in self._commands if cmd.lower().startswith(lowercase_text)]
-
- if state < len(prefix_matches):
- return prefix_matches[state]
- else:
- return None
-
-
class ControlInterpretor(object):
"""
Handles issuing requests and providing nicely formed responses, with support
More information about the tor-commits
mailing list