Update completer cli (#4299)

* completers: Add new completers after the non-exclusives

* completer: Print whether a completer is non-exclusive

* news: Add update-completer-cli
This commit is contained in:
Daniel Shimon 2021-05-30 09:42:55 +03:00 committed by GitHub
parent 214997d170
commit 4c055d82e8
Failed to generate hash of commit
4 changed files with 86 additions and 6 deletions

View file

@ -0,0 +1,24 @@
**Added:**
* <news item>
**Changed:**
* The ``completer add`` command after the non-exclusive completers.
This means it will not block them from adding their completions.
**Deprecated:**
* <news item>
**Removed:**
* <news item>
**Fixed:**
* <news item>
**Security:**
* <news item>

View file

@ -0,0 +1,35 @@
import pytest
from xonsh.built_ins import XSH
from xonsh.completers._aliases import add_one_completer
from xonsh.completers.tools import non_exclusive_completer
SIMPLE = lambda: None
NON_EXCLUSIVE = non_exclusive_completer(lambda: None)
@pytest.mark.parametrize(
"initial, exp",
(
({}, ["new"]),
({"simp": SIMPLE}, ["new", "simp"]),
({"nx": NON_EXCLUSIVE}, ["nx", "new"]),
({"nx": NON_EXCLUSIVE, "simp": SIMPLE}, ["nx", "new", "simp"]),
(
{"ctx1": NON_EXCLUSIVE, "ctx2": NON_EXCLUSIVE, "simp": SIMPLE},
["ctx1", "ctx2", "new", "simp"],
),
(
{"ctx1": NON_EXCLUSIVE, "ctx2": NON_EXCLUSIVE, "simp": SIMPLE},
["ctx1", "ctx2", "new", "simp"],
),
(
{"ctx1": NON_EXCLUSIVE, "simp": SIMPLE, "ctx2": NON_EXCLUSIVE},
["ctx1", "new", "simp", "ctx2"],
),
),
)
def test_add_completer_start(monkeypatch, initial, exp):
monkeypatch.setattr(XSH, "completers", initial)
add_one_completer("new", SIMPLE, "start")
assert list(XSH.completers.keys()) == exp

View file

@ -49,7 +49,7 @@ def _register_completer(name: str, func: str, pos="start", stack=None):
position into the list of completers at which the new
completer should be added. It can be one of the following values:
* "start" indicates that the completer should be added to the start of
the list of completers (it should be run before all others)
the list of completers (it should be run before all other exclusive completers)
* "end" indicates that the completer should be added to the end of the
list of completers (it should be run after all others)
* ">KEY", where KEY is a pre-existing name, indicates that this should

View file

@ -2,7 +2,11 @@ import collections
from xonsh.parsers.completion_context import CommandContext
from xonsh.built_ins import XSH
from xonsh.completers.tools import contextual_command_completer_for, justify
from xonsh.completers.tools import (
contextual_command_completer_for,
justify,
is_exclusive_completer,
)
@contextual_command_completer_for("completer")
@ -47,8 +51,20 @@ def complete_completer(command: CommandContext):
def add_one_completer(name, func, loc="end"):
new = collections.OrderedDict()
if loc == "start":
# Add new completer before the first exclusive one.
# We don't want new completers to be before the non-exclusive ones,
# because then they won't be used when this completer is successful.
# On the other hand, if the new completer is non-exclusive,
# we want it to be before all other exclusive completers so that is will always work.
items = list(XSH.completers.items())
first_exclusive = next(
(i for i, (_, v) in enumerate(items) if is_exclusive_completer(v)),
len(items),
)
for k, v in items[:first_exclusive]:
new[k] = v
new[name] = func
for (k, v) in XSH.completers.items():
for k, v in items[first_exclusive:]:
new[k] = v
elif loc == "end":
for (k, v) in XSH.completers.items():
@ -73,17 +89,22 @@ def add_one_completer(name, func, loc="end"):
def list_completers():
"""List the active completers"""
o = "Registered Completer Functions: \n"
o = "Registered Completer Functions: (NX = Non Exclusive)\n\n"
non_exclusive = " [NX]"
_comp = XSH.completers
ml = max((len(i) for i in _comp), default=0)
exclusive_len = ml + len(non_exclusive) + 1
_strs = []
for c in _comp:
if _comp[c].__doc__ is None:
doc = "No description provided"
else:
doc = " ".join(_comp[c].__doc__.split())
doc = justify(doc, 80, ml + 3)
_strs.append("{: >{}} : {}".format(c, ml, doc))
doc = justify(doc, 80, exclusive_len + 3)
if is_exclusive_completer(_comp[c]):
_strs.append("{: <{}} : {}".format(c, exclusive_len, doc))
else:
_strs.append("{: <{}} {} : {}".format(c, ml, non_exclusive, doc))
return o + "\n".join(_strs) + "\n"