Skip to content

Commit c5ff45c

Browse files
authored
Merge pull request #34 from Textualize/pipe
WIP pipe support
2 parents e569494 + 3875456 commit c5ff45c

File tree

2 files changed

+54
-5
lines changed

2 files changed

+54
-5
lines changed

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "toolong"
3-
version = "1.2.2"
3+
version = "1.3.0"
44
description = "A terminal log file viewer / tailer / analyzer"
55
authors = ["Will McGugan <[email protected]>"]
66
license = "MIT"
@@ -13,7 +13,7 @@ documentation = "https://github.com/textualize/toolong"
1313
[tool.poetry.dependencies]
1414
python = "^3.8"
1515
click = "^8.1.7"
16-
textual = "^0.50.0"
16+
textual = "^0.52.0"
1717
typing-extensions = "^4.9.0"
1818

1919
[tool.poetry.group.dev.dependencies]

src/toolong/cli.py

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from __future__ import annotations
22

33
from importlib.metadata import version
4+
import os
5+
import sys
6+
47
import click
58

69
from toolong.ui import UI
@@ -19,9 +22,55 @@
1922
)
2023
def run(files: list[str], merge: bool, output_merge: str) -> None:
2124
"""View / tail / search log files."""
22-
if not files:
25+
stdin_tty = sys.__stdin__.isatty()
26+
if not files and stdin_tty:
2327
ctx = click.get_current_context()
2428
click.echo(ctx.get_help())
2529
ctx.exit()
26-
ui = UI(files, merge=merge, save_merge=output_merge)
27-
ui.run()
30+
if stdin_tty:
31+
try:
32+
ui = UI(files, merge=merge, save_merge=output_merge)
33+
ui.run()
34+
except Exception:
35+
pass
36+
else:
37+
import signal
38+
import selectors
39+
import subprocess
40+
import tempfile
41+
42+
def request_exit(*args) -> None:
43+
"""Don't write anything when a signal forces an error."""
44+
sys.stderr.write("^C")
45+
46+
signal.signal(signal.SIGINT, request_exit)
47+
signal.signal(signal.SIGTERM, request_exit)
48+
49+
# Write piped data to a temporary file
50+
with tempfile.NamedTemporaryFile(
51+
mode="w+b", buffering=0, prefix="tl_"
52+
) as temp_file:
53+
54+
# Get input directly from /dev/tty to free up stdin
55+
with open("/dev/tty", "rb", buffering=0) as tty_stdin:
56+
# Launch a new process to render the UI
57+
with subprocess.Popen(
58+
[sys.argv[0], temp_file.name],
59+
stdin=tty_stdin,
60+
close_fds=True,
61+
env={**os.environ, "TEXTUAL_ALLOW_SIGNALS": "1"},
62+
) as process:
63+
64+
# Current process copies from stdin to the temp file
65+
selector = selectors.SelectSelector()
66+
selector.register(sys.stdin.fileno(), selectors.EVENT_READ)
67+
68+
while process.poll() is None:
69+
for _, event in selector.select(0.1):
70+
if process.poll() is not None:
71+
break
72+
if event & selectors.EVENT_READ:
73+
if line := os.read(sys.stdin.fileno(), 1024 * 64):
74+
temp_file.write(line)
75+
else:
76+
break

0 commit comments

Comments
 (0)