diff --git a/CHANGELOG.md b/CHANGELOG.md index c2b126b5..6806b92f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Release date: UNRELEASED ### New features and improvements -* ... +* Added a `--orientation` option to the `pagerotate` command to conditionally rotate the page to a target orientation (thanks to @gatesphere) (#705) ### Bug fixes diff --git a/tests/test_commands.py b/tests/test_commands.py index 53fdbd77..414372d5 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -728,6 +728,28 @@ def test_pagerotate_error(caplog): assert "page size is not defined, page not rotated" in caplog.text +def test_pagerotate_orientation(): + doc = vpype_cli.execute("random pagesize a4 pagerotate -o landscape") + assert doc.page_size == pytest.approx((1122.5196850393702, 793.7007874015749)) + + doc = vpype_cli.execute("random pagesize a4 pagerotate -cw -o landscape") + assert doc.page_size == pytest.approx((1122.5196850393702, 793.7007874015749)) + + doc = vpype_cli.execute("random pagesize --landscape a4 pagerotate -o portrait") + assert doc.page_size == pytest.approx((793.7007874015749, 1122.5196850393702)) + + doc = vpype_cli.execute("random pagesize --landscape a4 pagerotate -cw -o portrait") + assert doc.page_size == pytest.approx((793.7007874015749, 1122.5196850393702)) + + +def test_pagerotate_orientation_error(): + doc = vpype_cli.execute("random pagesize a4 pagerotate -o portrait") + assert doc.page_size == pytest.approx((793.7007874015749, 1122.5196850393702)) + + doc = vpype_cli.execute("random pagesize --landscape a4 pagerotate -o landscape") + assert doc.page_size == pytest.approx((1122.5196850393702, 793.7007874015749)) + + def test_help(runner): res = runner.invoke(cli, "--help") diff --git a/vpype_cli/operations.py b/vpype_cli/operations.py index eff7aa28..1ddbade8 100644 --- a/vpype_cli/operations.py +++ b/vpype_cli/operations.py @@ -11,7 +11,14 @@ from .cli import cli from .decorators import global_processor, layer_processor -from .types import IntegerType, LayerType, LengthType, PageSizeType, multiple_to_layer_ids +from .types import ( + ChoiceType, + IntegerType, + LayerType, + LengthType, + PageSizeType, + multiple_to_layer_ids, +) __all__ = ( "crop", @@ -662,12 +669,20 @@ def layout( is_flag=True, help="Rotate clockwise instead of the default counter-clockwise", ) +@click.option( + "--orientation", + "-o", + type=ChoiceType(["portrait", "landscape"]), + help="Conditionally rotate only if the final orientation matches this option", +) @global_processor -def pagerotate(document: vp.Document, clockwise: bool): +def pagerotate(document: vp.Document, clockwise: bool, orientation: str | None): """Rotate the page by 90 degrees. This command rotates the page by 90 degrees counter-clockwise. If the `--clockwise` option - is passed, it rotates the page clockwise instead. + is passed, it rotates the page clockwise instead. If the `--orientation` option is given + a value of either 'portrait' or 'landscape', the page will only be rotated if the final + orientation would match that choice. Note: if the page size is not defined, an error is printed and the page is not rotated. """ @@ -677,6 +692,19 @@ def pagerotate(document: vp.Document, clockwise: bool): return document w, h = page_size + # sanity checks + if orientation is not None and orientation not in ["portrait", "landscape"]: + logging.warning( + f"pagerotate: orientation value '{orientation}' not one of 'portrait', 'landscape'" + ) + return document + + # check orientation constraint, and do nothing if target orientation + # won't match desired result + if (orientation == "portrait" and h > w) or (orientation == "landscape" and w > h): + logging.debug("pagerotate: page already in target orientation, page not rotated") + return document + if clockwise: document.rotate(math.pi / 2) document.translate(h, 0)