diff --git a/README.md b/README.md index ddd19fa9..a07416b9 100644 --- a/README.md +++ b/README.md @@ -143,42 +143,70 @@ Labelle includes the Carlito font, licensed under the ## Modes -### Print text +### Overview -```labelle MyText``` +For a comprehensive list of options, run -Multilines will be generated on whitespace +```bash +labelle --help +``` + +### Preview -```labelle MyLine MySecondLine # Will print two Lines``` +To save tape, you can preview the label without printing it -If you want whitespaces just enclose in " " +```bash +labelle --output=console --text Hi +``` -```labelle "prints a single line"``` +![Hi](doc/hi.png) -### Print QRCodes and Barcodes +### Text -```labelle --help``` +If your text includes whitespace or any other characters like `<` or `$` that are +interpreted by your shell, then the text must be quoted. + +```bash +labelle --text 'Price: $3.50' +``` + +![Price: $3.50](doc/3-50.png) + +Multiple text arguments will stack on top of each other as separate lines + +```bash +labelle --text "first line" --text "second line" +``` + +![first line second line](doc/two-lines.png) ### Print Codes and Text Just add a text after your qr or barcode text -```labelle -qr "QR Content" "Cleartext printed"``` +```bash +labelle --qr "QR Content" --text "Cleartext printed" +``` + +![QR Content Cleartext printed](doc/qr-with-text.png) ### Picture printing -Any picture with JPEG standard may be printed. Beware it will be downsized to tape. +Any commonly-supported raster image may be printed. -```labelle -p mypic.jpg ""``` +```bash +labelle --picture labelle.png +``` -Take care of the trailing "" - you may enter text here which gets printed in -front of the image +![labelle.png](doc/labelle-label.png) ## GUI ### Run Labelle GUI -```labelle-gui``` +```bash +labelle-gui +``` ### GUI App Features diff --git a/doc/3-50.png b/doc/3-50.png new file mode 100644 index 00000000..31660693 Binary files /dev/null and b/doc/3-50.png differ diff --git a/doc/hi.png b/doc/hi.png new file mode 100644 index 00000000..159d42f3 Binary files /dev/null and b/doc/hi.png differ diff --git a/doc/labelle-label.png b/doc/labelle-label.png new file mode 100644 index 00000000..1d952d62 Binary files /dev/null and b/doc/labelle-label.png differ diff --git a/doc/qr-with-text.png b/doc/qr-with-text.png new file mode 100644 index 00000000..6410df05 Binary files /dev/null and b/doc/qr-with-text.png differ diff --git a/doc/two-lines.png b/doc/two-lines.png new file mode 100644 index 00000000..78f5b48f Binary files /dev/null and b/doc/two-lines.png differ diff --git a/pyproject.toml b/pyproject.toml index 1997df64..161cf40f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -92,13 +92,13 @@ commands = labelle --version labelle --help python -c "import labelle.gui.gui; print('GUI import succeeded')" - labelle --output console "single line" - labelle --output console-inverted "inverted" - labelle --output console multiple lines + labelle --output console --text "single line" + labelle --output console-inverted --text "inverted" + labelle --output console --text multiple --text lines labelle --output console --barcode "Barcode" --barcode-type code128 - labelle --output console --barcode-with-text "Barcode" --barcode-type code128 Caption - labelle --output console --qr QR - labelle --output console --qr QR Caption + labelle --output console --barcode-with-text "Barcode" --barcode-type code128 --text "Caption" + labelle --output console --qr "QR" + labelle --output console --qr "QR" --text "Caption" labelle --output console --picture ./labelle.png [testenv:{clean,build}] diff --git a/src/labelle/cli/cli.py b/src/labelle/cli/cli.py index 0ab34132..4630cd05 100755 --- a/src/labelle/cli/cli.py +++ b/src/labelle/cli/cli.py @@ -6,12 +6,17 @@ # this notice are preserved. # === END LICENSE STATEMENT === import logging +import shlex +import sys from pathlib import Path from typing import List, NoReturn, Optional import typer +from click.exceptions import ClickException +from click.exceptions import UsageError as ClickUsageError from rich.console import Console from rich.table import Table +from typer.rich_utils import rich_format_error from typing_extensions import Annotated from labelle import __version__ @@ -130,7 +135,7 @@ def default( ] = None, text: Annotated[ Optional[List[str]], - typer.Argument( + typer.Option( help="Text, each parameter gives a new line", rich_help_panel="Elements", ), @@ -554,9 +559,33 @@ def default( output_bitmap(bitmap, output) +def add_hint_about_text_option(e: ClickException) -> None: + """Insert a suggestion to use the --text flag when a command is not found. + + In dymoprint the --text option was implicit. If labelle is invoked without + --text, it presents as a ClickUsageError with the message "No such command..." + We append to this error message a hint to use the --text flag. + """ + if isinstance(e, ClickUsageError): + # Enhance the error message for dymoprint users who are + # not used to the --text flag being mandatory. + if e.message.startswith("No such command '") and e.message.endswith("'."): + command = e.message[17:-2] + e.message += f""" Did you mean {shlex.join(['--text', command])} ?""" + + def main() -> None: configure_logging() - app() + try: + app(standalone_mode=False) + except ClickException as e: + # Use standalone mode to avoid typer's default error handling here: + # + # This allows us to add the following hint: + add_hint_about_text_option(e) + + rich_format_error(e) + sys.exit(e.exit_code) if __name__ == "__main__": diff --git a/src/labelle/cli/tests/test_cli.py b/src/labelle/cli/tests/test_cli.py new file mode 100644 index 00000000..346bf0ba --- /dev/null +++ b/src/labelle/cli/tests/test_cli.py @@ -0,0 +1,25 @@ +import sys + +import pytest +from typer.testing import CliRunner + +from labelle.cli.cli import main + +runner = CliRunner() + + +def test_text_hint(monkeypatch): + # This is NOT the recommended way of testing Typer applications. + # We are doing it this way because we added additional error handling + # in main() which we need to test. + with monkeypatch.context() as m: + m.setattr(sys, "argv", ["labelle", "hello world"]) + with runner.isolation(input=None, env=None, color=False) as outstreams: + with pytest.raises(SystemExit): + main() + sys.stdout.flush() + stdout = outstreams[0].getvalue() + assert ( + b"""No such command 'hello world'. Did you mean --text 'hello world' ?""" + in stdout + )