|
15 | 15 | from enum import Enum
|
16 | 16 | from dataclasses import dataclass
|
17 | 17 | from rich.text import Text
|
18 |
| -from rich.console import Console |
| 18 | +from rich.tree import Tree |
19 | 19 |
|
20 | 20 | from . import _engine
|
21 | 21 | from . import index
|
@@ -454,61 +454,52 @@ def _lazy_engine_flow() -> _engine.Flow:
|
454 | 454 | return engine_flow
|
455 | 455 | self._lazy_engine_flow = _lazy_engine_flow
|
456 | 456 |
|
457 |
| - def _format_flow(self, flow_dict: dict) -> Text: |
458 |
| - output = Text() |
| 457 | + def _render_spec(self, verbose: bool = False) -> Tree: |
| 458 | + """ |
| 459 | + Render the flow spec as a styled rich Tree with hierarchical structure. |
| 460 | + """ |
| 461 | + tree = Tree(f"Flow: {self.name}", style="cyan") |
| 462 | + current_section = None |
| 463 | + section_node = None |
| 464 | + indent_stack = [] |
459 | 465 |
|
460 |
| - def add_line(content, indent=0, style=None, end="\n"): |
461 |
| - output.append(" " * indent) |
462 |
| - output.append(content, style=style) |
463 |
| - output.append(end) |
| 466 | + for i, (section, content, indent) in enumerate(self._get_spec(verbose=verbose)): |
| 467 | + # Skip "Scope" entries (see ReactiveOpScope in spec.rs) |
| 468 | + if content.startswith("Scope:"): |
| 469 | + continue |
464 | 470 |
|
465 |
| - def format_key_value(key, value, indent): |
466 |
| - if isinstance(value, (dict, list)): |
467 |
| - add_line(f"- {key}:", indent, style="green") |
468 |
| - format_data(value, indent + 2) |
469 |
| - else: |
470 |
| - add_line(f"- {key}:", indent, style="green", end="") |
471 |
| - add_line(f" {value}", style="yellow") |
472 |
| - |
473 |
| - def format_data(data, indent=0): |
474 |
| - if isinstance(data, dict): |
475 |
| - for key, value in data.items(): |
476 |
| - format_key_value(key, value, indent) |
477 |
| - elif isinstance(data, list): |
478 |
| - for i, item in enumerate(data): |
479 |
| - format_key_value(f"[{i}]", item, indent) |
| 471 | + if section != current_section: |
| 472 | + current_section = section |
| 473 | + section_node = tree.add(f"{section}:", style="bold magenta") |
| 474 | + indent_stack = [(0, section_node)] |
| 475 | + |
| 476 | + while indent_stack and indent_stack[-1][0] >= indent: |
| 477 | + indent_stack.pop() |
| 478 | + |
| 479 | + parent = indent_stack[-1][1] if indent_stack else section_node |
| 480 | + styled_content = Text(content, style="yellow") |
| 481 | + is_parent = any( |
| 482 | + next_indent > indent |
| 483 | + for _, next_content, next_indent in self._get_spec(verbose=verbose)[i + 1:] |
| 484 | + if not next_content.startswith("Scope:") |
| 485 | + ) |
| 486 | + |
| 487 | + if is_parent: |
| 488 | + node = parent.add(styled_content, style=None) |
| 489 | + indent_stack.append((indent, node)) |
480 | 490 | else:
|
481 |
| - add_line(str(data), indent, style="yellow") |
482 |
| - |
483 |
| - # Header |
484 |
| - flow_name = flow_dict.get("name", "Unnamed") |
485 |
| - add_line(f"Flow: {flow_name}", style="bold cyan") |
486 |
| - |
487 |
| - # Section |
488 |
| - for section_title, section_key in [ |
489 |
| - ("Sources:", "import_ops"), |
490 |
| - ("Processing:", "reactive_ops"), |
491 |
| - ("Targets:", "export_ops"), |
492 |
| - ]: |
493 |
| - add_line("") |
494 |
| - add_line(section_title, style="bold cyan") |
495 |
| - format_data(flow_dict.get(section_key, []), indent=0) |
496 |
| - |
497 |
| - return output |
498 |
| - |
499 |
| - def _render_text(self) -> Text: |
500 |
| - flow_spec_str = str(self._lazy_engine_flow()) |
501 |
| - try: |
502 |
| - flow_dict = json.loads(flow_spec_str) |
503 |
| - return self._format_flow(flow_dict) |
504 |
| - except json.JSONDecodeError: |
505 |
| - return Text(flow_spec_str) |
| 491 | + parent.add(styled_content, style=None) |
| 492 | + |
| 493 | + return tree |
| 494 | + |
| 495 | + def _get_spec(self, verbose: bool = False) -> list[tuple[str, str, int]]: |
| 496 | + return self._lazy_engine_flow().get_spec(verbose=verbose) |
506 | 497 |
|
507 |
| - def _render_schema(self) -> list[tuple[str, str, str]]: |
| 498 | + def _get_schema(self) -> list[tuple[str, str, str]]: |
508 | 499 | return self._lazy_engine_flow().get_schema()
|
509 | 500 |
|
510 | 501 | def __str__(self):
|
511 |
| - return str(self._render_text()) |
| 502 | + return str(self._get_spec()) |
512 | 503 |
|
513 | 504 | def __repr__(self):
|
514 | 505 | return repr(self._lazy_engine_flow())
|
|
0 commit comments