]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
kresctl: tab-completion: display config keywords in config completion docs-develop-kres-ph09xl/deployments/5364
authorFrantisek Tobias <frantisek.tobias@nic.cz>
Fri, 18 Oct 2024 11:26:10 +0000 (13:26 +0200)
committerFrantisek Tobias <frantisek.tobias@nic.cz>
Fri, 18 Oct 2024 11:26:10 +0000 (13:26 +0200)
python/knot_resolver/client/command.py
python/knot_resolver/client/commands/completion.py
python/knot_resolver/client/commands/config.py

index 6c1334b1ac6fb7cf2468d551624c82dbcedf159c..b0ae38ccdbb8c2d14430b8058102976812544632 100644 (file)
@@ -139,5 +139,36 @@ class Command(ABC):
         raise NotImplementedError()
 
     @staticmethod
-    def completion(parser: argparse.ArgumentParser) -> CompWords:
-        return get_subparsers_words(parser._actions)  # pylint: disable=W0212
+    def completion(parser: argparse.ArgumentParser, args: Optional[List[str]]) -> CompWords:
+        words: CompWords = get_subparsers_words(parser._actions)  # Get subparser words
+        if args is None or args == ['']:
+            return words
+
+        subparsers = parser._subparsers
+
+        if subparsers:
+            words = get_subparsers_words(subparsers._actions)
+
+            for i in range(len(args)):
+                uarg = args[i]
+                subparser = get_subparser_by_name(uarg, subparsers._actions)  # pylint: disable=W0212
+
+                # print(f"uarg: {uarg}, {args}, {words}\n")
+                if subparser:
+                    try:
+                        cmd = get_subparser_command(subparser)
+                        subparser_args = args[i + 1 :]
+                        words = cmd.completion(subparser, subparser_args)
+                    except:
+                        return get_subparsers_words(subparser._actions)
+
+                    break
+                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"]:
+                    # Continue if the argument is a valid subparser
+                    continue
+        return words
index 3fca6314953877e84285236baf2f4a51d03b0820..cffd7e0df0b5af42063fec2bc5af8b120f98cc50 100644 (file)
@@ -60,32 +60,7 @@ class CompletionCommand(Command):
         return completion, CompletionCommand
 
     def run(self, args: CommandArgs) -> None:
-        subparsers = args.parser._subparsers
-        words: CompWords = {}
-
-        if subparsers:
-            words = get_subparsers_words(subparsers._actions)
-
-            uargs = iter(self.comp_args)
-            for uarg in uargs:
-                subparser = get_subparser_by_name(uarg, subparsers._actions)  # pylint: disable=W0212
-
-                if subparser:
-                    cmd: Command = get_subparser_command(subparser)
-                    subparser_args = self.comp_args[self.comp_args.index(uarg) + 1 :]
-                    if subparser_args or self.space:
-                        if isinstance(cmd, ConfigCommand):
-                            words = cmd.completion(subparser, subparser_args)
-                        else:
-                            words = cmd.completion(subparser)
-                #     break
-                # elif uarg in ["-s", "--socket", "-c", "--config"]:
-                #     # if arg is socket config, skip next arg
-                #     next(uargs)
-                #     continue
-                # elif uarg in words:
-                #     # uarg is valid (complete) arg, continue
-                #     continue
+        words = Command.completion(args.parser, self.comp_args)
 
         # print completion words
         # based on required bash/fish shell format
index 844bed6fce905c3153393c483239ae389acd470e..8523cf2bf6e7d6b12d3675a173216921eaa305b8 100644 (file)
@@ -3,9 +3,10 @@ import sys
 from enum import Enum
 from typing import Any, Dict, List, Literal, Optional, Tuple, Type
 
-from knot_resolver.client.command import Command, CommandArgs, CompWords, register_command
+from knot_resolver.client.command import Command, CommandArgs, CompWords, register_command, get_subparser_by_name, get_subparsers_words
 from knot_resolver.utils.modeling.parsing import DataFormat, parse_json, try_to_parse
 from knot_resolver.utils.requests import request
+from knot_resolver.datamodel import KresConfig
 
 
 class Operations(Enum):
@@ -152,6 +153,24 @@ 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."
@@ -170,15 +189,30 @@ class ConfigCommand(Command):
 
     @staticmethod
     def completion(parser: argparse.ArgumentParser, args: Optional[List[str]] = None) -> CompWords:
-        words = Command.completion(parser)
-        if args is None:
-            return words
-
-        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)
-
+        if args is None or len(args) <= 1:
+            return Command.completion(parser, args)
+
+        words: CompWords = get_subparsers_words(parser._actions)
+        subparsers = parser._subparsers
+
+        if subparsers:
+            for i in range(len(args)):
+                uarg = args[i]
+                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:
@@ -191,7 +225,9 @@ class ConfigCommand(Command):
         #         return _path_comp_words(config_path[0], config_path, schema_props)
         #     else:
         #         break
-        return {}
+
+        return words
+
 
     def run(self, args: CommandArgs) -> None:
         if not self.operation: