Skip to content

Commit 1ae7b61

Browse files
committed
Console Preparations
1 parent af825fe commit 1ae7b61

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

setup_hook.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ def run_hook(release_path: str, data_path: str) -> None:
1717
"editor",
1818
"desktop-service",
1919
"runtimes",
20+
"console",
2021
])
2122
}
2223

src/utils/shellhost.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from typing import IO, Self, Callable, TypeAlias
2+
3+
from subprocess import Popen, PIPE, STDOUT
4+
from threading import Thread
5+
6+
OutputCallback: TypeAlias = Callable[[str], None]
7+
FinishedCallback: TypeAlias = Callable[[], None]
8+
9+
class ShellProcess:
10+
process: Popen[str] | None = None
11+
output_callbacks: list[OutputCallback] = []
12+
finished_callbacks: list[FinishedCallback] = []
13+
14+
def __init__(
15+
self: Self,
16+
args: list[str],
17+
output_callbacks: list[OutputCallback],
18+
finished_callbacks: list[FinishedCallback] = [],
19+
) -> None:
20+
self.output_callbacks = output_callbacks
21+
self.finished_callbacks = finished_callbacks
22+
self.process = Popen(
23+
args,
24+
stdin=PIPE,
25+
stdout=PIPE,
26+
stderr=STDOUT,
27+
universal_newlines=True
28+
)
29+
30+
thread = Thread(
31+
target=self.reader_thread,
32+
args=(self.process.stdout,)
33+
)
34+
35+
thread.daemon = True
36+
thread.start()
37+
38+
def on_flush(self: Self, chunk: str):
39+
for callback in self.output_callbacks:
40+
callback(chunk)
41+
42+
def alert_finished(self: Self) -> None:
43+
for callback in self.finished_callbacks:
44+
callback()
45+
46+
def reader_thread(self: Self, stdout_pipe: IO[str] | None):
47+
if not stdout_pipe:
48+
return
49+
50+
buffer = ""
51+
52+
while True:
53+
char = stdout_pipe.read(1)
54+
55+
if not char:
56+
if buffer:
57+
self.on_flush(buffer)
58+
buffer = ""
59+
60+
self.alert_finished()
61+
break
62+
63+
buffer += char
64+
65+
if char in ['\n', '\r']:
66+
self.on_flush(buffer)
67+
buffer = ""
68+
69+
def push_input(self: Self, input_data: str) -> None:
70+
if self.process and self.process.stdin:
71+
self.process.stdin.write(input_data + "\n")
72+
self.process.stdin.flush()
73+
74+
def terminate(self: Self) -> None:
75+
if self.process:
76+
self.process.terminate()
77+
self.process.wait()
78+
self.process = None
79+

src/windows/base.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ def __init__(
1616
frameless: bool = True,
1717
fulldrag: bool = False,
1818
resizable: bool = True,
19+
min_dims: tuple[int, int] = (200, 100),
1920
) -> None:
2021
self.window = create_window(
2122
title=title,
2223
url=url,
2324
js_api=self,
2425
width=dims[0],
2526
height=dims[1],
27+
min_size=min_dims,
2628
transparent=acryllic,
2729
vibrancy=acryllic,
2830
frameless=frameless,

src/windows/console.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from typing import Self
2+
3+
from utils.updater import Updater
4+
from utils.shellhost import ShellProcess
5+
6+
from windows.base import Base
7+
8+
class Console(Base):
9+
updater: Updater
10+
shell: ShellProcess
11+
filepath: str
12+
13+
def __init__(
14+
self: Self,
15+
url: str,
16+
filepath: str,
17+
) -> None:
18+
super().__init__(
19+
url=url,
20+
title="GraphScript Launcher",
21+
dims=(900, 600),
22+
min_dims=(480, 320),
23+
)
24+
25+
self.filepath = filepath
26+
self.window.events.loaded += self.start_shell
27+
28+
def close(self: Self) -> None:
29+
if self.shell: self.shell.terminate()
30+
super().close()
31+
32+
def add_console_output(self: Self, message: str) -> None:
33+
self.window.evaluate_js(
34+
f"window.pushConsoleOutput({repr(message)});"
35+
)
36+
37+
def emit_finished(self: Self) -> None:
38+
self.window.evaluate_js("window.emitFinished();")
39+
40+
def start_shell(self: Self) -> None:
41+
self.shell = ShellProcess(
42+
[
43+
"gsam",
44+
self.filepath,
45+
],
46+
[self.add_console_output],
47+
[self.emit_finished]
48+
)
49+
50+
def push_input(self: Self, input_data: str) -> None:
51+
self.shell.push_input(input_data)
52+

0 commit comments

Comments
 (0)