diff --git a/manim_slides/commons.py b/manim_slides/commons.py index 2566297..c3810f4 100644 --- a/manim_slides/commons.py +++ b/manim_slides/commons.py @@ -1,11 +1,13 @@ from typing import Callable import click +from click import Context, Parameter from .defaults import CONFIG_PATH +from .manim import logger -def config_path_option(function) -> Callable: +def config_path_option(function: Callable) -> Callable: """Wraps a function to add configuration path option.""" return click.option( "-c", @@ -18,7 +20,7 @@ def config_path_option(function) -> Callable: )(function) -def config_options(function) -> Callable: +def config_options(function: Callable) -> Callable: """Wraps a function to add configuration options.""" function = config_path_option(function) function = click.option( @@ -31,3 +33,27 @@ def config_options(function) -> Callable: help="Merge any existing configuration file with the new configuration.", )(function) return function + + +def verbosity_option(function: Callable) -> Callable: + """Wraps a function to add verbosity option.""" + + def callback(ctx: Context, param: Parameter, value: bool) -> None: + + if not value or ctx.resilient_parsing: + return + + logger.setLevel(value) + + return click.option( + "-v", + "--verbosity", + type=click.Choice( + ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], + case_sensitive=False, + ), + help="Verbosity of CLI output", + default=None, + expose_value=False, + callback=callback, + )(function) diff --git a/manim_slides/config.py b/manim_slides/config.py index 32c4298..6119d7a 100644 --- a/manim_slides/config.py +++ b/manim_slides/config.py @@ -5,6 +5,7 @@ from typing import List, Optional, Set from pydantic import BaseModel, root_validator, validator from .defaults import LEFT_ARROW_KEY_CODE, RIGHT_ARROW_KEY_CODE +from .manim import logger class Key(BaseModel): @@ -20,7 +21,12 @@ class Key(BaseModel): return v def match(self, key_id: int): - return key_id in self.ids + m = key_id in self.ids + + if m: + logger.debug(f"Pressed key: {self.name}") + + return m class Config(BaseModel): diff --git a/manim_slides/present.py b/manim_slides/present.py index b9a454e..cb848bc 100644 --- a/manim_slides/present.py +++ b/manim_slides/present.py @@ -11,9 +11,10 @@ import numpy as np from pydantic import ValidationError from tqdm import tqdm -from .commons import config_path_option +from .commons import config_path_option, verbosity_option from .config import Config, PresentationConfig, SlideConfig, SlideType from .defaults import FOLDER_PATH, FONT_ARGS +from .manim import logger INTERPOLATION_FLAGS = { "nearest": cv2.INTER_NEAREST, @@ -450,6 +451,9 @@ class Display: cv2.destroyAllWindows() if self.record_to is not None and len(self.recordings) > 0: + logger.debug( + f"A total of {len(self.recordings)} frames will be saved to {self.record_to}" + ) file, frame_number, fps = self.recordings[0] cap = cv2.VideoCapture(file) @@ -489,6 +493,7 @@ class Display: show_default=True, ) @click.help_option("-h", "--help") +@verbosity_option def list_scenes(folder) -> None: """List available scenes.""" @@ -502,13 +507,18 @@ def _list_scenes(folder) -> List[str]: for file in os.listdir(folder): if file.endswith(".json"): + filepath = os.path.join(folder, file) try: - filepath = os.path.join(folder, file) _ = PresentationConfig.parse_file(filepath) scenes.append(os.path.basename(file)[:-5]) - except Exception: # Could not parse this file as a proper presentation config + except Exception as e: # Could not parse this file as a proper presentation config + logger.warn( + f"Something went wrong with parsing presentation config `{filepath}`: {e}" + ) pass + logger.info(f"Found {len(scenes)} valid scene configuration files in `{folder}`.") + return scenes @@ -552,6 +562,7 @@ def _list_scenes(folder) -> List[str]: help="If set, the presentation will be recorded into a AVI video file with given name.", ) @click.help_option("-h", "--help") +@verbosity_option def present( scenes, config_path, @@ -616,8 +627,8 @@ def present( f"File {config_file} does not exist, check the scene name and make sure to use Slide as your scene base class" ) try: - config = PresentationConfig.parse_file(config_file) - presentations.append(Presentation(config)) + pres_config = PresentationConfig.parse_file(config_file) + presentations.append(Presentation(pres_config)) except ValidationError as e: raise click.UsageError(str(e)) @@ -627,6 +638,7 @@ def present( except ValidationError as e: raise click.UsageError(str(e)) else: + logger.info("No configuration file found, using default configuration.") config = Config() if record_to is not None: diff --git a/manim_slides/wizard.py b/manim_slides/wizard.py index b887429..b34d89c 100644 --- a/manim_slides/wizard.py +++ b/manim_slides/wizard.py @@ -5,7 +5,7 @@ import click import cv2 import numpy as np -from .commons import config_options +from .commons import config_options, verbosity_option from .config import Config from .defaults import CONFIG_PATH, FONT_ARGS @@ -39,6 +39,7 @@ def prompt(question: str) -> int: @click.command() @config_options @click.help_option("-h", "--help") +@verbosity_option def wizard(config_path, force, merge): """Launch configuration wizard.""" return _init(config_path, force, merge, skip_interactive=False) @@ -47,6 +48,7 @@ def wizard(config_path, force, merge): @click.command() @config_options @click.help_option("-h", "--help") +@verbosity_option def init(config_path, force, merge, skip_interactive=False): """Initialize a new default configuration file.""" return _init(config_path, force, merge, skip_interactive=True)