Add support for comma separated completions

This commit is contained in:
Kovid Goyal
2021-06-26 10:52:14 +05:30
parent 71cd92da29
commit 051374cd55
2 changed files with 44 additions and 9 deletions

View File

@@ -164,11 +164,23 @@ def option_help_map() -> Dict[str, str]:
def complete_choices(ans: Completions, prefix: str, title: str, key: str, comma_separated: bool) -> None:
choices = {}
word_transforms = {}
effective_prefix = prefix
hidden_prefix = ''
if comma_separated:
effective_prefix = prefix.split(',')[-1]
hidden_prefix = ','.join(prefix.split(',')[:-1])
if hidden_prefix:
hidden_prefix += ','
for line in lines_from_command('ssh', '-Q', key):
q = line.strip()
if q.startswith(prefix):
if q.startswith(effective_prefix):
if comma_separated:
tq = q
q = hidden_prefix + q + ','
word_transforms[q] = tq
choices[q] = ''
ans.add_match_group(title, choices)
ans.add_match_group(title, choices, trailing_space=not comma_separated, word_transforms=word_transforms)
def complete_arg(ans: Completions, option_flag: str, prefix: str = '') -> None:

View File

@@ -49,14 +49,28 @@ serializers: Dict[str, Callable] = {}
class MatchGroup:
def __init__(self, x: Union[Dict[str, str], Iterable[str]], trailing_space: bool = True, is_files: bool = False):
def __init__(
self, x: Union[Dict[str, str], Iterable[str]],
trailing_space: bool = True,
is_files: bool = False,
word_transforms: Optional[Dict[str, str]] = None,
):
self.mdict = x if isinstance(x, dict) else dict.fromkeys(x, '')
self.trailing_space = trailing_space
self.is_files = is_files
self.word_transforms = word_transforms or {}
def __iter__(self) -> Iterator[str]:
return iter(self.mdict)
def transformed_words(self) -> Iterator[str]:
for w in self:
yield self.word_transforms.get(w, w)
def transformed_items(self) -> Iterator[Tuple[str, str]]:
for w, desc in self.items():
yield self.word_transforms.get(w, w), desc
def items(self) -> Iterator[Tuple[str, str]]:
return iter(self.mdict.items())
@@ -94,8 +108,13 @@ class Completions:
self.match_groups: Dict[str, MatchGroup] = {}
self.delegate: Delegate = Delegate()
def add_match_group(self, name: str, x: Union[Dict[str, str], Iterable[str]], trailing_space: bool = True, is_files: bool = False) -> MatchGroup:
self.match_groups[name] = m = MatchGroup(x, trailing_space, is_files)
def add_match_group(
self, name: str, x: Union[Dict[str, str], Iterable[str]],
trailing_space: bool = True,
is_files: bool = False,
word_transforms: Optional[Dict[str, str]] = None
) -> MatchGroup:
self.match_groups[name] = m = MatchGroup(x, trailing_space, is_files, word_transforms)
return m
@@ -188,6 +207,9 @@ def zsh_output_serializer(ans: Completions) -> str:
width = screen.cols
def fmt_desc(word: str, desc: str, max_word_len: int) -> Iterator[str]:
if not desc:
yield word
return
desc = prettify(desc.splitlines()[0])
multiline = False
if wcswidth(word) > max_word_len:
@@ -218,14 +240,15 @@ def zsh_output_serializer(ans: Completions) -> str:
cmd.extend(('-p', shlex.quote(common_prefix)))
matches = MatchGroup({k[len(common_prefix):]: v for k, v in matches.items()})
has_descriptions = any(matches.values())
if has_descriptions:
if has_descriptions or matches.word_transforms:
lines.append('compdescriptions=(')
sz = max(map(wcswidth, matches))
sz = max(map(wcswidth, matches.transformed_words()))
limit = min(16, sz)
for word, desc in matches.items():
for word, desc in matches.transformed_items():
lines.extend(map(shlex.quote, fmt_desc(word, desc, limit)))
lines.append(')')
cmd.append('-l')
if has_descriptions:
cmd.append('-l')
cmd.append('-d')
cmd.append('compdescriptions')
cmd.append('--')