-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcontainer_exec.py
More file actions
72 lines (57 loc) · 2.07 KB
/
container_exec.py
File metadata and controls
72 lines (57 loc) · 2.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
from textual import events
from textual_terminal import Terminal
from textual.app import ComposeResult
from textual.widgets import Static
import shutil
# --- Monkey patch textual-terminal key handling ---
async def patched_on_key(self, event: events.Key) -> None:
if self.emulator is None:
return
if event.key == "shift+escape":
self.app.set_focus(None)
return
event.stop()
control_key_map = {
"ctrl+c": "\x03",
"ctrl+d": "\x04",
"ctrl+z": "\x1A",
"ctrl+r": "\x12",
"ctrl+a": "\x01",
"ctrl+e": "\x05",
"ctrl+k": "\x0B",
"ctrl+u": "\x15",
"ctrl+l": "\x0C",
}
if event.key in control_key_map:
await self.send_queue.put(["stdin", control_key_map[event.key]])
elif event.key == "enter":
await self.send_queue.put(["stdin", "\n"])
elif event.key == "backspace":
await self.send_queue.put(["stdin", "\x7f"])
else:
char = self.ctrl_keys.get(event.key) or event.character
if char:
await self.send_queue.put(["stdin", char])
Terminal.on_key = patched_on_key
# --- Container shell widget using textual-terminal ---
class ContainerShell(Static):
"""Widget that runs an interactive shell inside a Docker container."""
def __init__(self, container_id: str, **kwargs):
super().__init__(**kwargs)
self.container_id = container_id
self.terminal = None
def compose(self) -> ComposeResult:
"""Create a terminal running docker exec."""
shell = "/bin/bash" if shutil.which("bash") else "/bin/sh"
docker_cmd = f"docker exec -i -t {self.container_id} {shell}"
self.terminal = Terminal(
command=docker_cmd,
id="container-terminal"
)
yield self.terminal
def on_mount(self) -> None:
"""Start the terminal when mounted. Focus is handled by the parent screen
when the Terminal tab becomes active so the terminal doesn't steal focus
on initial mount."""
if self.terminal:
self.terminal.start()