825ffa92c5ddb49f70d927febd4322f543e2e4ba
[lunaix-os.git] / lunaix-os / scripts / build-tools / shared / shconfig / commands.py
1 import textwrap
2 import pydoc
3
4 from .common import CmdTable, ShconfigException
5 from .common import select, cmd
6
7 from lcfg2.config   import ConfigEnvironment
8 from lcfg2.common   import NodeProperty, NodeDependency, ConfigNodeError
9
10 class Commands(CmdTable):
11     def __init__(self, env: ConfigEnvironment):
12         super().__init__()
13
14         self.__env = env
15
16     def __get_node(self, name: str):
17         node_name = name.removeprefix("CONFIG_").lower()
18         node = self.__env.get_node(node_name)
19         if node is None:
20             raise ShconfigException(f"no such config: {name}")
21         return node
22     
23     def __get_opt_line(self, node, color_hint = False):
24         aligned = 40
25         name    = f"CONFIG_{node._name.upper()}"
26         value   = NodeProperty.Value[node]
27         enabled = NodeProperty.Enabled[node]
28         hidden  = NodeProperty.Hidden[node]
29         ro      = NodeProperty.Readonly[node]
30
31         status  = f"{select(not enabled, 'x', '.')}"          \
32                 f"{select(ro, 'r', '.')}"          \
33                 f"{select(hidden, 'h', '.')}"      \
34                                     
35         val_txt = f"{value if value is not None else '<?>'}"
36                 
37         line = f"[{status}] {name}"
38         to_pad = max(aligned - len(line), 4)
39         line = f"{line} {'.' * to_pad} {val_txt}"
40
41         if color_hint and not enabled:
42             line = f"\x1b[90;49m{line}\x1b[0m"
43         return line
44     
45     @cmd("help", "h")
46     def __fn_help(self):
47         """
48         Print this message
49         """
50
51         print()
52         for exe in self._cmd_map:
53             print(exe, "\n")
54
55     @cmd("show", "ls")
56     def __fn_show(self):
57         """
58         Show all configurable options
59         """
60         
61         lines = [
62             "Display format:",
63             "",
64             "        (flags) CONFIG_NAME ..... VALUE",
65             " ",
66             "   (flags)",
67             "      x    Config is disabled",
68             "      r    Read-Only config",
69             "      h    Hidden config",
70             "",
71             "",
72             "Defined configuration terms",
73             ""
74         ]
75
76         for node in self.__env.terms():
77             lines.append(self.__get_opt_line(node, True))    
78
79         pydoc.pager("\n".join(lines))
80
81     @cmd("set")
82     def __fn_set(self, name: str, value):
83         """
84         Update a configurable option's value
85         """
86         
87         node = self.__get_node(name)
88         if node is None:
89             raise ShconfigException(f"no such config: {name}")
90         
91         if NodeProperty.Readonly[node]:
92             raise ShconfigException(f"node is read only")
93         
94         try:
95             NodeProperty.Value[node] = value
96             self.__env.refresh()
97         except ConfigNodeError as e:
98             print(e)
99
100     @cmd("dep")
101     def __fn_dep(self, name: str):
102         """
103         Show the dependency chain and boolean conditionals
104         """
105
106         def __print_dep_recursive(env, node, inds = 0):
107             indent = " "*inds
108             dep: NodeDependency = NodeProperty.Dependency[node]
109             
110             state = 'enabled' if NodeProperty.Value[node] else 'disabled'
111             print(f"{indent}* {node._name} (currently {state})")
112             if dep is None:
113                 return
114             
115             print(f"  {indent}predicate: {dep._expr}")
116             print(f"  {indent}dependents:")
117             for name in dep._names:
118                 n = env.get_node(name)
119                 __print_dep_recursive(env, n, inds + 6)
120
121         node = self.__get_node(name)
122         __print_dep_recursive(self.__env, node)
123
124     @cmd("opt", "val", "v")
125     def __fn_opt(self, name: str):
126         """
127         Show the current value and flags of selected options
128         """
129
130         node = self.__get_node(name)        
131         print(self.__get_opt_line(node))
132
133     @cmd("what", "?")
134     def __fn_what(self, name: str):
135         """
136         Show the documentation associated with the option
137         """
138
139         node = self.__get_node(name)
140         help = NodeProperty.HelpText[node]
141         help = "<no help message>" if not help else help
142
143         print()
144         print(textwrap.indent(help.strip(), "  |\t", lambda _:True))
145         print()
146
147
148     @cmd("effect", "link")
149     def __fn_effect(self, name: str):
150         """
151         Show the effects of this option on other options
152         """
153         
154         node = self.__get_node(name)
155         link = NodeProperty.Linkage[node]
156
157         if not link:
158             return
159         
160         for other, exprs in link.linkages():
161             print(f" {other}:")
162             for expr in exprs:
163                 print(f"   > when {expr}")
164             print()
165