Merge pull request 'refactor: Make EffectPlugin an abstract base class, update effects to inherit from it, and improve plugin discovery.' (#32) from chore/plugin-migration into main

Reviewed-on: #32
This commit was merged in pull request #32.
This commit is contained in:
2026-03-19 06:15:41 +00:00
6 changed files with 45 additions and 15 deletions

View File

@@ -5,6 +5,7 @@ PLUGIN_DIR = Path(__file__).parent
def discover_plugins(): def discover_plugins():
from engine.effects.registry import get_registry from engine.effects.registry import get_registry
from engine.effects.types import EffectPlugin
registry = get_registry() registry = get_registry()
imported = {} imported = {}
@@ -22,8 +23,8 @@ def discover_plugins():
attr = getattr(module, attr_name) attr = getattr(module, attr_name)
if ( if (
isinstance(attr, type) isinstance(attr, type)
and hasattr(attr, "name") and issubclass(attr, EffectPlugin)
and hasattr(attr, "process") and attr is not EffectPlugin
and attr_name.endswith("Effect") and attr_name.endswith("Effect")
): ):
plugin = attr() plugin = attr()

View File

@@ -3,7 +3,7 @@ import random
from engine.effects.types import EffectConfig, EffectContext, EffectPlugin from engine.effects.types import EffectConfig, EffectContext, EffectPlugin
class FadeEffect: class FadeEffect(EffectPlugin):
name = "fade" name = "fade"
config = EffectConfig(enabled=True, intensity=1.0) config = EffectConfig(enabled=True, intensity=1.0)

View File

@@ -7,7 +7,7 @@ from engine.sources import FEEDS, POETRY_SOURCES
from engine.terminal import C_DIM, G_DIM, G_LO, RST, W_GHOST from engine.terminal import C_DIM, G_DIM, G_LO, RST, W_GHOST
class FirehoseEffect: class FirehoseEffect(EffectPlugin):
name = "firehose" name = "firehose"
config = EffectConfig(enabled=True, intensity=1.0) config = EffectConfig(enabled=True, intensity=1.0)

View File

@@ -5,7 +5,7 @@ from engine.effects.types import EffectConfig, EffectContext, EffectPlugin
from engine.terminal import C_DIM, DIM, G_DIM, G_LO, RST from engine.terminal import C_DIM, DIM, G_DIM, G_LO, RST
class GlitchEffect: class GlitchEffect(EffectPlugin):
name = "glitch" name = "glitch"
config = EffectConfig(enabled=True, intensity=1.0) config = EffectConfig(enabled=True, intensity=1.0)

View File

@@ -5,7 +5,7 @@ from engine.effects.types import EffectConfig, EffectContext, EffectPlugin
from engine.terminal import C_DIM, G_DIM, G_LO, RST, W_GHOST from engine.terminal import C_DIM, G_DIM, G_LO, RST, W_GHOST
class NoiseEffect: class NoiseEffect(EffectPlugin):
name = "noise" name = "noise"
config = EffectConfig(enabled=True, intensity=0.15) config = EffectConfig(enabled=True, intensity=0.15)

View File

@@ -1,3 +1,4 @@
from abc import ABC, abstractmethod
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any from typing import Any
@@ -8,10 +9,11 @@ class EffectContext:
terminal_height: int terminal_height: int
scroll_cam: int scroll_cam: int
ticker_height: int ticker_height: int
mic_excess: float camera_x: int = 0
grad_offset: float mic_excess: float = 0.0
frame_number: int grad_offset: float = 0.0
has_message: bool frame_number: int = 0
has_message: bool = False
items: list = field(default_factory=list) items: list = field(default_factory=list)
@@ -22,15 +24,42 @@ class EffectConfig:
params: dict[str, Any] = field(default_factory=dict) params: dict[str, Any] = field(default_factory=dict)
class EffectPlugin: class EffectPlugin(ABC):
name: str name: str
config: EffectConfig config: EffectConfig
def process(self, buf: list[str], ctx: EffectContext) -> list[str]: @abstractmethod
raise NotImplementedError def process(self, buf: list[str], ctx: EffectContext) -> list[str]: ...
def configure(self, config: EffectConfig) -> None: @abstractmethod
raise NotImplementedError def configure(self, config: EffectConfig) -> None: ...
def create_effect_context(
terminal_width: int = 80,
terminal_height: int = 24,
scroll_cam: int = 0,
ticker_height: int = 0,
camera_x: int = 0,
mic_excess: float = 0.0,
grad_offset: float = 0.0,
frame_number: int = 0,
has_message: bool = False,
items: list | None = None,
) -> EffectContext:
"""Factory function to create EffectContext with sensible defaults."""
return EffectContext(
terminal_width=terminal_width,
terminal_height=terminal_height,
scroll_cam=scroll_cam,
ticker_height=ticker_height,
camera_x=camera_x,
mic_excess=mic_excess,
grad_offset=grad_offset,
frame_number=frame_number,
has_message=has_message,
items=items or [],
)
@dataclass @dataclass