Apply the autosuggestion as the first completion in the PTK completer

This commit is contained in:
Anthony Scopatz 2017-02-18 21:44:28 -05:00
parent ef717c5bb3
commit bcfb0b96d5
2 changed files with 60 additions and 38 deletions

View file

@ -5,6 +5,7 @@ import builtins
from prompt_toolkit.layout.dimension import LayoutDimension
from prompt_toolkit.completion import Completer, Completion
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
class PromptToolkitCompleter(Completer):
@ -13,22 +14,26 @@ class PromptToolkitCompleter(Completer):
It just redirects requests to normal Xonsh completer.
"""
def __init__(self, completer, ctx):
"""Takes instance of xonsh.completer.Completer and dict with context."""
def __init__(self, completer, ctx, shell):
"""Takes instance of xonsh.completer.Completer, the xonsh execution
context, and the shell instance itself.
"""
self.completer = completer
self.ctx = ctx
self.shell = shell
self.hist_suggester = AutoSuggestFromHistory()
def get_completions(self, document, complete_event):
"""Returns a generator for list of completions."""
env = builtins.__xonsh_env__
should_complete = (
complete_event.completion_requested or
builtins.__xonsh_env__.get('UPDATE_COMPLETIONS_ON_KEYPRESS')
env.get('UPDATE_COMPLETIONS_ON_KEYPRESS')
)
# Only generate completions when the user hits tab.
if should_complete:
if self.completer is None:
yield from []
else:
if not should_complete or self.completer is None:
return
# generate actual completions
line = document.current_line.lstrip()
line_ex = builtins.aliases.expand_alias(line)
@ -37,31 +42,48 @@ class PromptToolkitCompleter(Completer):
if line[:endidx].rfind(' ') >= 0 else 0)
prefix = line[begidx:endidx]
expand_offset = len(line_ex) - len(line)
completions, l = self.completer.complete(prefix,
line_ex,
# get normal completions
completions, l = self.completer.complete(prefix, line_ex,
begidx + expand_offset,
endidx + expand_offset,
self.ctx)
# completions from auto suggest
if env.get('AUTO_SUGGEST'):
sug_comp = self.suggestion_completion(document, line)
if sug_comp is None:
pass
elif len(completions) == 0:
completions = (sug_comp,)
else:
completions = (sug_comp,) + completions
# reserve space, if needed.
if len(completions) <= 1:
pass
elif len(os.path.commonprefix(completions)) <= len(prefix):
self.reserve_space()
# Find common prefix (strip quoting)
c_prefix = os.path.commonprefix([a.strip('\'"')
for a in completions])
c_prefix = os.path.commonprefix([a.strip('\'"') for a in completions])
# Find last split symbol, do not trim the last part
while c_prefix:
if c_prefix[-1] in r'/\.:@,':
break
c_prefix = c_prefix[:-1]
# yield completions
for comp in completions:
# do not display quote
disp = comp.strip('\'"')[len(c_prefix):]
yield Completion(comp, -l, display=disp)
def suggestion_completion(self, document, line):
"""Provides a completion based on the current auto-suggestion."""
cli = self.shell.prompter.cli
sug = self.hist_suggester.get_suggestion(cli, cli.current_buffer, document)
if sug is None:
return None
comp, _ , _ = sug.text.partition(' ')
_, _, prev = line.rpartition(' ')
return prev + comp
def reserve_space(self):
cli = builtins.__xonsh_shell__.shell.prompter.cli
window = cli.application.layout.children[0].content.children[1]

View file

@ -38,7 +38,7 @@ class PromptToolkitShell(BaseShell):
super().__init__(**kwargs)
self.prompter = Prompter()
self.history = PromptToolkitHistory()
self.pt_completer = PromptToolkitCompleter(self.completer, self.ctx)
self.pt_completer = PromptToolkitCompleter(self.completer, self.ctx, self)
key_bindings_manager_args = {
'enable_auto_suggest_bindings': True,
'enable_search': True,