added completer

This commit is contained in:
Anthony Scopatz 2015-03-01 22:59:44 -06:00
parent f909fbee2e
commit b4b4490272
3 changed files with 72 additions and 5 deletions

52
xonsh/completer.py Normal file
View file

@ -0,0 +1,52 @@
"""A (tab-)completer for xonsh."""
from __future__ import print_function, unicode_literals
import os
import sys
import builtins
import subprocess
from glob import glob, iglob
XONSH_TOKENS = {'and', 'as', 'assert', 'break', 'class', 'continue', 'def',
'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global',
'import', 'if', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass',
'raise', 'return', 'try', 'while', 'with', 'yield', '+', '-', '/', '//',
'%', '**', '|', '&', '~', '^', '>>', '<<', '<', '<=', '>', '>=', '==',
'!=', '->', '=', '+=', '-=', '*=', '/=', '%=', '**=', '>>=', '<<=',
'&=', '^=', '|=', '//=', ',', ';', ':', '?', '??', '$(', '${', '$[',
'..', '...'}
class Completer(object):
"""This provides a list of optional completions for the xonsh shell."""
def complete(self, prefix, line, begidx, endidx, ctx=None):
"""Complete the string s, given a possible execution context.
Parameters
----------
prefix : str
The string to match
line : str
The line that prefix appears on.
begidx : int
The index in line that prefix starts on.
endidx : int
The index in line that prefix ends on.
ctx : Iterable of str (ie dict, set, etc), optional
Names in the current execution context.
Returns
-------
rtn : list of str
Possible completions of prefix, sorted alphabetically.
"""
rtn = {s for s in XONSH_TOKENS if s.startswith(prefix)}
if ctx is not None:
rtn |= {s for s in ctx if s.startswith(prefix)}
rtn |= {s for s in dir(builtins) if s.startswith(prefix)}
rtn |= {s for s in builtins.aliases if s.startswith(prefix)}
if prefix.startswith('$'):
key = prefix[1:]
rtn |= {k for k in builtins.__xonsh_env__ if k.startswith(key)}
rtn.update(iglob(prefix + '*'))
#print(rtn)
return sorted(rtn)

View file

@ -114,7 +114,7 @@ class Lexer(object):
# Assignment Operators
'EQUALS', 'PLUSEQUAL', 'MINUSEQUAL', 'TIMESEQUAL', 'DIVEQUAL',
'MODEQUAL', 'POWEQUAL', 'LSHIFTEQUAL','RSHIFTEQUAL', 'AMPERSANDEQUAL',
'MODEQUAL', 'POWEQUAL', 'LSHIFTEQUAL', 'RSHIFTEQUAL', 'AMPERSANDEQUAL',
'XOREQUAL', 'PIPEEQUAL', 'DOUBLEDIVEQUAL',
# Command line

View file

@ -4,6 +4,7 @@ from cmd import Cmd
import builtins
from xonsh.execer import Execer
from xonsh.completer import Completer
class Shell(Cmd):
"""The xonsh shell."""
@ -13,10 +14,11 @@ class Shell(Cmd):
stdout=stdout)
self.execer = Execer()
self.ctx = ctx or {}
self.completer = Completer()
def parseline(self, line):
"""Overridden to no-op."""
return '', None, line
return '', line, line
def default(self, line):
"""Implements parser."""
@ -30,9 +32,22 @@ class Shell(Cmd):
def completedefault(self, text, line, begidx, endidx):
"""Implements tab-completion for text."""
x = [s for s in self.ctx if s.startswith(text)]
x += [s for s in dir(builtins) if s.startswith(text)]
return x
if len(text) == 0:
return self.completer.complete(text, line, begidx, endidx, ctx=self.ctx)
s = ''
beg = 0
end = len(line)
for tok in line.split():
if text not in tok:
continue
loc = line.find(tok, beg)
if loc == -1 or loc > begidx:
break
s = tok
beg = loc
end = loc + len(s)
#print('\n', s)
return self.completer.complete(s, line, beg, end, ctx=self.ctx)
# tab complete on first index too
completenames = completedefault