]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
kresctl: tab-completion: stop appending space after one config layer is completed
authorFrantisek Tobias <frantisek.tobias@nic.cz>
Tue, 10 Dec 2024 07:23:44 +0000 (08:23 +0100)
committerAleš Mrázek <ales.mrazek@nic.cz>
Fri, 20 Dec 2024 21:24:22 +0000 (22:24 +0100)
python/knot_resolver/client/command.py
python/knot_resolver/client/commands/config.py
utils/shell-completion/client.bash

index e4eddf0877706aebb0cc47877288f56a8c192e78..79dd9bec21c3b074e959fbf5439a55f02c52c237 100644 (file)
@@ -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):
index de25f30aa99e57b2e94c8f1a237a3c8399428cb0..fef3ad79cb5c3f78dab3d306cae2986c1c8db882 100644 (file)
@@ -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("/")
 
index 0df57f316146f84b58ce5f9ef82506dd26e6a3eb..5cf66723b9dd36f61402a35e60953af30ab341bd 100644 (file)
@@ -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