diff --git a/CHANGELOG.md b/CHANGELOG.md index af24799b..275f95e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +[Unreleased] + +- Add a new output format `errorsonly` which only shows output if an error occured. + ## v3.0.1 (2024-01-12) - Fixes a bug where Quicktime and mp4 files return no Exif data. diff --git a/organize/cli.py b/organize/cli.py index 15bc111f..bf37abfe 100644 --- a/organize/cli.py +++ b/organize/cli.py @@ -30,7 +30,8 @@ Options: A config name or path to a config file -W --working-dir The working directory - -F --format (DEFAULT|JSONL) The output format [Default: DEFAULT] + -F --format (default|errorsonly|JSONL) + The output format [Default: default] -T --tags Tags to run (eg. "initial,release") -S --skip-tags Tags to skip -h --help Show this help page. @@ -72,7 +73,7 @@ Tags = Set[str] OutputFormat = Annotated[ - Literal["default", "jsonl"], BeforeValidator(lambda v: v.lower()) + Literal["default", "jsonl", "errorsonly"], BeforeValidator(lambda v: v.lower()) ] console = Console() @@ -84,6 +85,16 @@ def _open_uri(uri: str): webbrowser.open(uri) +def _output_for_format(format: OutputFormat) -> Output: + if format == "default": + return Default() + elif format == "errorsonly": + return Default(errors_only=True) + elif format == "jsonl": + return JSONL() + raise ValueError(f"{format} is not a valid output format.") + + def execute( config: Optional[str], working_dir: Optional[Path], @@ -92,12 +103,10 @@ def execute( skip_tags: Tags, simulate: bool, ) -> None: - output = JSONL() if format == "jsonl" else Default() - assert isinstance(output, Output) config_path = find_config(name_or_path=config) Config.from_path(config_path).execute( simulate=simulate, - output=output, + output=_output_for_format(format), tags=tags, skip_tags=skip_tags, working_dir=working_dir or Path("."), diff --git a/organize/output/default.py b/organize/output/default.py index 8ed4f846..be079cf6 100644 --- a/organize/output/default.py +++ b/organize/output/default.py @@ -15,6 +15,8 @@ from .output import Level if TYPE_CHECKING: + from typing import List + from organize.resource import Resource from ._sender import SenderType @@ -51,7 +53,7 @@ def set_error_msg(cls, msg: str) -> None: class Default: - def __init__(self, theme: Optional[Theme] = None): + def __init__(self, theme: Optional[Theme] = None, errors_only: bool = False): if theme is None: theme = Theme( { @@ -74,6 +76,10 @@ def __init__(self, theme: Optional[Theme] = None): "summary.fail": "red", } ) + self.errors_only = errors_only + self.msg_queue: List[str] = [] + self.det_resource = ChangeDetector() + self.console = Console(theme=theme, highlight=False) self.status = Status("", console=self.console) @@ -141,14 +147,26 @@ def msg( sender: SenderType, level: Level = "info", ) -> None: - self.show_resource(res) msg_pre = format_sender(sender=sender, standalone=res.path is None) if level == "info": - self.console.print(f"{msg_pre}{format_info(msg=msg)}") - elif level == "error": - self.console.print(f"{msg_pre}{format_error(msg=msg)}") + msg = f"{msg_pre}{format_info(msg=msg)}" elif level == "warn": - self.console.print(f"{msg_pre}{format_warn(msg=msg)}") + msg = f"{msg_pre}{format_warn(msg=msg)}" + elif level == "error": + msg = f"{msg_pre}{format_error(msg=msg)}" + + if self.errors_only: + if self.det_resource.changed(res): + self.msg_queue.clear() + self.msg_queue.append(msg) + if level == "error": + self.show_resource(res) + for msg in self.msg_queue: + self.console.print(msg) + self.msg_queue.clear() + else: + self.show_resource(res) + self.console.print(msg) def confirm( self,