forked from genewildish/Mainline
feat(repl): Add REPL effect with HUD-style interactive interface
Implement a Read-Eval-Print Loop (REPL) effect that provides a HUD-style overlay for interactive pipeline control. ## New Files - engine/effects/plugins/repl.py - REPL effect plugin with command processor - engine/display/backends/terminal.py - Added raw mode and input handling - examples/repl_simple.py - Simple demonstration script - tests/test_repl_effect.py - 18 comprehensive tests ## Features ### REPL Interface - HUD-style overlay showing FPS, command history, output buffer size - Command history navigation (Up/Down arrows) - Command execution (Enter) - Character input and backspace support - Output buffer with scrolling ### Commands - help - Show available commands - status - Show pipeline status and metrics - effects - List all effects in pipeline - effect <name> <on|off> - Toggle effect - param <effect> <param> <value> - Set parameter - pipeline - Show current pipeline order - clear - Clear output buffer - quit - Show exit message ### Terminal Input Support - Added set_raw_mode() to TerminalDisplay for capturing keystrokes - Added get_input_keys() to read keyboard input - Proper terminal state restoration on cleanup ## Usage Add 'repl' to effects in your configuration: ## Testing All 18 REPL tests pass, covering: - Effect registration - Command processing - Navigation (history, editing) - Configuration - Rendering ## Integration The REPL effect integrates with the existing pipeline system: - Uses EffectPlugin interface - Supports partial updates - Reads metrics from EffectContext - Can be controlled via keyboard when terminal display is in raw mode Next steps: - Integrate REPL input handling into pipeline_runner.py - Add keyboard event processing loop - Create full demo with interactive features
This commit is contained in:
@@ -124,22 +124,44 @@ class PipelineConfig:
|
||||
|
||||
# Add effect nodes
|
||||
for effect in self.effects:
|
||||
graph.node(
|
||||
effect.name,
|
||||
NodeType.EFFECT,
|
||||
effect=effect.name,
|
||||
intensity=effect.intensity,
|
||||
enabled=effect.enabled,
|
||||
**effect.params,
|
||||
)
|
||||
# Handle both EffectConfig objects and dictionaries
|
||||
if isinstance(effect, dict):
|
||||
name = effect.get("name", "")
|
||||
intensity = effect.get("intensity", 1.0)
|
||||
enabled = effect.get("enabled", True)
|
||||
params = effect.get("params", {})
|
||||
else:
|
||||
name = effect.name
|
||||
intensity = effect.intensity
|
||||
enabled = effect.enabled
|
||||
params = effect.params
|
||||
|
||||
if name:
|
||||
graph.node(
|
||||
name,
|
||||
NodeType.EFFECT,
|
||||
effect=name,
|
||||
intensity=intensity,
|
||||
enabled=enabled,
|
||||
**params,
|
||||
)
|
||||
|
||||
# Add display node
|
||||
display_config = self.display or DisplayConfig()
|
||||
if isinstance(self.display, dict):
|
||||
display_backend = self.display.get("backend", "terminal")
|
||||
display_positioning = self.display.get("positioning", "mixed")
|
||||
elif self.display:
|
||||
display_backend = self.display.backend
|
||||
display_positioning = self.display.positioning
|
||||
else:
|
||||
display_backend = "terminal"
|
||||
display_positioning = "mixed"
|
||||
|
||||
graph.node(
|
||||
"display",
|
||||
NodeType.DISPLAY,
|
||||
backend=display_config.backend,
|
||||
positioning=display_config.positioning,
|
||||
backend=display_backend,
|
||||
positioning=display_positioning,
|
||||
)
|
||||
|
||||
# Create linear connections
|
||||
@@ -151,7 +173,9 @@ class PipelineConfig:
|
||||
|
||||
# Add all effects in order
|
||||
for effect in self.effects:
|
||||
chain.append(effect.name)
|
||||
name = effect.get("name", "") if isinstance(effect, dict) else effect.name
|
||||
if name:
|
||||
chain.append(name)
|
||||
|
||||
chain.append("display")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user