renderers.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. from collections import OrderedDict
  2. from typing import Dict, Optional, Any, List
  3. from rich.table import Table
  4. from .variables import VariableCollection
  5. def render_variable_table(
  6. variables: VariableCollection,
  7. title: str = "Variables",
  8. show_options: bool = False,
  9. sections: Optional[OrderedDict[str, Dict[str, Any]]] = None,
  10. ) -> Table:
  11. """Build a Rich table representing variable metadata."""
  12. table = Table(title=title, header_style="bold cyan")
  13. table.add_column("Name", style="cyan", no_wrap=True)
  14. table.add_column("Type", style="yellow", no_wrap=True)
  15. if show_options:
  16. table.add_column("Options", style="magenta")
  17. table.add_column("Default", style="green", no_wrap=True)
  18. table.add_column("Description", style="white")
  19. rows_by_name: Dict[str, Dict[str, str]] = {
  20. row["name"]: row for row in variables.as_rows()
  21. }
  22. def _style_value(value: str, enabled: bool) -> str:
  23. if enabled or not value:
  24. return value
  25. return f"[grey50]{value}[/grey50]"
  26. def _add_variable_row(row: Dict[str, str], *, enabled: bool = True) -> None:
  27. cells = [
  28. _style_value(row["name"], enabled),
  29. _style_value(row["type"], enabled),
  30. ]
  31. if show_options:
  32. options = ", ".join(row["options"]) if row["options"] else ""
  33. cells.append(_style_value(options, enabled))
  34. cells.extend(
  35. [
  36. _style_value(row["default"], enabled),
  37. _style_value(row["description"], enabled),
  38. ]
  39. )
  40. style = None if enabled else "grey50"
  41. table.add_row(*cells, style=style)
  42. if sections:
  43. column_count = 4 + (1 if show_options else 0)
  44. for idx, meta in enumerate(sections.values()):
  45. title = meta.get("title") or "Section"
  46. names = meta.get("variables", [])
  47. toggle_var = None
  48. toggle_name = meta.get("toggle")
  49. if toggle_name:
  50. toggle_var = variables.get_variable(toggle_name)
  51. enabled = True
  52. if toggle_var is not None:
  53. try:
  54. enabled = bool(toggle_var.get_typed_value())
  55. except ValueError:
  56. enabled = True
  57. header_style = "bold magenta" if enabled else "bold grey50"
  58. header_title = title if enabled else f"{title} (disabled)"
  59. header_cells = [
  60. _style_value(header_title, enabled)
  61. ] + ["" for _ in range(column_count - 1)]
  62. table.add_row(*header_cells, style=header_style, end_section=False)
  63. for name in names:
  64. row = rows_by_name.get(name)
  65. if not row:
  66. continue
  67. _add_variable_row(row, enabled=enabled)
  68. if idx != len(sections) - 1:
  69. table.add_section()
  70. else:
  71. for row in rows_by_name.values():
  72. _add_variable_row(row)
  73. return table
  74. def render_template_list_table(
  75. templates: List[Any],
  76. module_name: str,
  77. *,
  78. include_library: bool = False,
  79. ) -> Table:
  80. """Build a Rich table for template listings without extra info lines.
  81. Columns and formatting:
  82. - ID (with dimmed (version) suffix if available)
  83. - Name
  84. - Description (takes remaining width, truncates with ellipsis)
  85. - Author (last column)
  86. """
  87. table = Table(title=f"{module_name.title()} Templates", header_style="bold cyan", expand=True)
  88. # Constrain non-description columns to preserve space
  89. table.add_column("ID", style="cyan", no_wrap=True, max_width=28, overflow="ellipsis")
  90. table.add_column("Name", style="white", no_wrap=True, max_width=28, overflow="ellipsis")
  91. if include_library:
  92. table.add_column("Library", style="magenta", no_wrap=True, max_width=16, overflow="ellipsis")
  93. # Description gets most space via ratio and truncates with ellipsis
  94. table.add_column("Description", style="white", no_wrap=True, overflow="ellipsis", ratio=1)
  95. table.add_column("Author", style="yellow", no_wrap=True, max_width=24, overflow="ellipsis")
  96. for tpl in templates:
  97. _id = tpl.id or "-"
  98. _ver = tpl.version or ""
  99. id_with_ver = f"{_id} [dim]({_ver})[/dim]" if _ver else _id
  100. name = tpl.name or _id
  101. author = tpl.author or "-"
  102. desc = tpl.description or "-"
  103. if include_library:
  104. library = tpl.library or "-"
  105. table.add_row(id_with_ver, name, library, desc, author)
  106. else:
  107. table.add_row(id_with_ver, name, desc, author)
  108. return table