Skip to content

Instantly share code, notes, and snippets.

@aliles
Created August 18, 2011 12:01
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aliles/1153926 to your computer and use it in GitHub Desktop.
Save aliles/1153926 to your computer and use it in GitHub Desktop.
Enhancements to Python REPL
"""REPL enhancements for Python interactive interpreter.
This module adds:
- tab completion (requires readline support)
- command history between sessions
- syntactic sugar for 'help(stmt)' via 'stmt?'
- user 'more' as pager command
- output history
To enable set the environment variables:
PYTHONSTARTUP=$HOME/.startup.py
Note: The PYTHONSTARTUP environment variable wont expand a '~' to the users
home directory, use $HOME instead.
"""
try:
import atexit
import os
import readline
import rlcompleter
except ImportError as err:
pass
else:
class __ReadlineCompleter(rlcompleter.Completer):
"""Tab completion support for readline.
If there is not text for command completion, insert 4 spaces.
"""
def __init__(self, tab=' '):
self._complete = rlcompleter.Completer.complete
self._insert_text = readline.insert_text
self.tab = tab
rlcompleter.Completer.__init__(self)
def complete(self, text, state):
if text == '':
self.insert_text(self.tab)
return None
else:
return self._complete(self, text, state)
readline.parse_and_bind('tab: complete')
readline.set_completer(__ReadlineCompleter().complete)
class __HistoryManager(object):
"""Load and store command history.
Commands are persisted in file '~/.history.py'.
"""
def __init__(self, path='~/.history.py'):
self.history_path = os.path.expanduser(path)
self._read_history_file = readline.read_history_file
self._write_history_file = readline.write_history_file
self.load_history()
def load_history(self):
if os.path.isfile(self.history_path):
self._read_history_file(self.history_path)
def save_history(self):
self._write_history_file(self.history_path)
atexit.register(__HistoryManager().save_history)
del __ReadlineCompleter
del __HistoryManager
del atexit, os, readline, rlcompleter
try:
import inspect
import string
import sys
except ImportError as err:
pass
else:
class __HelpSyntax(object):
"""Quick access to help documentation.
If statement ends with a '?', evaulate help(stmt).
"""
def __init__(self):
self.default = sys.__excepthook__
self.isframe = inspect.isframe
self.stack = inspect.stack
self.stdout = sys.stdout
self.whitespace = string.whitespace
def __call__(self, type, value, traceback):
if not isinstance(value, SyntaxError):
return self.default(type, value, traceback)
stmt = value.text.rstrip()
if not stmt.endswith('?'):
return self.default(type, value, traceback)
name = stmt.rstrip('?(' + self.whitespace)
self.show_help(name)
def show_help(self, name):
for record in self.stack():
frame = record[0]
if not self.isframe(frame):
continue
if frame.f_globals.get('__name__') != '__main__':
continue
cmd = 'help({0})'.format(name)
self.stdout.write(cmd)
return eval(cmd, frame.f_globals, frame.f_locals)
sys.excepthook = __HelpSyntax()
del __HelpSyntax
del inspect, string, sys
try:
import functools
import pydoc
except ImportError as err:
pass
else:
pydoc.pager = functools.partial(pydoc.pipepager, cmd='more')
del functools, pydoc
try:
import sys
except ImportError as err:
pass
else:
class __Prompt(object):
"""Maintain dictionary of output history.
If '__history__' is a dict, store output results using one up number
keys. Prompt is changed to identify how many keys have been populated.
"""
def __init__(self, prompt='>>> '):
self.counter = 0
self.prompt = prompt
def __radd__(self, left):
return str(left) + str(self)
def __str__(self):
if self.is_history():
self.update_history()
return 'H[{0}] {1}'.format(self.counter, self.prompt)
return self.prompt
def is_history(self):
return isinstance(globals().get('__history__'), dict)
def update_history(self):
try:
if (_ is not __history__ and
_ is not __history__.get(self.counter)):
self.counter += 1
__history__[self.counter] = _
return True
except NameError:
pass
finally:
return True
# __history__ = {0: None}
__history__ = None
sys.ps1 = __Prompt()
del __Prompt
del sys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment