]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
kresctl: tab-completion: enable config completion
authorFrantisek Tobias <frantisek.tobias@nic.cz>
Tue, 15 Oct 2024 10:40:23 +0000 (12:40 +0200)
committerFrantisek Tobias <frantisek.tobias@nic.cz>
Tue, 15 Oct 2024 10:40:23 +0000 (12:40 +0200)
python/knot_resolver/client/commands/config.py

index 438bb3999b39537335796329a55e6257b2195d39..844bed6fce905c3153393c483239ae389acd470e 100644 (file)
@@ -1,7 +1,7 @@
 import argparse
 import sys
 from enum import Enum
-from typing import List, Literal, Optional, Tuple, Type
+from typing import Any, Dict, List, Literal, Optional, Tuple, Type
 
 from knot_resolver.client.command import Command, CommandArgs, CompWords, register_command
 from knot_resolver.utils.modeling.parsing import DataFormat, parse_json, try_to_parse
@@ -22,54 +22,54 @@ def operation_to_method(operation: Operations) -> Literal["PUT", "GET", "DELETE"
     return "GET"
 
 
-def _properties_words(props: Dict[str, Any]) -> CompWords:
-    words: CompWords = {}
-    for name, prop in props.items():
-        words[name] = prop["description"] if "description" in prop else None
-    return words
-
-
-def _path_comp_words(node: str, nodes: List[str], props: Dict[str, Any]) -> CompWords:
-    i = nodes.index(node)
-    ln = len(nodes[i:])
-
-    # if node is last in path, return all possible words on thi level
-    if ln == 1:
-        return _properties_words(props)
-    # if node is valid
-    elif node in props:
-        node_schema = props[node]
-
-        if "anyOf" in node_schema:
-            for item in node_schema["anyOf"]:
-                print(item)
-
-        elif "type" not in node_schema:
-            pass
-
-        elif node_schema["type"] == "array":
-            if ln > 2:
-                # skip index for item in array
-                return _path_comp_words(nodes[i + 2], nodes, node_schema["items"]["properties"])
-            if "enum" in node_schema["items"]:
-                print(node_schema["items"]["enum"])
-            return {"0": "first array item", "-": "last array item"}
-        elif node_schema["type"] == "object":
-            if "additionalProperties" in node_schema:
-                print(node_schema)
-            return _path_comp_words(nodes[i + 1], nodes, node_schema["properties"])
-#         return {}
-
-        # arrays/lists must be handled sparately
-        if node_schema["type"] == "array":
-            if ln > 2:
-                # skip index for item in array
-                return _path_comp_words(nodes[i + 2], nodes, node_schema["items"]["properties"])
-            return {"0": "first array item", "-": "last array item"}
-        return _path_comp_words(nodes[i + 1], nodes, node_schema["properties"])
-    else:
-        # if node is not last or valid, value error
-        raise ValueError(f"unknown config path node: {node}")
+def _properties_words(props: Dict[str, Any]) -> CompWords:
+    words: CompWords = {}
+    for name, prop in props.items():
+        words[name] = prop["description"] if "description" in prop else None
+    return words
+
+
+def _path_comp_words(node: str, nodes: List[str], props: Dict[str, Any]) -> CompWords:
+    i = nodes.index(node)
+    ln = len(nodes[i:])
+
+    # if node is last in path, return all possible words on thi level
+    if ln == 1:
+        return _properties_words(props)
+    # if node is valid
+    elif node in props:
+        node_schema = props[node]
+
+        if "anyOf" in node_schema:
+            for item in node_schema["anyOf"]:
+                print(item)
+
+        elif "type" not in node_schema:
+            pass
+
+        elif node_schema["type"] == "array":
+            if ln > 2:
+                # skip index for item in array
+                return _path_comp_words(nodes[i + 2], nodes, node_schema["items"]["properties"])
+            if "enum" in node_schema["items"]:
+                print(node_schema["items"]["enum"])
+            return {"0": "first array item", "-": "last array item"}
+        elif node_schema["type"] == "object":
+            if "additionalProperties" in node_schema:
+                print(node_schema)
+            return _path_comp_words(nodes[i + 1], nodes, node_schema["properties"])
+        # return {}
+
+        # arrays/lists must be handled sparately
+        if node_schema["type"] == "array":
+            if ln > 2:
+                # skip index for item in array
+                return _path_comp_words(nodes[i + 2], nodes, node_schema["items"]["properties"])
+            return {"0": "first array item", "-": "last array item"}
+        return _path_comp_words(nodes[i + 1], nodes, node_schema["properties"])
+    else:
+        # if node is not last or valid, value error
+        raise ValueError(f"unknown config path node: {node}")
 
 
 @register_command
@@ -170,8 +170,15 @@ class ConfigCommand(Command):
 
     @staticmethod
     def completion(parser: argparse.ArgumentParser, args: Optional[List[str]] = None) -> CompWords:
+        words = Command.completion(parser)
         if args is None:
-            return Command.completion(parser)
+            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)
+
 
         # for arg in args:
         #     if arg in words: