]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
kresctl: tab-completion: fix config path suggestions
authorFrantisek Tobias <frantisek.tobias@nic.cz>
Thu, 31 Oct 2024 13:32:10 +0000 (14:32 +0100)
committerFrantisek Tobias <frantisek.tobias@nic.cz>
Fri, 15 Nov 2024 08:27:51 +0000 (09:27 +0100)
python/knot_resolver/client/client.py
python/knot_resolver/client/command.py
python/knot_resolver/client/commands/completion.py
python/knot_resolver/client/commands/config.py
python/knot_resolver/client/main.py
utils/shell-completion/client.bash

index 4e7d13ea953c610f00ddf22d867175555989d4da..c0be495fa933ac2582c029268f81670b4746d350 100644 (file)
@@ -22,8 +22,8 @@ class KresClient:
             args = CommandArgs(self.namespace, self.parser)
             command = args.command(self.namespace)
             command.run(args)
-        else:
-            self.parser.print_help()
+        else:
+            self.parser.print_help()
 
     def _prompt_format(self) -> str:
         bolt = "\033[1m"
index e0a0c13e9335cfd620f234dfc484f6041b6075c3..8b04b2922374b8194f82493938698d1429748661 100644 (file)
@@ -149,25 +149,21 @@ class Command(ABC):
         if subparsers:
             words = get_subparsers_words(subparsers._actions)
 
-            for i in range(len(args)):
+            i = 0
+            while i < len(args):
                 uarg = args[i]
                 subparser = get_subparser_by_name(uarg, subparsers._actions)  # pylint: disable=W0212
 
                 if subparser:
-                    try:
-                        cmd = get_subparser_command(subparser)
-                        subparser_args = args[i + 1 :]
-                        words = cmd.completion(subparser, subparser_args)
-                    except ValueError:
-                        return get_subparsers_words(subparser._actions)
-
-                    break
+                    cmd = get_subparser_command(subparser)
+                    subparser_args = args[i + 1 :]
+                    words = cmd.completion(subparser, subparser_args)
+
                 elif uarg in ["-s", "--socket", "-c", "--config"]:
                     # Skip next argument if a known flag is detected
                     i += 1
                     # next(uargs, None)
-                    continue
-                elif uarg in ["--bash", "--space"]:
+                # elif uarg in ["--bash", "--space"]:
                     # Continue if the argument is a valid subparser
-                    continue
+                i += 1
         return words
index 03f4a9c669522fb65737acc08dc1a9bc3e21652e..58601404c0215a88a5696ec5904a5c4e1aef2e93 100644 (file)
@@ -52,7 +52,7 @@ class CompletionCommand(Command):
         return completion, CompletionCommand
 
     def run(self, args: CommandArgs) -> None:
-        words = Command.completion(args.parser, self.comp_args)
+        words = Command.completion(args.parser, self.args)
 
         # print completion words
         # based on required bash/fish shell format
index 5d0b5c74beb9bf03aea1cbc2aaebd4921bff236e..9c5e116f06bd2ec08b0b3ccf8b7e7261030c3d99 100644 (file)
@@ -9,6 +9,7 @@ from knot_resolver.client.command import (
     CompWords,
     get_subparser_by_name,
     get_subparsers_words,
+    get_subparser_command,
     register_command,
 )
 from knot_resolver.datamodel import KresConfig
@@ -37,6 +38,10 @@ def _properties_words(props: Dict[str, Any]) -> CompWords:
     return words
 
 
+def get_config_path_options():
+    return _properties_words(KresConfig.json_schema()["properties"])
+
+
 def _path_comp_words(node: str, nodes: List[str], props: Dict[str, Any]) -> CompWords:
     i = nodes.index(node)
     ln = len(nodes[i:])
@@ -160,24 +165,6 @@ class ConfigCommand(Command):
             nargs="?",
         )
 
-        # GET & SET config options
-        prop_words = _properties_words(KresConfig.json_schema()["properties"])
-        for prop_key in prop_words:
-            get.add_argument(
-                prop_key,
-                help=prop_words[prop_key],
-                type=str,
-                nargs="?",
-            )
-
-            set.add_argument(
-                prop_key,
-                help=prop_words[prop_key],
-                action="store",
-                type=str,
-                nargs="?",
-            )
-
         # DELETE operation
         delete = config_subparsers.add_parser(
             "delete", help="Delete given configuration property or list item at the given index."
@@ -199,42 +186,40 @@ class ConfigCommand(Command):
         if args is None or len(args) <= 1:
             return Command.completion(parser, args)
 
-        words: CompWords = get_subparsers_words(parser._actions)
+        words: CompWords = get_subparsers_words(parser._actions)  # Get subparser words
+
         subparsers = parser._subparsers
+        schema_props: Dict[str, Any] = KresConfig.json_schema()["properties"]
 
         if subparsers:
+            words = get_subparsers_words(subparsers._actions)
+
             for i in range(len(args)):
                 uarg = args[i]
+                if uarg == "conf_get_path_subst" and \
+                    (uarg == args[-2] or (uarg == args[-3] and args[-2] not in schema_props)):
+                    return get_config_path_options()
+
                 subparser = get_subparser_by_name(uarg, subparsers._actions)  # pylint: disable=W0212
-                if subparser is not None:
-                    subparser_words = get_subparsers_words(subparser._actions)
-                    words = dict()
-                    for action in subparser._actions:
-                        if action.dest not in subparser_words:
-                            subparser_words[action.dest] = action.help or None
-
-                    words.update(subparser_words)
-
-                    subparsers = subparser._subparsers
-                    if not subparsers:
-                        break
-                else:
-                    break
-
-        # for arg in args:
-        #     if arg in words:
-        #         continue
-        #     elif arg.startswith("-"):
-        #         return words
-        #     elif arg == args[-1]:
-        #         config_path = arg[1:].split("/") if arg.startswith("/") else arg.split("/")
-        #         schema_props: Dict[str, Any] = KresConfig.json_schema()["properties"]
-        #         return _path_comp_words(config_path[0], config_path, schema_props)
-        #     else:
-        #         break
+
+                if subparser:
+                    try:
+                        cmd = get_subparser_command(subparser)
+                        subparser_args = args[i + 1 :]
+                        words = cmd.completion(subparser, subparser_args)
+                    except ValueError:
+                        subparser_words = get_subparsers_words(subparser._actions)
+
+                        words = dict()
+                        for action in subparser._actions:
+                            if action.dest not in subparser_words:
+                                subparser_words[action.dest] = action.help or None
+
+                        words.update(subparser_words)
 
         return words
 
+
     def run(self, args: CommandArgs) -> None:
         if not self.operation:
             args.subparser.print_help()
index 75cd6a77fe252b86c1f8a2a86afc95acb9e5aaf8..3ce6fa5a6d13b92bc8dda42eb22652d97c83a47a 100644 (file)
@@ -68,7 +68,8 @@ def main() -> None:
     parser = create_main_argument_parser()
     install_commands_parsers(parser)
 
-    namespace = parser.parse_args()
+    namespace, _ = parser.parse_known_args()
+    # namespace = parser.parse_args()
     client = KresClient(namespace, parser)
     client.execute()
 
index 778630fb92b2852b3e6b26dfa07d25a02eb4826f..2f3b4b45303e4100f76317c057c41610d08193c7 100644 (file)
@@ -18,6 +18,8 @@ _kresctl_filter_switches()
                 new_words[count]="$WORD"
                 ((count++))
             else
+                new_words[count]=" "
+                ((count++))
                 _kresctl_skip_next=1
             fi
         else
@@ -36,8 +38,15 @@ _kresctl_completion()
     COMPREPLY=()
     local cur opts cmp_words
 
-    cur="${COMP_WORDS[COMP_CWORD]}"
+    for (( i=2; i<${#COMP_WORDS[@]}; i++ )); do
+        if [[ "${COMP_WORDS[i-2]}" == "config" ]] &&
+           ([[ "${COMP_WORDS[i]}" == "-p" ]] || [[ "${COMP_WORDS[i]}" == "--path" ]]); then
+            COMP_WORDS[i]="conf_get_path_subst"
+            break
+        fi
+    done
 
+    cur="${COMP_WORDS[COMP_CWORD]}"
     cmp_words=($(_kresctl_filter_switches))
 
     # check if there is a word is empty
@@ -47,7 +56,7 @@ _kresctl_completion()
         # no word to complete, return all posible options
         opts=$(kresctl completion --bash --space "${cmp_words[@]}")
     else
-        opts=$(kresctl completion --bash "${cmp_words[@]}")
+        opts=$(kresctl completion --bash --space "${cmp_words[@]}")
     fi
 
     # if there is no completion from kresctl