mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 00:14:41 +01:00
Use substring for env completion and better way to sort list (#5388)
### Motivation It's very annoying to search env variable exactly by lprefix. The better is to search by substring and sort results by the position of substring and then alphabetically. Closes #5386 ### Before ```xsh $TRA<Tab> # nothing ``` ### After ```xsh $TRA<Tab> # 'XONSH_TRACE_COMPLETIONS', # 'XONSH_TRACE_SUBPROC', # 'XONSH_TRACE_SUBPROC_FUNC', # 'XONSH_TRACEBACK_LOGFILE', # 'XONSH_SHOW_TRACEBACK', # 'VC_GIT_INCLUDE_UNTRACKED' ``` ## For community ⬇️ **Please click the 👍 reaction instead of leaving a `+1` or 👍 comment** --------- Co-authored-by: a <1@1.1> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
21da30e753
commit
a3e8b1a025
5 changed files with 63 additions and 20 deletions
23
news/env_completion.rst
Normal file
23
news/env_completion.rst
Normal file
|
@ -0,0 +1,23 @@
|
|||
**Added:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Changed:**
|
||||
|
||||
* Env variables completion: now use substring for search and then sort results by the position of substring and then alphabetically. PR 5388.
|
||||
|
||||
**Deprecated:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Removed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Fixed:**
|
||||
|
||||
* <news item>
|
||||
|
||||
**Security:**
|
||||
|
||||
* <news item>
|
|
@ -12,30 +12,30 @@ def parser():
|
|||
@pytest.mark.parametrize(
|
||||
"cmd",
|
||||
(
|
||||
"ls $WO",
|
||||
"ls /home/$WO",
|
||||
"ls '/home/$WO'",
|
||||
"ls @('hi ' + $WO",
|
||||
"ls $WOW",
|
||||
"ls /home/$WOW",
|
||||
"ls '/home/$WOW'",
|
||||
"ls @('hi ' + $WOW",
|
||||
),
|
||||
)
|
||||
def test_simple(cmd, xession, monkeypatch, parser):
|
||||
xession.env.update({"WOW": 1})
|
||||
xession.env.update({"WOWZER": 1})
|
||||
|
||||
context = parser.parse(cmd, len(cmd))
|
||||
comps, lprefix = complete_environment_vars(context)
|
||||
# account for the ending quote
|
||||
if cmd[-1] in "'":
|
||||
assert lprefix == 4
|
||||
assert lprefix == 5
|
||||
else:
|
||||
assert lprefix == 3
|
||||
assert set(comps) == {"$WOW"}
|
||||
assert lprefix == 4
|
||||
assert set(comps) == {"$WOWZER"}
|
||||
|
||||
|
||||
def test_rich_completions(xession, monkeypatch, parser):
|
||||
xession.env.update({"WOW": 1})
|
||||
xession.env.register("WOW", type=int, doc="Nice Docs!")
|
||||
xession.env.update({"WOWZER": 1})
|
||||
xession.env.register("WOWZER", type=int, doc="Nice Docs!")
|
||||
|
||||
context = parser.parse("$WO", 3)
|
||||
context = parser.parse("$WOW", 4)
|
||||
completion = next(complete_environment_vars(context)[0])
|
||||
assert completion.display == "$WOW [int]"
|
||||
assert completion.display == "$WOWZER [int]"
|
||||
assert completion.description == "Nice Docs!"
|
||||
|
|
|
@ -155,3 +155,16 @@ def test_non_exclusive(completer, completers_mock, middle_result, exp):
|
|||
completers_mock["c"] = non_exclusive_completer(lambda *a: {"c1", "c2"})
|
||||
|
||||
assert completer.complete("", "", 0, 0, {})[0] == exp
|
||||
|
||||
|
||||
def test_env_completer_sort(completer, completers_mock):
|
||||
@contextual_command_completer
|
||||
def comp(context: CommandContext):
|
||||
return {"$SUPER_WOW", "$WOW1", "$WOW0", "$MID_WOW"}
|
||||
|
||||
completers_mock["a"] = comp
|
||||
|
||||
comps = completer.complete(
|
||||
"$WOW", "$WOW", 4, 0, {}, multiline_text="'$WOW'", cursor_index=4
|
||||
)
|
||||
assert set(comps[0]) == {"$WOW0", "$WOW1", "$MID_WOW", "$SUPER_WOW"}
|
||||
|
|
|
@ -284,9 +284,18 @@ class Completer:
|
|||
)
|
||||
break
|
||||
|
||||
def sortkey(s):
|
||||
# todo: should sort with prefix > substring > fuzzy
|
||||
return s.lstrip(''''"''').lower()
|
||||
prefix = None
|
||||
if completion_context:
|
||||
prefix = completion_context.command.prefix
|
||||
if prefix.startswith("$"):
|
||||
prefix = prefix[1:]
|
||||
|
||||
def sortkey(s):
|
||||
"""Sort values by prefix position and then alphabetically."""
|
||||
return (s.lower().find(prefix.lower()), s.lower())
|
||||
else:
|
||||
# Fallback sort.
|
||||
sortkey = lambda s: s.lstrip(''''"''').lower()
|
||||
|
||||
# the last completer's lprefix is returned. other lprefix values are inside the RichCompletions.
|
||||
return tuple(sorted(completions, key=sortkey)), lprefix
|
||||
|
|
|
@ -2,7 +2,6 @@ from xonsh.built_ins import XSH
|
|||
from xonsh.completers.tools import (
|
||||
RichCompletion,
|
||||
contextual_completer,
|
||||
get_filter_function,
|
||||
non_exclusive_completer,
|
||||
)
|
||||
from xonsh.parsers.completion_context import CompletionContext
|
||||
|
@ -27,15 +26,14 @@ def complete_environment_vars(context: CompletionContext):
|
|||
lprefix = len(key) + 1
|
||||
if context.command is not None and context.command.is_after_closing_quote:
|
||||
lprefix += 1
|
||||
filter_func = get_filter_function()
|
||||
env = XSH.env
|
||||
|
||||
vars = [k for k, v in env.items() if key.lower() in k.lower()]
|
||||
return (
|
||||
RichCompletion(
|
||||
"$" + k,
|
||||
display=f"${k} [{type(v).__name__}]",
|
||||
display=f"${k} [{type(env[k]).__name__}]",
|
||||
description=env.get_docs(k).doc,
|
||||
)
|
||||
for k, v in env.items()
|
||||
if filter_func(k, key)
|
||||
for k in vars
|
||||
), lprefix
|
||||
|
|
Loading…
Add table
Reference in a new issue