Source code for simvx.ide.debug_controller
"""Debug and run controller -- breakpoints, stepping, terminal execution."""
from __future__ import annotations
import logging
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .app import IDERoot
log = logging.getLogger(__name__)
[docs]
class DebugController:
"""Manages run/debug actions for the IDE.
Handles launching scripts, breakpoint toggling, and debugger stepping.
"""
def __init__(self, ide: IDERoot) -> None:
self._ide = ide
# -- Convenience accessors ------------------------------------------------
@property
def _debug_manager(self):
return self._ide._debug_manager
@property
def _bottom_tabs(self):
return self._ide._bottom_tabs
@property
def _terminal_panel(self):
return self._ide._terminal_panel
@property
def state(self):
return self._ide.state
# -- Run ------------------------------------------------------------------
[docs]
def on_run_file(self):
if not self.state.active_file:
return
if self.state.active_file.startswith("untitled"):
self.state.status_message.emit("Save file first before running")
return
# If breakpoints exist and debug manager available, use debugger
if self._debug_manager and self.state.get_all_breakpoints():
self._debug_manager.start_debug(self.state.active_file)
self._ide._show_bottom_panel()
if self._bottom_tabs:
tab_controls = [c for c in self._bottom_tabs.children if hasattr(c, "visible")]
for i, c in enumerate(tab_controls):
if getattr(c, "name", "") == "Debug":
self._bottom_tabs.current_tab = i
self._bottom_tabs._update_layout()
break
self.state.status_message.emit("Debugging started...")
else:
self.state.run_requested.emit(self.state.active_file)
[docs]
def on_run_no_debug(self):
if self.state.active_file:
self._run_in_terminal(self.state.active_file)
[docs]
def on_run_requested(self, path: str):
self._run_in_terminal(path)
def _run_in_terminal(self, path: str):
self._ide._show_bottom_panel()
self._ide._switch_to_tab("Terminal")
if self._terminal_panel:
self._terminal_panel.run_file(path)
# -- Breakpoints ----------------------------------------------------------
[docs]
def on_toggle_breakpoint(self):
if self.state.active_file:
self.state.toggle_breakpoint(self.state.active_file, self.state.cursor_line)
# -- Stepping -------------------------------------------------------------
[docs]
def on_step_over(self):
if self._debug_manager:
self._debug_manager.step_over()
[docs]
def on_step_into(self):
if self._debug_manager:
self._debug_manager.step_into()
[docs]
def on_step_out(self):
if self._debug_manager:
self._debug_manager.step_out()
[docs]
def on_stop_debug(self):
if self._debug_manager:
self._debug_manager.stop_debug()
self.state.debug_stopped.emit()
[docs]
def on_restart_debug(self):
if self._debug_manager:
path = self.state.active_file
self._debug_manager.stop_debug()
if path:
self._debug_manager.start_debug(path)