5 from .common import CmdTable, ShconfigException
6 from .common import select, cmd, get_config_name
8 from lcfg2.config import ConfigEnvironment
9 from lcfg2.common import NodeProperty, NodeDependency, ConfigNodeError
11 class Commands(CmdTable):
12 def __init__(self, env: ConfigEnvironment):
17 def __get_node(self, name: str):
18 node_name = name.removeprefix("CONFIG_").lower()
19 node = self.__env.get_node(node_name)
21 raise ShconfigException(f"no such config: {name}")
24 def __get_opt_line(self, node, color_hint = False):
26 name = f"CONFIG_{node._name.upper()}"
27 value = NodeProperty.Value[node]
28 enabled = NodeProperty.Enabled[node]
29 hidden = NodeProperty.Hidden[node]
30 ro = NodeProperty.Readonly[node]
32 status = f"{select(not enabled, 'x', '.')}" \
33 f"{select(ro, 'r', '.')}" \
34 f"{select(hidden, 'h', '.')}" \
36 val_txt = f"{value if value is not None else '<?>'}"
42 elif isinstance(value, str):
43 val_txt = f'"{val_txt}"'
45 line = f"[{status}] {name}"
46 to_pad = max(aligned - len(line), 4)
47 line = f"{line} {'.' * to_pad} {val_txt}"
49 if color_hint and not enabled:
50 line = f"\x1b[90;49m{line}\x1b[0m"
53 def __format_config_list(self, nodes):
58 _l = disabled if not NodeProperty.Enabled[node] else lines
59 _l.append(self.__get_opt_line(node, True))
64 "\t---- disabled ----",
78 for exe in self._cmd_map:
84 Show all configurable options
90 " (flags) CONFIG_NAME ..... VALUE",
93 " x Config is disabled",
94 " r Read-Only config",
102 "Defined configuration terms",
106 lines += self.__format_config_list(self.__env.terms())
108 pydoc.pager("\n".join(lines))
111 def __fn_set(self, name: str, value):
113 Update a configurable option's value
116 node = self.__get_node(name)
118 raise ShconfigException(f"no such config: {name}")
120 if NodeProperty.Readonly[node]:
121 raise ShconfigException(f"node is read only")
124 NodeProperty.Value[node] = value
126 except ConfigNodeError as e:
130 def __fn_dep(self, name: str):
132 Show the dependency chain and boolean conditionals
135 def __print_dep_recursive(env, node, inds = 0):
137 dep: NodeDependency = NodeProperty.Dependency[node]
139 state = 'enabled' if NodeProperty.Enabled[node] else 'disabled'
140 print(f"{indent}* {node._name} (currently {state})")
144 print(f" {indent}predicate: {dep._expr}")
145 print(f" {indent}dependents:")
146 for name in dep._names:
147 n = env.get_node(name)
148 __print_dep_recursive(env, n, inds + 6)
150 node = self.__get_node(name)
151 __print_dep_recursive(self.__env, node)
153 @cmd("opt", "val", "v")
154 def __fn_opt(self, name: str):
156 Show the current value and flags of selected options
159 node = self.__get_node(name)
160 print(self.__get_opt_line(node))
162 @cmd("what", "help", "?")
163 def __fn_what(self, name: str):
165 Show the documentation associated with the option
168 node = self.__get_node(name)
169 help = NodeProperty.HelpText[node]
170 help = "<no help message>" if not help else help
173 print(textwrap.indent(help.strip(), " |\t", lambda _:True))
178 def __fn_affect(self, name: str):
180 Show the effects of this option on other options
183 node = self.__get_node(name)
184 link = NodeProperty.Linkage[node]
189 for other, exprs in link.linkages():
192 print(f" > when {expr}")
196 def __fn_search(self, fuzz: str):
198 Perform fuzzy search on configs (accept regex)
202 expr = re.compile(fuzz)
203 for node in self.__env.terms():
204 name = get_config_name(node._name)
205 if not expr.findall(name):
213 lines = self.__format_config_list(nodes)
215 pydoc.pager("\n".join(lines))