Skip to content

Instantly share code, notes, and snippets.

@Roguelazer
Last active August 29, 2015 14: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 Roguelazer/a3cfd3d193072cb688be to your computer and use it in GitHub Desktop.
Save Roguelazer/a3cfd3d193072cb688be to your computer and use it in GitHub Desktop.
pythonrc with tab completion
try:
import readline
except ImportError:
pass
else:
import itertools
import rlcompleter
import re
import os
import atexit
import sys
import socket
def get_all_modules():
import os.path, sys
yield 'sys'
for p in sys.path:
if p and os.path.isdir(p):
for root, dirs, files in os.walk(p):
base = ''
if '.egg-info' in root:
continue
if '.egg' in root:
egg_offset = 0
for i, component in enumerate(root.split(os.sep)):
if '.egg' in component:
egg_offset = i
base = os.sep.join(root.split(os.sep)[egg_offset+1:]).replace(os.sep, '.')
else:
base = root.replace(p, '').replace(os.sep, '.')
if base.startswith('.'):
base = base[1:]
if base:
base += '.'
for d in dirs:
full_path = os.path.join(root, d)
if os.path.exists(os.path.join(full_path, '__init__.py')):
yield base + d
for item in files:
if item == '__init__.py':
yield base[:-1]
elif item.startswith('__'):
continue
elif '.py' in item:
yield base + re.sub(r'.py[co]?$', '', item)
elif item.endswith('.so'):
yield base + item[:-3]
# custom completer. knows how to complete python keywords (from rlcompleter.Completer) and also
# any modules in sys.path
class irlcompleter(rlcompleter.Completer):
def complete_module(self, text, state, strip_prefix=None):
if getattr(self, 'mods', None) is None:
mods = set()
mods_by_dot = {}
for m in get_all_modules():
dot = m.count('.')
mods_by_dot.setdefault(dot, set())
mods_by_dot[dot].add(m)
mods.add(m)
self.mods = mods
self.mods_by_dot = mods_by_dot
if state == 0:
self.mod_matches = {}
for k, ms in sorted(self.mods_by_dot.items(), reverse=True):
self.mod_matches[k] = list(sorted(m for m in ms if m.lower().startswith(text.lower())))
try:
rv = self.mod_matches.get(text.count('.'), list)[state]
if strip_prefix:
rv = rv[len(strip_prefix):]
return rv
except IndexError:
return None
def complete(self, text, state, buf=None):
if buf is None:
buf = readline.get_line_buffer()
if re.match(r'^\s*import ', buf):
return self.complete_module(text, state)
else:
if re.match(r'^\s*from\s+', buf):
# trim leading empty fields
fields = re.split(r'\s+', buf)
#fields = list(itertools.dropwhile(lambda x: not x,
if len(fields) <= 2:
return self.complete_module(text, state)
elif len(fields) == 3:
if state == 0:
return 'import'
else:
return None
else:
search = fields[1]
if len(fields) >= 4:
search += '.' + fields[3]
return self.complete_module(search, state, strip_prefix=(fields[1]+'.'))
return rlcompleter.Completer.complete(self,text,state)
# Restore our command-line history, and save it when Python exits.
history_file = os.path.expanduser("~/.pyhistory")
if os.path.exists(history_file):
try:
readline.read_history_file(history_file)
except Exception as e:
pass
def save_hist():
import readline
readline.write_history_file(history_file)
atexit.register(save_hist)
if 'libedit' in readline.__doc__:
readline.parse_and_bind("bind ^I rl_complete")
else:
readline.parse_and_bind("tab: complete")
readline.set_completer(irlcompleter().complete)
# make the promt more informative
sys.ps1 = 'python %s @ %s >>> ' % ('.'.join(map(str, sys.version_info)), socket.gethostname())
# Clean up the namespace.
del sys
del socket
del os
del atexit
# vim: set syntax=python expandtab ts=4 sw=4:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment