summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrantisek Tobias <frantisek.tobias@nic.cz>2024-12-10 08:23:44 +0100
committerAleš Mrázek <ales.mrazek@nic.cz>2024-12-20 22:24:22 +0100
commita48d032e8e3e1d66e0c9c050c710a410ea8cec7b (patch)
tree957527e6c2377bb6151bbb3b3ff8d216256f63b0
parentpython: client: add completion for all config layers (diff)
downloadknot-resolver-a48d032e8e3e1d66e0c9c050c710a410ea8cec7b.tar.xz
knot-resolver-a48d032e8e3e1d66e0c9c050c710a410ea8cec7b.zip
kresctl: tab-completion: stop appending space after one config layer is completed
-rw-r--r--python/knot_resolver/client/command.py42
-rw-r--r--python/knot_resolver/client/commands/config.py4
-rw-r--r--utils/shell-completion/client.bash4
3 files changed, 47 insertions, 3 deletions
diff --git a/python/knot_resolver/client/command.py b/python/knot_resolver/client/command.py
index e4eddf08..79dd9bec 100644
--- a/python/knot_resolver/client/command.py
+++ b/python/knot_resolver/client/command.py
@@ -1,7 +1,7 @@
import argparse
from abc import ABC, abstractmethod # pylint: disable=[no-name-in-module]
from pathlib import Path
-from typing import Dict, List, Optional, Tuple, Type, TypeVar
+from typing import Dict, List, Optional, Set, Tuple, Type, TypeVar
from urllib.parse import quote
from knot_resolver.constants import API_SOCK_FILE, CONFIG_FILE
@@ -16,10 +16,50 @@ CompWords = Dict[str, Optional[str]]
COMP_DIRNAMES = "#dirnames#"
COMP_FILENAMES = "#filenames#"
+COMP_NOSPACE = "#nospace#"
_registered_commands: List[Type["Command"]] = []
+def get_mutually_exclusive_commands(parser: argparse.ArgumentParser) -> List[Set[str]]:
+ command_names: List[Set[str]] = []
+ for group in parser._mutually_exclusive_groups: # noqa: SLF001
+ command_names.append(set())
+ for action in group._group_actions: # noqa: SLF001
+ if action.option_strings:
+ command_names[-1].update(action.option_strings)
+ return command_names
+
+
+def is_unique_and_new(arg: str, args: Set[str], exclusive: List[Set[str]], last: str) -> bool:
+ if arg not in args:
+ for excl in exclusive:
+ if arg in excl:
+ for cmd in excl:
+ if cmd in args:
+ return False
+ return True
+
+ return arg == last
+
+
+def get_subparsers_words(
+ subparser_actions: List[argparse.Action], args: Set[str], exclusive: List[Set[str]], last: str
+) -> CompWords:
+ words: CompWords = {}
+ for action in subparser_actions:
+ if isinstance(action, argparse._SubParsersAction) and action.choices: # noqa: SLF001
+ for choice, parser in action.choices.items():
+ if is_unique_and_new(choice, args, exclusive, last):
+ words[choice] = parser.description
+ else:
+ for opt in action.option_strings:
+ if is_unique_and_new(opt, args, exclusive, last):
+ words[opt] = action.help
+
+ return words
+
+
def get_parser_action(name: str, parser_actions: List[argparse.Action]) -> Optional[argparse.Action]:
for action in parser_actions:
if (action.choices and name in action.choices) or (action.option_strings and name in action.option_strings):
diff --git a/python/knot_resolver/client/commands/config.py b/python/knot_resolver/client/commands/config.py
index de25f30a..fef3ad79 100644
--- a/python/knot_resolver/client/commands/config.py
+++ b/python/knot_resolver/client/commands/config.py
@@ -3,7 +3,7 @@ import sys
from enum import Enum
from typing import List, Literal, Optional, Tuple, Type
-from knot_resolver.client.command import Command, CommandArgs, CompWords, comp_get_words, register_command
+from knot_resolver.client.command import COMP_NOSPACE, Command, CommandArgs, CompWords, comp_get_words, register_command
from knot_resolver.datamodel import KresConfig
from knot_resolver.utils.modeling.parsing import DataFormat, parse_json, try_to_parse
from knot_resolver.utils.requests import request
@@ -124,6 +124,8 @@ class ConfigCommand(Command):
if nargs > 1 and args[-2] in ["-p", "--path"]:
words: CompWords = {}
+ words[COMP_NOSPACE] = None
+
path = args[-1]
path_nodes = path.split("/")
diff --git a/utils/shell-completion/client.bash b/utils/shell-completion/client.bash
index 0df57f31..5cf66723 100644
--- a/utils/shell-completion/client.bash
+++ b/utils/shell-completion/client.bash
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#/usr/bin/env bash
_kresctl_completion()
{
@@ -15,6 +15,8 @@ _kresctl_completion()
args="$args${args:+ }-d"
elif [[ "$opt" == "#filenames#" ]]; then
args="$args${args:+ }-f"
+ elif [[ "$opt" == "#nospace#" ]]; then
+ compopt -o nospace
else
words="$words${words:+ }$opt"
fi