Coverage for src/interactive_context.py: 97%
33 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-06-05 22:56 -0700
« prev ^ index » next coverage.py v7.8.0, created at 2025-06-05 22:56 -0700
1"""
2Interactive context management for Chuck command handlers.
4This module provides a centralized system for tracking and managing
5interactive command contexts, allowing commands to prompt for and
6process user input across multiple steps.
7"""
9from typing import Dict, Any, Optional
12class InteractiveContext:
13 """
14 Global manager for interactive context states.
15 Helps coordinate between command handlers and the TUI.
16 """
18 _instance = None
20 def __new__(cls):
21 if cls._instance is None:
22 cls._instance = super(InteractiveContext, cls).__new__(cls)
23 cls._instance._active_contexts = {}
24 cls._instance._current_command = None
25 return cls._instance
27 @property
28 def current_command(self) -> Optional[str]:
29 """Get the currently active command, if any."""
30 return self._current_command
32 def set_active_context(self, command: str) -> None:
33 """
34 Set a command as active in interactive mode.
36 Args:
37 command: The command name (e.g., "setup_wizard" or "/setup_wizard")
38 Slash prefix will be removed internally for consistency.
39 """
40 # Normalize command name by removing slash prefix if present
41 normalized_cmd = command.lstrip("/")
43 # Store original command for UI reference but normalize for internal storage
44 self._current_command = command
45 if normalized_cmd not in self._active_contexts:
46 self._active_contexts[normalized_cmd] = {}
48 def clear_active_context(self, command: str) -> None:
49 """
50 Clear the interactive context for a command.
52 Args:
53 command: The command name (e.g., "setup_wizard" or "/setup_wizard")
54 Slash prefix will be removed internally for consistency.
55 """
56 # Normalize command name by removing slash prefix if present
57 normalized_cmd = command.lstrip("/")
59 # Compare normalized versions of commands to avoid mismatches
60 if (
61 self._current_command
62 and self._current_command.lstrip("/") == normalized_cmd
63 ):
64 self._current_command = None
66 if normalized_cmd in self._active_contexts:
67 del self._active_contexts[normalized_cmd]
69 def is_in_interactive_mode(self) -> bool:
70 """Check if any command is in interactive mode."""
71 return self._current_command is not None
73 def get_context_data(self, command: str) -> Dict[str, Any]:
74 """
75 Get stored context data for a command.
77 Args:
78 command: The command name (e.g., "setup_wizard" or "/setup_wizard")
79 Slash prefix will be removed internally for consistency.
81 Returns:
82 Dictionary of context data for the command
83 """
84 # Normalize command name by removing slash prefix if present
85 normalized_cmd = command.lstrip("/")
87 return self._active_contexts.get(normalized_cmd, {})
89 def store_context_data(self, command: str, key: str, value: Any) -> None:
90 """
91 Store data in the context for a command.
93 Args:
94 command: The command name (e.g., "setup_wizard" or "/setup_wizard")
95 Slash prefix will be removed internally for consistency.
96 key: The key to store the data under
97 value: The value to store
98 """
99 # Normalize command name by removing slash prefix if present
100 normalized_cmd = command.lstrip("/")
102 if normalized_cmd not in self._active_contexts:
103 self._active_contexts[normalized_cmd] = {}
105 self._active_contexts[normalized_cmd][key] = value