-
Notifications
You must be signed in to change notification settings - Fork 0
/
Panel.php
120 lines (106 loc) · 3.46 KB
/
Panel.php
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<?php
declare(strict_types = 1);
namespace Innmind\SilentCartographer\Command;
use Innmind\SilentCartographer\{
Protocol,
IPC\Message\PanelActivated,
IPC\Message\PanelDeactivated,
};
use Innmind\IPC\{
IPC,
Process,
Process\Name,
Exception\RuntimeException,
};
use Innmind\OperatingSystem\CurrentProcess\Signals;
use Innmind\Signals\Signal;
use Innmind\CLI\{
Command,
Command\Arguments,
Command\Options,
Environment,
};
use Innmind\Stream\Writable;
use Innmind\Immutable\Str;
use function Innmind\Immutable\unwrap;
final class Panel implements Command
{
private IPC $ipc;
private Name $subRoutine;
private Protocol $protocol;
private Signals $signals;
public function __construct(
IPC $ipc,
Name $subRoutine,
Protocol $protocol,
Signals $signals
) {
$this->ipc = $ipc;
$this->subRoutine = $subRoutine;
$this->protocol = $protocol;
$this->signals = $signals;
}
public function __invoke(Environment $env, Arguments $arguments, Options $options): void
{
$this->ipc->wait($this->subRoutine);
$process = $this->ipc->get($this->subRoutine);
$this->safe($process);
$process->send(new PanelActivated(...unwrap($arguments->pack())));
$this->print(
$process,
$env->output(),
$options->contains('format') ? $options->get('format') : '[{type}][{pid}][{room}][{tags}] {activity}',
);
}
public function toString(): string
{
return <<<USAGE
panel ...tags --format=
Open a panel to display all activity that matches the given tags
When no tag provided it will display all messages
Available placeholders for the format option:
* {type}
* {pid}
* {room}
* {tags}
* {activity}
USAGE;
}
private function safe(Process $process): void
{
$softClose = function() use ($process): void {
$process->send(new PanelDeactivated);
try {
$process->close();
} catch (RuntimeException $e) {
// it can happen if the sub routine closes before we trigger the
// close
}
};
$this->signals->listen(Signal::hangup(), $softClose);
$this->signals->listen(Signal::interrupt(), $softClose);
$this->signals->listen(Signal::abort(), $softClose);
$this->signals->listen(Signal::terminate(), $softClose);
$this->signals->listen(Signal::terminalStop(), $softClose);
$this->signals->listen(Signal::alarm(), $softClose);
}
private function print(Process $process, Writable $output, string $format): void
{
try {
do {
$message = $process->wait();
$roomActivity = $this->protocol->decode($message);
$output->write(
Str::of("$format\n")
->replace('{type}', $roomActivity->program()->type()->toString())
->replace('{pid}', $roomActivity->program()->id()->toString())
->replace('{room}', $roomActivity->program()->room()->location()->path()->toString())
->replace('{tags}', \implode('/', $roomActivity->activity()->tags()->list()))
->replace('{activity}', $roomActivity->activity()->toString()),
);
} while (!$process->closed());
} catch (RuntimeException $e) {
// stop the loop
}
}
}