Repository: royreznik/rexi (language: python)

Issue:
Add option to pass a file as an argument and not stdin
allowing to to so:
```bash
rexi --file /tmp/wtf.txt
```


Discussion / hints:

Fix patch:
diff --git a/rexi/cli.py b/rexi/cli.py
index 934bfc7..91b720d 100644
--- a/rexi/cli.py
+++ b/rexi/cli.py
@@ -1,5 +1,6 @@
 import os
 import sys
+from typing import Annotated, Optional
 
 import typer
 
@@ -10,12 +11,23 @@
 
 # noinspection SpellCheckingInspection
 @app.command("rexi")
-def rexi_cli() -> None:
-    stdin = sys.stdin.read()
-    try:
-        os.close(sys.stdin.fileno())
-    except OSError:
-        pass
-    sys.stdin = open("/dev/tty", "rb")  # type: ignore[assignment]
-    app: RexiApp[int] = RexiApp(stdin)
+def rexi_cli(
+    input_file: Annotated[
+        Optional[typer.FileText],
+        typer.Option(
+            "--input", "-i",
+            help="Input file to pass to rexi; if not provided, stdin will be used.",
+        ),
+    ] = None,
+) -> None:
+    if input_file:
+        input_text = input_file.read()
+    else:
+        input_text = sys.stdin.read()
+        try:
+            os.close(sys.stdin.fileno())
+        except OSError:
+            pass
+        sys.stdin = open("/dev/tty", "rb")  # type: ignore[assignment]
+    app: RexiApp[int] = RexiApp(input_text)
     app.run()


Test patch:
diff --git a/tests/test_cli.py b/tests/test_cli.py
index bc196dc..e834bd8 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -1,4 +1,5 @@
 from io import BytesIO
+from pathlib import Path
 from unittest.mock import Mock
 
 from _pytest.monkeypatch import MonkeyPatch
@@ -6,7 +7,7 @@
 from rexi.cli import app
 
 
-def test_app(monkeypatch: MonkeyPatch) -> None:
+def test_stdin_cli(monkeypatch: MonkeyPatch) -> None:
     """
     Couldn't find a better way to test the CLI without patching everything :(
     """
@@ -24,3 +25,16 @@ def test_app(monkeypatch: MonkeyPatch) -> None:
     open_mock.assert_called_once_with("/dev/tty", "rb")
     class_mock.assert_called_once_with(text.decode())
     instance_mock.run.assert_called_once()
+
+
+def test_file_input_cli(monkeypatch: MonkeyPatch, tmp_path: Path) -> None:
+    runner = CliRunner()
+    text = "This iS! aTe xt2 F0r T3sT!ng"
+    (tmp_path / "text_file").write_text(text)
+    class_mock = Mock()
+    instance_mock = Mock()
+    with monkeypatch.context():
+        class_mock.return_value = instance_mock
+        monkeypatch.setattr("rexi.cli.RexiApp", class_mock)
+        runner.invoke(app, args=["-i", str(tmp_path / "text_file")])
+    class_mock.assert_called_once_with(text)