""" Silique (https://www.silique.fr) Copyright (C) 2022-2025 This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . """ from rich.console import Console from rich.tree import Tree from rich.table import Table from rich.panel import Panel from ..i18n import _ from ..util import CommonOutput class OutputFamily(CommonOutput): level = 10 name = "console" variable_hidden_color = "orange1" variable_normal_color = None value_unmodified_color = "gold1" value_modified_color = "green" value_default_color = None error_color = 'bright_red' def run(self): max_width = self.root.rougailconfig["display.console.max_width"] self.console = Console(force_terminal=True, width=max_width) with self.console.capture() as capture: ret = self.root.print() return ret, capture.get() def print(self) -> None: ret = self.root.exporter() for out in self.out: self.console.print(out) return ret def header(self): caption_line = "" if self.root_family.variable_default_enable: caption_line += _("Variable") + "\n" if self.root_family.variable_hidden_enable: caption_line += f'[{self.variable_hidden_color}]{_("Unmodifiable variable")}[/{self.variable_hidden_color}]\n' header_value = "" if self.root_family.value_unmodified_enable: header_value += f'[{self.value_unmodified_color}]{_("Default value")}[/{self.value_unmodified_color}]\n' if self.root_family.value_modified_enable: header_value += f'[{self.value_modified_color}]{_("Modified value")}[/{self.value_modified_color}]\n' if self.root_family.value_default_enable: header_value += f'(:hourglass_flowing_sand: {_("Original default value")})\n' caption = Table.grid(padding=1, collapse_padding=True) caption.pad_edge = False caption.add_row(caption_line[:-1], header_value[:-1]) self.out.append(Panel.fit(caption, title=_("Caption"))) # layers = Table.grid(padding=1, collapse_padding=True) caption.pad_edge = False if self.root.layer_datas: max_len = 0 for datas in self.root.layer_datas.values(): for data in datas.values(): max_len = max(max_len, len(data)) display_layers = ["" for i in range(max_len)] for datas in self.root.layer_datas.values(): for data in datas.values(): last_index = len(data) - 1 for idx in range(max_len): if last_index < idx: display_layers[idx] += "\n" else: display_layers[idx] += data[idx] + "\n" layers.add_row(*[layer[:-1] for layer in display_layers]) self.out.append(Panel.fit(layers, title=_("Layers"))) def error_header(self): tree = Tree( f"[bold][{self.error_color}]:stop_sign: {_('ERRORS')}[/{self.error_color}][/bold]", guide_style=f"bold {self.error_color}", ) self.out.append(tree) return tree def display_error(self, tree, error, level): return tree.add(error) def display_warnings( self, warnings: list, ) -> None: tree = Tree( f"[bold][bright_yellow]:bell: {_('WARNINGS')}[/bright_yellow][/bold]", guide_style="bold bright_yellow", ) for warning in warnings: tree.add(warning) self.out.append(tree) def add_variable( self, *args, **kwargs, ): key, value = super().add_variable(*args, **kwargs) if isinstance(value, list): subtree = self.get_tree().add( ":notebook: " + _("{0}:").format(key), guide_style="bold bright_blue", ) for val in value: subtree.add(str(val)) else: self.get_tree().add(":notebook: " + _("{0}: {1}").format(key, value)) def colorize( self, values, option=None, ) -> str: multi = False ret = [] default = [] for idx, data in enumerate(values): value = data["value"] if isinstance(value, list): multi = True else: value = [value] for vidx, val in enumerate(value): if len(ret) == vidx: ret.append("") default.append(False) if idx: if not default[vidx]: if ret[vidx]: ret[vidx] += " " ret[vidx] += "(" default[vidx] = True else: ret[vidx] += " " ret[vidx] += ":hourglass_flowing_sand: " if option: val = self.convert_value( option, val, ) color = data["color"] if color is not None: ret[vidx] += f"[{color}]{val}[/{color}]" else: ret[vidx] += val loaded_from = data["loaded_from"] if loaded_from: ret[vidx] += f" :arrow_backward: {loaded_from}" for idx in range(len(ret)): if default[idx]: ret[idx] += ")" if not multi: if not ret: return "" return ret[0] return ret def get_tree(self): if self.tree is None: if self.parent is None: tree = Tree else: tree = self.parent.add # if self.is_leader: # self.tree = tree( # ":notebook: " + _("{0}:").format(self.family), # guide_style="bold bright_blue", # ) # elif self.no_icon: if self.no_icon: self.tree = tree( self.family, guide_style="bold bright_blue", ) else: self.tree = tree( f":open_file_folder: {self.family}", guide_style="bold bright_blue", ) return self.tree