From d52e4c9fd3d02639f9f7faa5be23d277555fc1ac Mon Sep 17 00:00:00 2001 From: zanjonke Date: Fri, 13 Mar 2026 11:03:47 +0100 Subject: [PATCH 1/2] TUI enhancements --- plain2code.py | 11 ----------- tui/components.py | 23 ++++++++++++++++++++++- tui/state_handlers.py | 22 +++++++++++++++------- 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/plain2code.py b/plain2code.py index ae11074..b1f2e76 100644 --- a/plain2code.py +++ b/plain2code.py @@ -49,17 +49,6 @@ DEFAULT_TEMPLATE_DIRS = importlib.resources.files("standard_template_library") -MAX_UNITTEST_FIX_ATTEMPTS = 20 -MAX_CONFORMANCE_TEST_FIX_ATTEMPTS = 20 -MAX_CONFORMANCE_TEST_RUNS = 20 -MAX_REFACTORING_ITERATIONS = 5 -MAX_UNIT_TEST_RENDER_RETRIES = 2 - -MAX_ISSUE_LENGTH = 10000 # Characters. - -UNRECOVERABLE_ERROR_EXIT_CODES = [69] -TIMEOUT_ERROR_EXIT_CODE = 124 - def get_render_range(render_range, plain_source): render_range = render_range.split(",") diff --git a/tui/components.py b/tui/components.py index f4ad923..792182b 100644 --- a/tui/components.py +++ b/tui/components.py @@ -246,8 +246,10 @@ class RenderingInfoBox(Vertical): def __init__(self, **kwargs): super().__init__(**kwargs) self.module_text = "" + self.functional_requirement_text = "" self.functionality_text = "" self.module_widget: Static | None = None + self.functional_requirement_widget: Static | None = None self.functionality_widget: Static | None = None def update_module(self, text: str) -> None: @@ -260,25 +262,36 @@ def update_functionality(self, text: str) -> None: self.functionality_text = text self._refresh_content() + def update_functional_requirement(self, text: str) -> None: + """Update the functionality text display.""" + self.functional_requirement_text = text + self._refresh_content() + def _refresh_content(self) -> None: """Refresh text inside the box.""" if self.module_widget is not None: self.module_widget.update(self.module_text or "") + if self.functional_requirement_widget is not None: + self.functional_requirement_widget.update(self.functional_requirement_text or "") if self.functionality_widget is not None: self.functionality_widget.update(self.functionality_text or "") def on_mount(self) -> None: """Initialize default labels on mount.""" self.module_text = "Module: " + self.functional_requirement_text = "Functional requirement:" self.functionality_text = "Functionality:" + self._refresh_content() def compose(self): self.module_widget = Static(self.module_text, classes="rendering-info-row") + self.functional_requirement_widget = Static(self.functional_requirement_text, classes="rendering-info-row") self.functionality_widget = Static(self.functionality_text, classes="rendering-info-row") yield Static("module status", classes="rendering-info-title") with Vertical(classes="rendering-info-box"): yield self.module_widget + yield self.functional_requirement_widget yield self.functionality_widget @@ -355,6 +368,7 @@ class FRIDProgress(Vertical): CONFORMANCE_TEST_VALIDATION_TEXT = "Conformance tests" RENDERING_MODULE_TEXT = "Module: " + RENDERING_FUNCTIONAL_REQUIREMENT_TEXT = "Functional requirement:" RENDERING_FUNCTIONALITY_TEXT = "Functionality:" def __init__( @@ -367,7 +381,14 @@ def __init__( self.unittests_script = unittests_script self.conformance_tests_script = conformance_tests_script - def update_fr_text(self, text: str) -> None: + def update_functional_requirement_text(self, text: str) -> None: + try: + info_box = self.query_one(RenderingInfoBox) + info_box.update_functional_requirement(text) + except Exception: + pass + + def update_functionality_text(self, text: str) -> None: try: # Update the rendering info box instead info_box = self.query_one(RenderingInfoBox) diff --git a/tui/state_handlers.py b/tui/state_handlers.py index a3a786c..70ef127 100644 --- a/tui/state_handlers.py +++ b/tui/state_handlers.py @@ -4,6 +4,7 @@ from typing import Optional from plain2code_events import RenderContextSnapshot +from render_machine.render_context import MAX_CONFORMANCE_TEST_FIX_ATTEMPTS, MAX_UNITTEST_FIX_ATTEMPTS from render_machine.states import States from . import components as tui_components @@ -66,8 +67,13 @@ def __init__(self, tui, unittests_script: Optional[str], conformance_tests_scrip def handle(self, _: list[str], snapshot: RenderContextSnapshot, _previous_state_segments: list[str]) -> None: """Handle READY_FOR_FRID_IMPLEMENTATION state.""" # Update FRID text + functional_requirement_text = ( + f"{tui_components.FRIDProgress.RENDERING_FUNCTIONAL_REQUIREMENT_TEXT} {snapshot.frid_context.frid}" + ) + get_frid_progress(self.tui).update_functional_requirement_text(functional_requirement_text) + rendering_functionality_text = f"{tui_components.FRIDProgress.RENDERING_FUNCTIONALITY_TEXT} {snapshot.frid_context.functional_requirement_text}" - get_frid_progress(self.tui).update_fr_text(rendering_functionality_text) + get_frid_progress(self.tui).update_functionality_text(rendering_functionality_text) # Set progress states update_progress_item_status(self.tui, TUIComponents.FRID_PROGRESS_RENDER_FR.value, ProgressItem.PROCESSING) @@ -101,9 +107,7 @@ def __init__(self, tui, unittests_script: Optional[str], conformance_tests_scrip self.unittests_script = unittests_script self.conformance_tests_script = conformance_tests_script - def handle( - self, segments: list[str], _snapshot: RenderContextSnapshot, _previous_state_segments: list[str] - ) -> None: + def handle(self, segments: list[str], snapshot: RenderContextSnapshot, _previous_state_segments: list[str]) -> None: """Handle PROCESSING_UNIT_TESTS state.""" if segments[2] == States.UNIT_TESTS_READY.value: if self.unittests_script is not None: @@ -124,7 +128,11 @@ def handle( update_progress_item_substates( self.tui, TUIComponents.FRID_PROGRESS_UNIT_TEST.value, - [Substate("Fixing unit tests")], + [ + Substate( + f"Fixing unit tests (attempt {snapshot.unit_tests_running_context.fix_attempts} of {MAX_UNITTEST_FIX_ATTEMPTS})" + ) + ], ) @@ -215,12 +223,12 @@ def handle(self, segments: list[str], snapshot: RenderContextSnapshot, previous_ [Substate("Preparing testing environment for conformance tests")], ) elif segments[2] == States.CONFORMANCE_TEST_ENV_PREPARED.value: - running_text = f"Running conformance tests for functional requirement {snapshot.conformance_tests_running_context.current_testing_frid}" + running_text = f"Running conformance tests for functional requirement {snapshot.conformance_tests_running_context.current_testing_frid} of module {snapshot.conformance_tests_running_context.current_testing_module_name}" update_progress_item_substates( self.tui, TUIComponents.FRID_PROGRESS_CONFORMANCE_TEST.value, [Substate(running_text)] ) elif segments[2] == States.CONFORMANCE_TEST_FAILED.value: - fixing_text = f"Fixing conformance tests for functional requirement {snapshot.conformance_tests_running_context.current_testing_frid}" + fixing_text = f"Fixing conformance tests for functional requirement {snapshot.conformance_tests_running_context.current_testing_frid} of module {snapshot.conformance_tests_running_context.current_testing_module_name} (attempt {snapshot.conformance_tests_running_context.fix_attempts} of {MAX_CONFORMANCE_TEST_FIX_ATTEMPTS})" update_progress_item_substates( self.tui, TUIComponents.FRID_PROGRESS_CONFORMANCE_TEST.value, [Substate(fixing_text)] ) From 6b434b04d35f6a75012835e2b542d97006e86660 Mon Sep 17 00:00:00 2001 From: zanjonke Date: Mon, 16 Mar 2026 14:42:51 +0100 Subject: [PATCH 2/2] Fix review comments --- tui/components.py | 22 +--------------------- tui/state_handlers.py | 31 +++++++++++++++++-------------- 2 files changed, 18 insertions(+), 35 deletions(-) diff --git a/tui/components.py b/tui/components.py index 792182b..9eb947c 100644 --- a/tui/components.py +++ b/tui/components.py @@ -246,10 +246,8 @@ class RenderingInfoBox(Vertical): def __init__(self, **kwargs): super().__init__(**kwargs) self.module_text = "" - self.functional_requirement_text = "" self.functionality_text = "" self.module_widget: Static | None = None - self.functional_requirement_widget: Static | None = None self.functionality_widget: Static | None = None def update_module(self, text: str) -> None: @@ -262,36 +260,26 @@ def update_functionality(self, text: str) -> None: self.functionality_text = text self._refresh_content() - def update_functional_requirement(self, text: str) -> None: - """Update the functionality text display.""" - self.functional_requirement_text = text - self._refresh_content() - def _refresh_content(self) -> None: """Refresh text inside the box.""" if self.module_widget is not None: self.module_widget.update(self.module_text or "") - if self.functional_requirement_widget is not None: - self.functional_requirement_widget.update(self.functional_requirement_text or "") if self.functionality_widget is not None: self.functionality_widget.update(self.functionality_text or "") def on_mount(self) -> None: """Initialize default labels on mount.""" self.module_text = "Module: " - self.functional_requirement_text = "Functional requirement:" self.functionality_text = "Functionality:" self._refresh_content() def compose(self): self.module_widget = Static(self.module_text, classes="rendering-info-row") - self.functional_requirement_widget = Static(self.functional_requirement_text, classes="rendering-info-row") self.functionality_widget = Static(self.functionality_text, classes="rendering-info-row") yield Static("module status", classes="rendering-info-title") with Vertical(classes="rendering-info-box"): yield self.module_widget - yield self.functional_requirement_widget yield self.functionality_widget @@ -368,8 +356,7 @@ class FRIDProgress(Vertical): CONFORMANCE_TEST_VALIDATION_TEXT = "Conformance tests" RENDERING_MODULE_TEXT = "Module: " - RENDERING_FUNCTIONAL_REQUIREMENT_TEXT = "Functional requirement:" - RENDERING_FUNCTIONALITY_TEXT = "Functionality:" + RENDERING_FUNCTIONALITY_TEXT = "Functionality " def __init__( self, @@ -381,13 +368,6 @@ def __init__( self.unittests_script = unittests_script self.conformance_tests_script = conformance_tests_script - def update_functional_requirement_text(self, text: str) -> None: - try: - info_box = self.query_one(RenderingInfoBox) - info_box.update_functional_requirement(text) - except Exception: - pass - def update_functionality_text(self, text: str) -> None: try: # Update the rendering info box instead diff --git a/tui/state_handlers.py b/tui/state_handlers.py index 70ef127..d9eb2b3 100644 --- a/tui/state_handlers.py +++ b/tui/state_handlers.py @@ -4,7 +4,6 @@ from typing import Optional from plain2code_events import RenderContextSnapshot -from render_machine.render_context import MAX_CONFORMANCE_TEST_FIX_ATTEMPTS, MAX_UNITTEST_FIX_ATTEMPTS from render_machine.states import States from . import components as tui_components @@ -67,12 +66,8 @@ def __init__(self, tui, unittests_script: Optional[str], conformance_tests_scrip def handle(self, _: list[str], snapshot: RenderContextSnapshot, _previous_state_segments: list[str]) -> None: """Handle READY_FOR_FRID_IMPLEMENTATION state.""" # Update FRID text - functional_requirement_text = ( - f"{tui_components.FRIDProgress.RENDERING_FUNCTIONAL_REQUIREMENT_TEXT} {snapshot.frid_context.frid}" - ) - get_frid_progress(self.tui).update_functional_requirement_text(functional_requirement_text) - rendering_functionality_text = f"{tui_components.FRIDProgress.RENDERING_FUNCTIONALITY_TEXT} {snapshot.frid_context.functional_requirement_text}" + rendering_functionality_text = f"{tui_components.FRIDProgress.RENDERING_FUNCTIONALITY_TEXT}{snapshot.frid_context.frid}: {snapshot.frid_context.functional_requirement_text}" get_frid_progress(self.tui).update_functionality_text(rendering_functionality_text) # Set progress states @@ -107,7 +102,9 @@ def __init__(self, tui, unittests_script: Optional[str], conformance_tests_scrip self.unittests_script = unittests_script self.conformance_tests_script = conformance_tests_script - def handle(self, segments: list[str], snapshot: RenderContextSnapshot, _previous_state_segments: list[str]) -> None: + def handle( + self, segments: list[str], _snapshot: RenderContextSnapshot, _previous_state_segments: list[str] + ) -> None: """Handle PROCESSING_UNIT_TESTS state.""" if segments[2] == States.UNIT_TESTS_READY.value: if self.unittests_script is not None: @@ -128,11 +125,7 @@ def handle(self, segments: list[str], snapshot: RenderContextSnapshot, _previous update_progress_item_substates( self.tui, TUIComponents.FRID_PROGRESS_UNIT_TEST.value, - [ - Substate( - f"Fixing unit tests (attempt {snapshot.unit_tests_running_context.fix_attempts} of {MAX_UNITTEST_FIX_ATTEMPTS})" - ) - ], + [Substate("Fixing unit tests")], ) @@ -223,12 +216,22 @@ def handle(self, segments: list[str], snapshot: RenderContextSnapshot, previous_ [Substate("Preparing testing environment for conformance tests")], ) elif segments[2] == States.CONFORMANCE_TEST_ENV_PREPARED.value: - running_text = f"Running conformance tests for functional requirement {snapshot.conformance_tests_running_context.current_testing_frid} of module {snapshot.conformance_tests_running_context.current_testing_module_name}" + running_text = f"Running conformance tests for functional requirement {snapshot.conformance_tests_running_context.current_testing_frid}" + if snapshot.conformance_tests_running_context.current_testing_module_name != snapshot.module_name: + running_text += ( + f" of module {snapshot.conformance_tests_running_context.current_testing_module_name}" + ) + update_progress_item_substates( self.tui, TUIComponents.FRID_PROGRESS_CONFORMANCE_TEST.value, [Substate(running_text)] ) elif segments[2] == States.CONFORMANCE_TEST_FAILED.value: - fixing_text = f"Fixing conformance tests for functional requirement {snapshot.conformance_tests_running_context.current_testing_frid} of module {snapshot.conformance_tests_running_context.current_testing_module_name} (attempt {snapshot.conformance_tests_running_context.fix_attempts} of {MAX_CONFORMANCE_TEST_FIX_ATTEMPTS})" + fixing_text = f"Fixing conformance tests for functional requirement {snapshot.conformance_tests_running_context.current_testing_frid}" + if snapshot.conformance_tests_running_context.current_testing_module_name != snapshot.module_name: + fixing_text += ( + f" of module {snapshot.conformance_tests_running_context.current_testing_module_name}" + ) + update_progress_item_substates( self.tui, TUIComponents.FRID_PROGRESS_CONFORMANCE_TEST.value, [Substate(fixing_text)] )