From 2b3ad08f830e692ff40be7df550e50e3de22f1f8 Mon Sep 17 00:00:00 2001 From: Frantisek Tobias Date: Tue, 15 Oct 2024 12:40:23 +0200 Subject: [PATCH] kresctl: tab-completion: enable config completion --- .../knot_resolver/client/commands/config.py | 107 ++++++++++-------- 1 file changed, 57 insertions(+), 50 deletions(-) diff --git a/python/knot_resolver/client/commands/config.py b/python/knot_resolver/client/commands/config.py index 438bb3999..844bed6fc 100644 --- a/python/knot_resolver/client/commands/config.py +++ b/python/knot_resolver/client/commands/config.py @@ -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: -- 2.47.3