mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 00:14:41 +01:00
fix: append space at the end of completions (#4611)
This commit is contained in:
parent
af06aa8311
commit
cd57240237
3 changed files with 80 additions and 19 deletions
27
tests/xontribs/test_fish_completer.py
Normal file
27
tests/xontribs/test_fish_completer.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fish_completer(tmpdir, xession, load_xontrib, fake_process):
|
||||
"""vox Alias function"""
|
||||
load_xontrib("fish_completer")
|
||||
xession.env.update(
|
||||
dict(
|
||||
XONSH_DATA_DIR=str(tmpdir),
|
||||
XONSH_SHOW_TRACEBACK=True,
|
||||
)
|
||||
)
|
||||
|
||||
fake_process.register_subprocess(
|
||||
command=["fish", fake_process.any()],
|
||||
# completion for "git chec"
|
||||
stdout=b"""\
|
||||
cherry-pick Apply the change introduced by an existing commit
|
||||
checkout Checkout and switch to a branch""",
|
||||
)
|
||||
|
||||
return fake_process
|
||||
|
||||
|
||||
def test_fish_completer(fish_completer, check_completer):
|
||||
assert check_completer("git", prefix="chec") == {"checkout", "cherry-pick"}
|
|
@ -81,6 +81,27 @@ class CommandContext(NamedTuple):
|
|||
else:
|
||||
return f"{self.opening_quote}{self.prefix}"
|
||||
|
||||
@property
|
||||
def command(self):
|
||||
if self.args:
|
||||
return self.args[0].raw_value
|
||||
return None
|
||||
|
||||
@property
|
||||
def words_before_cursor(self) -> str:
|
||||
"""words without current prefix"""
|
||||
return " ".join([arg.raw_value for arg in self.args[: self.arg_index]])
|
||||
|
||||
@property
|
||||
def text_before_cursor(self) -> str:
|
||||
"""full text before cursor including prefix"""
|
||||
return self.words_before_cursor + " " + self.prefix
|
||||
|
||||
@property
|
||||
def begidx(self) -> int:
|
||||
"""cursor's position"""
|
||||
return len(self.text_before_cursor)
|
||||
|
||||
|
||||
class PythonContext(NamedTuple):
|
||||
"""
|
||||
|
|
|
@ -1,43 +1,56 @@
|
|||
from xonsh.completers import completer
|
||||
from xonsh.completers.tools import (
|
||||
RichCompletion,
|
||||
contextual_command_completer,
|
||||
get_filter_function,
|
||||
)
|
||||
|
||||
from xonsh.completers.tools import RichCompletion, contextual_command_completer
|
||||
import os
|
||||
import subprocess as sp
|
||||
from xonsh.built_ins import XSH
|
||||
from xonsh.parsers.completion_context import CommandContext
|
||||
|
||||
|
||||
def create_rich_completion(line: str):
|
||||
def create_rich_completion(line: str, append_space=False):
|
||||
line = line.strip()
|
||||
if "\t" in line:
|
||||
cmd, desc = map(str.strip, line.split("\t", maxsplit=1))
|
||||
else:
|
||||
cmd, desc = line, ""
|
||||
|
||||
# special treatment for path completions.
|
||||
# not appending space even if it is a single candidate.
|
||||
if cmd.endswith(os.pathsep):
|
||||
append_space = False
|
||||
|
||||
return RichCompletion(
|
||||
str(cmd),
|
||||
description=str(desc),
|
||||
append_space=True,
|
||||
cmd,
|
||||
description=desc,
|
||||
append_space=append_space,
|
||||
)
|
||||
|
||||
|
||||
@contextual_command_completer
|
||||
def fish_proc_completer(ctx: CommandContext):
|
||||
"""Populate completions using fish shell and remove bash-completer"""
|
||||
args = [arg.value for arg in ctx.args] + [ctx.prefix]
|
||||
line = " ".join(args)
|
||||
args = ["fish", "-c", f"complete -C '{line}'"]
|
||||
if not ctx.args:
|
||||
return
|
||||
line = ctx.text_before_cursor
|
||||
|
||||
script_lines = [
|
||||
f"complete --no-files {ctx.command}", # switch off basic file completions for the executable
|
||||
f"complete -C '{line}'",
|
||||
]
|
||||
args = ["fish", "-c", "; ".join(script_lines)]
|
||||
env = XSH.env.detype()
|
||||
output = sp.check_output(args, env=env).decode()
|
||||
filter_func = get_filter_function()
|
||||
try:
|
||||
output = sp.check_output(args, env=env).decode()
|
||||
except Exception as ex:
|
||||
print(f"Failed to get fish-completions: {ex}")
|
||||
return
|
||||
|
||||
if output:
|
||||
for line in output.strip().splitlines(keepends=False):
|
||||
comp = create_rich_completion(line)
|
||||
if filter_func(comp, ctx.prefix):
|
||||
yield comp
|
||||
lines = output.strip().splitlines(keepends=False)
|
||||
# if there is a single completion candidate then maybe it is over
|
||||
append_space = len(lines) == 1
|
||||
for line in lines:
|
||||
comp = create_rich_completion(line, append_space)
|
||||
yield comp
|
||||
|
||||
|
||||
completer.add_one_completer("fish", fish_proc_completer, "<bash")
|
||||
|
|
Loading…
Add table
Reference in a new issue