import pytest from inspect import signature from unittest.mock import MagicMock from prompt_toolkit.document import Document from prompt_toolkit.completion import Completion as PTKCompletion from xonsh.aliases import Aliases from xonsh.completer import Completer from xonsh.completers.tools import RichCompletion from xonsh.ptk_shell.completer import PromptToolkitCompleter @pytest.mark.parametrize( "completion, lprefix, ptk_completion", [ (RichCompletion("x", 0, "x()", "func"), 0, None), (RichCompletion("x", 1, "xx", "instance"), 0, None), ( RichCompletion("x", description="wow"), 5, PTKCompletion(RichCompletion("x"), -5, "x", "wow"), ), (RichCompletion("x"), 5, PTKCompletion(RichCompletion("x"), -5, "x")), ("x", 5, PTKCompletion("x", -5, "x")), ], ) def test_rich_completion(completion, lprefix, ptk_completion, monkeypatch, xession): xonsh_completer_mock = MagicMock() xonsh_completer_mock.complete.return_value = {completion}, lprefix
def complete_completer_names(xsh, **_): """Complete all loaded completer names""" for name, comp in xsh.completers.items(): doc = NumpyDoc(comp) yield RichCompletion(name, description=doc.description)
def iter_completions(self, rule): for kw in rule.keywords: yield RichCompletion(kw, description=rule.help)
] @pytest.mark.parametrize( "completion, rich_completion", [ ( # from jedi when code is 'x' and xx=3 ( "instance", "xx", "x", "int(x=None, /) -> int", ("instance", "instance int"), ), RichCompletion("x", display="xx", description="instance int"), ), ( # from jedi when code is 'xx=3\nx' ("statement", "xx", "x", None, ("instance", "instance int")), RichCompletion("x", display="xx", description="instance int"), ), ( # from jedi when code is 'x.' and x=3 ( "function", "from_bytes", "from_bytes", "from_bytes(bytes, byteorder, *, signed=False)", ("function", "def __get__"), ),
def job_id_completer(xsh, **_): """Return currently running jobs ids""" for job_id in xsh.all_jobs: yield RichCompletion(str(job_id), description=format_job_string(job_id))
def _example_completer(prefix, line, begidx, endidx, ctx): """carapace completer for example""" if not line.startswith('example '): return # not the expected command to complete from shlex import split from xonsh.completers.tools import RichCompletion words = "" wordsNonPosix = "" try: words = split(line[0:endidx] + "_") # ensure last word is empty when ends with space wordsNonPosix = split(line[0:endidx], posix=False) except: try: words = split( line[0:endidx] + '"' + "_") # ensure last word is empty when ends with space wordsNonPosix = split(line[0:endidx] + '"', posix=False) wordsNonPosix[-1] = wordsNonPosix[-1][:-1] except: words = split( line[0:endidx] + "'" + "_") # ensure last word is empty when ends with space wordsNonPosix = split(line[0:endidx] + "'", posix=False) wordsNonPosix[-1] = wordsNonPosix[-1][:-1] words[-1] = words[-1][0:-1] if len(words[-1]) != 0: begidx = endidx for word in reversed(wordsNonPosix): begidx = begidx - len(word) if line[begidx - 1] == " ": break for index, item in enumerate(wordsNonPosix): if item.startswith("r'"): words[index] = words[index][ 1:] # fix rawstring not handled by shlex current = words[-1] previous = words[-2] result = {} def _example_callback(): from json import loads from subprocess import Popen, PIPE from xonsh.completers.tools import RichCompletion cb, _ = Popen(['example', '_carapace', 'xonsh', '_', *words], stdout=PIPE, stderr=PIPE).communicate() try: return { RichCompletion(c["Value"], display=c["Display"], description=c["Description"], prefix_len=0) for c in loads(cb) } except: return {} result = _example_callback() if len(result) == 0: result = { RichCompletion(current, display=current, description='', prefix_len=0) } result = set( map( lambda x: RichCompletion(x, display=x.display, description=x.description, prefix_len=endidx - begidx), result)) return result
import pytest from xonsh.completers.tools import RichCompletion from xonsh.readline_shell import _render_completions @pytest.mark.parametrize( "prefix, completion, prefix_len, readline_completion", [ ("", "a", 0, "a"), ("a", "b", 0, "ab"), ("a", "b", 1, "b"), ("adc", "bc", 2, "abc"), ("", RichCompletion("x", 0), 0, "x"), ("", RichCompletion("x", 0, "aaa", "aaa"), 0, "x"), ("a", RichCompletion("b", 1), 0, "b"), ("a", RichCompletion("b", 0), 1, "ab"), ("a", RichCompletion("b"), 0, "ab"), ("a", RichCompletion("b"), 1, "b"), ], ) def test_render_completions(prefix, completion, prefix_len, readline_completion): assert _render_completions({completion}, prefix, prefix_len) == [ readline_completion ]
def XONSH_STMT_TOKENS(): return { RichCompletion("as", append_space=True), RichCompletion("assert", append_space=True), "break", RichCompletion("class", append_space=True), "continue", RichCompletion("def", append_space=True), RichCompletion("del", append_space=True), RichCompletion("elif", append_space=True), RichCompletion("except", append_space=True), "finally:", RichCompletion("from", append_space=True), RichCompletion("global", append_space=True), RichCompletion("import", append_space=True), RichCompletion("nonlocal", append_space=True), "pass", RichCompletion("raise", append_space=True), RichCompletion("return", append_space=True), "try:", RichCompletion("while", append_space=True), RichCompletion("with", append_space=True), RichCompletion("yield", append_space=True), "-", "/", "//", "%", "**", "|", "&", "~", "^", ">>", "<<", "<", "<=", "->", "=", "+=", "-=", "*=", "/=", "%=", "**=", ">>=", "<<=", "&=", "^=", "|=", "//=", ";", ":", "..", }
def complete_jedi(context: CompletionContext): """Completes python code using Jedi and xonsh operators""" if context.python is None: return None xonsh_execer: XonshSession = builtins.__xonsh__ # type: ignore ctx = context.python.ctx or {} # if the first word is a known command (and we're not completing it), don't complete. # taken from xonsh/completers/python.py if context.command and context.command.arg_index != 0: first = context.command.args[0].value if first in xonsh_execer.commands_cache and first not in ctx: # type: ignore return None # if we're completing a possible command and the prefix contains a valid path, don't complete. if context.command: path_parts = os.path.split(context.command.prefix) if len(path_parts) > 1 and os.path.isdir( os.path.join(*path_parts[:-1])): return None filter_func = get_filter_function() jedi.settings.case_insensitive_completion = not xonsh_execer.env.get( "CASE_SENSITIVE_COMPLETIONS") source = context.python.multiline_code index = context.python.cursor_index row = source.count("\n", 0, index) + 1 column = (index - source.rfind("\n", 0, index) - 1 ) # will be `index - (-1) - 1` if there's no newline extra_ctx = {"__xonsh__": xonsh_execer} try: extra_ctx["_"] = _ except NameError: pass if JEDI_NEW_API: script = jedi.Interpreter(source, [ctx, extra_ctx]) else: script = jedi.Interpreter(source, [ctx, extra_ctx], line=row, column=column) script_comp = set() try: if JEDI_NEW_API: script_comp = script.complete(row, column) else: script_comp = script.completions() except Exception: pass res = set( create_completion(comp) for comp in script_comp if should_complete(comp)) if index > 0: last_char = source[index - 1] res.update( RichCompletion(t, prefix_len=1) for t in XONSH_SPECIAL_TOKENS if filter_func(t, last_char)) else: res.update( RichCompletion(t, prefix_len=0) for t in XONSH_SPECIAL_TOKENS) return res
] @pytest.mark.parametrize( "completion, rich_completion", [ ( # from jedi when code is 'x' and xx=3 ( "instance", "xx", "x", "int(x=None, /) -> int", ("instance", "instance int"), ), RichCompletion( "xx", display="xx", description="instance int", prefix_len=1), ), ( # from jedi when code is 'xx=3\nx' ("statement", "xx", "x", None, ("instance", "instance int")), RichCompletion( "xx", display="xx", description="instance int", prefix_len=1), ), ( # from jedi when code is 'x.' and x=3 ( "function", "from_bytes", "from_bytes", "from_bytes(bytes, byteorder, *, signed=False)", ("function", "def __get__"),
import pytest from xonsh.completers.tools import RichCompletion from xonsh.readline_shell import _render_completions @pytest.mark.parametrize( 'prefix, completion, prefix_len, readline_completion', [ ('', 'a', 0, 'a'), ('a', 'b', 0, 'ab'), ('a', 'b', 1, 'b'), ('adc', 'bc', 2, 'abc'), ('', RichCompletion('x', 0), 0, 'x'), ('', RichCompletion('x', 0, 'aaa', 'aaa'), 0, 'x'), ('a', RichCompletion('b', 1), 0, 'b'), ('a', RichCompletion('b', 0), 1, 'ab'), ('a', RichCompletion('b'), 0, 'ab'), ('a', RichCompletion('b'), 1, 'b'), ]) def test_render_completions(prefix, completion, prefix_len, readline_completion): assert _render_completions({completion}, prefix, prefix_len) == [readline_completion]
def comp(context: CommandContext): return { RichCompletion(context.prefix + "a", append_space=True), RichCompletion(context.prefix + " ", append_space=False), # bad usage RichCompletion(context.prefix + "b", append_space=True, append_closing_quote=False), }
jedi_xontrib.complete_jedi('x', 'x', 0, 1, {}) assert jedi_mock.Interpreter.call_args_list[0][0][0] == complete_document assert jedi_mock.Interpreter().complete.call_args_list == [ call(2, 5) # line (one-indexed), column (zero-indexed) ] @pytest.mark.parametrize( 'completion, rich_completion', [ ( # from jedi when code is 'x' and xx=3 ('instance', 'xx', 'x', 'int(x=None, /) -> int', ('instance', 'instance int')), RichCompletion('x', display='xx', description='instance int')), ( # from jedi when code is 'xx=3\nx' ('statement', 'xx', 'x', None, ('instance', 'instance int')), RichCompletion('x', display='xx', description='instance int')), ( # from jedi when code is 'x.' and x=3 ('function', 'from_bytes', 'from_bytes', 'from_bytes(bytes, byteorder, *, signed=False)', ('function', 'def __get__')), RichCompletion( 'from_bytes', display='from_bytes()', description='from_bytes(bytes, byteorder, *, signed=False)')), ( # from jedi when code is 'x=3\nx.'