libtmux-async 0.1.0.alpha.2 → 0.1.0.alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +248 -70
- data/lib/libtmux/async/control.rb +27 -21
- data/lib/libtmux/async/scope.rb +1 -0
- data/lib/libtmux/async/server.rb +13 -8
- data/lib/libtmux/async/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e64f6117feba9404d8cd8fabcdacbdf1ef098f3b1bdc6226c4f03c66a2581fbc
|
|
4
|
+
data.tar.gz: 9ff7ca35a31683ccdf6ba76562ec4ff156aaf2eb75e9e13e1e1a197abefbdbc4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cb9f3e5f40e3ad10061c168a68728d33a19a6917071bf4853f63a83f122427c7b9caa43312a120aa2d30fa4abaeb83bfd36457717099a06a484479b135f015f7
|
|
7
|
+
data.tar.gz: df18e0b035473957c327faf618798fd1dbd2e12e4e19aa5fc423ce5426442d5842d2637e6246ea345f9a9b833b387ae2805c35e2cba04b8cc2e373f280f01567
|
data/README.md
CHANGED
|
@@ -11,68 +11,135 @@
|
|
|
11
11
|
|
|
12
12
|
# libtmux-async
|
|
13
13
|
|
|
14
|
-
Run libtmux operations inside an application-owned Async task
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
Run libtmux operations inside an application-owned Async task: a
|
|
15
|
+
[subprocess facade][async-server], [ordered mapping][async-scope-map],
|
|
16
|
+
[control replies][guardedreply] and
|
|
17
|
+
[event subscriptions][async-controlsubscription].
|
|
18
|
+
|
|
19
|
+
[API reference](https://libtmux.org/en/ruby/latest/reference/libtmux-async/) ·
|
|
20
|
+
[Guide](https://libtmux.org/en/ruby/latest/guides/async/) ·
|
|
21
|
+
[RubyGems](https://rubygems.org/gems/libtmux-async)
|
|
17
22
|
|
|
18
23
|
</div>
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
Part of [libtmux for Ruby](https://github.com/libtmux/libtmux-ruby#readme).
|
|
26
|
+
Built on [libtmux](https://github.com/libtmux/libtmux-ruby/tree/master/gems/libtmux).
|
|
27
|
+
|
|
28
|
+
Imports start no scheduler, tmux server or background task. A scope borrows a
|
|
29
|
+
core [`Server`][server] and leaves its daemon running when the scope exits.
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
**Contents** — [Quick start](#quick-start) ·
|
|
32
|
+
[Cancel](#cancel-a-request-without-stalling-the-others) ·
|
|
33
|
+
[Map](#keep-results-ordered-and-bounded) ·
|
|
34
|
+
[Control](#read-control-events-in-a-scope) ·
|
|
35
|
+
[Leaves out](#what-it-leaves-out) · [Support](#support-and-status) ·
|
|
36
|
+
[Documentation](#documentation)
|
|
24
37
|
|
|
25
|
-
|
|
26
|
-
and its cleanup. This excerpt uses that server and creates the Async root:
|
|
38
|
+
## Quick start
|
|
27
39
|
|
|
28
|
-
|
|
40
|
+
Install the alpha. It needs Ruby 3.3 or newer and tmux 3.3a or newer on
|
|
41
|
+
`PATH`:
|
|
42
|
+
|
|
43
|
+
```console
|
|
44
|
+
$ gem install libtmux-async --pre
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Open a scope over a core server with [`LibTmux::Async.open`][async-open], then
|
|
48
|
+
capture every pane concurrently with [`Scope#map`][async-scope-map]. The outer
|
|
49
|
+
[`Server.start`][server-start] block only supplies a server for the scope to
|
|
50
|
+
borrow:
|
|
51
|
+
|
|
52
|
+
<!-- example: api_async_scope/main -->
|
|
29
53
|
```ruby
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
54
|
+
require "libtmux"
|
|
55
|
+
require "libtmux/async"
|
|
56
|
+
|
|
57
|
+
LibTmux::Server.start do |server|
|
|
58
|
+
server.new_session(name: "work", command: ["/bin/cat"])
|
|
59
|
+
server.new_session(name: "logs", command: ["/bin/cat"])
|
|
60
|
+
Async do |parent|
|
|
61
|
+
LibTmux::Async.open(parent: parent, server: server) do |scope|
|
|
62
|
+
refs = scope.server.list_panes.map(&:ref)
|
|
63
|
+
screens = scope.map(refs, concurrency: 2) { |ref| scope.server.pane(ref).capture }
|
|
64
|
+
puts "captured panes: #{screens.length}"
|
|
65
|
+
puts "all succeeded: #{screens.all?(&:success?)}"
|
|
36
66
|
end
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
67
|
+
end.wait
|
|
68
|
+
end
|
|
69
|
+
```
|
|
70
|
+
<!-- /example -->
|
|
71
|
+
|
|
72
|
+
It prints:
|
|
73
|
+
|
|
74
|
+
```text
|
|
75
|
+
captured panes: 2
|
|
76
|
+
all succeeded: true
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- Leave out `parent:` to use the current Async task.
|
|
80
|
+
- A scope rejects use from another thread, process or scheduler, so create one
|
|
81
|
+
scope for each scheduler thread.
|
|
82
|
+
- Scope exit retires its clients and joins its owned tasks.
|
|
83
|
+
|
|
84
|
+
## Cancel a request without stalling the others
|
|
85
|
+
|
|
86
|
+
### [`Async::Server#run`][async-server-run]: cancel a request that is waiting
|
|
87
|
+
|
|
88
|
+
`scope.server.run` waits for a tmux command in a task. Cancel that task and
|
|
89
|
+
the scope retires its client, while sibling requests keep running.
|
|
90
|
+
|
|
91
|
+
[`wait_for`][async-server-wait_for] returns once the request has signalled
|
|
92
|
+
that it is running, so the cancel arrives while it waits:
|
|
93
|
+
|
|
94
|
+
<!-- example: api_async_run/main -->
|
|
95
|
+
```ruby
|
|
96
|
+
require "libtmux"
|
|
97
|
+
require "libtmux/async"
|
|
98
|
+
|
|
99
|
+
LibTmux::Server.start do |server|
|
|
100
|
+
server.new_session(name: "work", command: ["/bin/cat"])
|
|
101
|
+
Async do |parent|
|
|
102
|
+
LibTmux::Async.open(parent: parent, server: server) do |scope|
|
|
103
|
+
waiting = parent.async do
|
|
104
|
+
scope.server.run(["wait-for", "-S", "ready", ";", "wait-for", "held"], timeout: 5)
|
|
105
|
+
rescue LibTmux::Cancelled => error
|
|
106
|
+
error
|
|
107
|
+
end
|
|
108
|
+
scope.server.wait_for("ready", timeout: 5)
|
|
109
|
+
waiting.cancel
|
|
110
|
+
failure = waiting.wait
|
|
111
|
+
puts "request: #{failure.class}"
|
|
112
|
+
puts "delivery: #{failure.delivery}"
|
|
41
113
|
end
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
failure = waiting.wait
|
|
45
|
-
Example.check(failure.is_a?(LibTmux::Cancelled), "cancellation lost")
|
|
46
|
-
Example.check(failure.delivery == :possibly_sent, "cancelled dispatch claimed no effects")
|
|
47
|
-
Example.raises(Errno::ECHILD) { Process.waitpid(failure.pid, Process::WNOHANG) }
|
|
48
|
-
Example.check(scope.server.diagnostics.fetch(:admitted_requests).zero?, "cancelled client remains admitted")
|
|
49
|
-
end
|
|
50
|
-
end.wait
|
|
114
|
+
end.wait
|
|
115
|
+
end
|
|
51
116
|
```
|
|
52
117
|
<!-- /example -->
|
|
53
118
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
`
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
`
|
|
74
|
-
|
|
75
|
-
|
|
119
|
+
It prints:
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
request: LibTmux::Cancelled
|
|
123
|
+
delivery: possibly_sent
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- `run` returns the same binary [`CommandResult`][commandresult] as the core.
|
|
127
|
+
- [`Cancelled`][cancelled] carries `delivery` as `:not_sent` or
|
|
128
|
+
`:possibly_sent`. A deadline cannot undo tmux effects.
|
|
129
|
+
- Interactive terminal attachment stays on the blocking core and raises
|
|
130
|
+
[`UnsupportedFeatureError`][unsupportedfeatureerror] here.
|
|
131
|
+
|
|
132
|
+
The [complete program](../../examples/async_cancel.rb) also keeps capturing
|
|
133
|
+
while the request waits, and checks that the cancelled client is reaped. The
|
|
134
|
+
contract is in [Async scope][behavior-async-scope].
|
|
135
|
+
|
|
136
|
+
## Keep results ordered and bounded
|
|
137
|
+
|
|
138
|
+
### [`Scope#map`][async-scope-map]: input order, capped payloads
|
|
139
|
+
|
|
140
|
+
`map` runs a block for each item, up to `concurrency:` at a time, and returns a
|
|
141
|
+
frozen Array in input order. The quick start is a `map`. These limits apply to
|
|
142
|
+
every scope:
|
|
76
143
|
|
|
77
144
|
| Scope limit | Default |
|
|
78
145
|
| --- | --- |
|
|
@@ -84,23 +151,134 @@ they are not exact Ruby heap measurements.
|
|
|
84
151
|
| Control connections | 4 |
|
|
85
152
|
| Ordinary command deadline | 5 seconds |
|
|
86
153
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
`
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
[
|
|
105
|
-
|
|
106
|
-
|
|
154
|
+
- Independent requests may complete out of order, and the result is still in
|
|
155
|
+
input order.
|
|
156
|
+
- `map` caps retained items and counts payload bytes of strings, primitive
|
|
157
|
+
values, [`CommandResult`][commandresult], Arrays and Hashes. Cycles and deep
|
|
158
|
+
nesting are refused.
|
|
159
|
+
- An application-defined result needs a `result_bytes:` callable that returns
|
|
160
|
+
a nonnegative Integer.
|
|
161
|
+
- Keep measured values unchanged until the map returns. The counts cover
|
|
162
|
+
payload bytes and do not measure the Ruby heap.
|
|
163
|
+
|
|
164
|
+
The contract is in [Async map][behavior-async-map].
|
|
165
|
+
|
|
166
|
+
## Read control events in a scope
|
|
167
|
+
|
|
168
|
+
### [`Async::Server#open_control`][async-server-open_control]: replies and events
|
|
169
|
+
|
|
170
|
+
A control connection has its own request, reply and subscriber limits.
|
|
171
|
+
[`exchange`][async-controlconnection-exchange] runs one command, and
|
|
172
|
+
[`events`][async-controlconnection-events] yields what tmux reports outside a
|
|
173
|
+
reply:
|
|
174
|
+
|
|
175
|
+
<!-- example: api_async_control/main -->
|
|
176
|
+
```ruby
|
|
177
|
+
require "libtmux"
|
|
178
|
+
require "libtmux/async"
|
|
179
|
+
|
|
180
|
+
LibTmux::Server.start do |server|
|
|
181
|
+
session = server.new_session(name: "work", command: ["/bin/cat"])
|
|
182
|
+
window = session.list_windows.fetch(0)
|
|
183
|
+
Async do |parent|
|
|
184
|
+
LibTmux::Async.open(parent: parent, server: server) do |scope|
|
|
185
|
+
scope.server.open_control(session: session.ref) do |control|
|
|
186
|
+
reply = control.exchange("display-message -p ready", timeout: 5)
|
|
187
|
+
puts "reply: #{reply.blocks.last.body.strip}"
|
|
188
|
+
events = control.events
|
|
189
|
+
window.rename("renamed")
|
|
190
|
+
event = events.next(timeout: 5) until event&.raw&.start_with?("%window-renamed")
|
|
191
|
+
puts "event: #{event.raw.strip}"
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end.wait
|
|
195
|
+
end
|
|
196
|
+
```
|
|
197
|
+
<!-- /example -->
|
|
198
|
+
|
|
199
|
+
It prints:
|
|
200
|
+
|
|
201
|
+
```text
|
|
202
|
+
reply: ready
|
|
203
|
+
event: %window-renamed @0 renamed
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
- `exchange` answers a [`GuardedReply`][guardedreply] with `:boundary_window`
|
|
207
|
+
attribution. It makes no claim that the command finished.
|
|
208
|
+
- Events arrive through `events.next` or an explicit
|
|
209
|
+
[`subscribe`][async-controlconnection-subscribe]. Consumer callbacks run
|
|
210
|
+
outside the parser.
|
|
211
|
+
- A reliable subscription raises on overflow, and a tail subscription reports
|
|
212
|
+
the dropped range.
|
|
213
|
+
- Cancelling a dispatched exchange that is not drained closes the connection.
|
|
214
|
+
- [`pause_output`][async-controlconnection-pause_output] and
|
|
215
|
+
[`resume_output`][async-controlconnection-resume_output] report possible
|
|
216
|
+
loss through gap events. A gap does not show that the action took effect.
|
|
217
|
+
- To reconnect, close the connection and pass it as `reconnect:`. The
|
|
218
|
+
replacement stays owned by the scope, has a new generation, and starts with
|
|
219
|
+
a gap of unknown loss. Nothing is replayed.
|
|
220
|
+
|
|
221
|
+
The contract is in [Control connections][behavior-control].
|
|
222
|
+
|
|
223
|
+
## What it leaves out
|
|
224
|
+
|
|
225
|
+
- **Terminal attachment.** `attach` stays on the blocking core and raises
|
|
226
|
+
[`UnsupportedFeatureError`][unsupportedfeatureerror] on this facade.
|
|
227
|
+
- **Replay.** Reconnect and resume never replay requests or missed output. See
|
|
228
|
+
[Control connections][behavior-control].
|
|
229
|
+
- **A scheduler.** Imports start no scheduler or background task, and your
|
|
230
|
+
application owns the Async root task. See [Execution modes][doc-modes].
|
|
231
|
+
- **Cross-thread scopes.** A scope belongs to the thread, process and
|
|
232
|
+
scheduler that opened it. See [Async scope][behavior-async-scope].
|
|
233
|
+
|
|
234
|
+
## Support and status
|
|
235
|
+
|
|
236
|
+
**Alpha.** APIs may change between releases.
|
|
237
|
+
|
|
238
|
+
- **Ruby 3.3 or newer** and **tmux 3.3a or newer.** The facade dispatches
|
|
239
|
+
through a version-checked core server, so it carries the same daemon release
|
|
240
|
+
check.
|
|
241
|
+
- **Control connections need tmux 3.7 or newer.**
|
|
242
|
+
[`open_control`][async-server-open_control] refuses an older daemon before a
|
|
243
|
+
control client attaches.
|
|
244
|
+
- **Async 2.46.** The gem depends on `async` ~> 2.46.0 and the same version of
|
|
245
|
+
`libtmux`.
|
|
246
|
+
- **Linux, including WSL, and macOS.** The [compatibility workflow][compat]
|
|
247
|
+
runs Ruby 3.3, 3.4 and 4.0 with tmux 3.3a through 3.8 on Ubuntu 24.04 and retains
|
|
248
|
+
per-revision results. macOS is supported on a best-effort basis, and CI
|
|
249
|
+
coverage for it is highly limited.
|
|
250
|
+
|
|
251
|
+
## Documentation
|
|
252
|
+
|
|
253
|
+
| | |
|
|
254
|
+
| --- | --- |
|
|
255
|
+
| [Reference](https://libtmux.org/en/ruby/latest/reference/libtmux-async/) | The Async classes, one page each |
|
|
256
|
+
| [Async guide](https://libtmux.org/en/ruby/latest/guides/async/) | Running concurrent commands within an owned scope |
|
|
257
|
+
| [Execution modes][doc-modes] | Blocking calls, Async tasks and control subscriptions |
|
|
258
|
+
| [Recipes][doc-recipes] | Complete programs with checked excerpts |
|
|
259
|
+
| [Public behavior][behavior-async-scope] | Scheduling, ownership and limits of a scope |
|
|
260
|
+
|
|
261
|
+
[async-controlconnection-events]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-controlconnection-events/
|
|
262
|
+
[async-controlconnection-exchange]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-controlconnection-exchange/
|
|
263
|
+
[async-controlconnection-pause_output]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-controlconnection-pause_output/
|
|
264
|
+
[async-controlconnection-resume_output]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-controlconnection-resume_output/
|
|
265
|
+
[async-controlconnection-subscribe]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-controlconnection-subscribe/
|
|
266
|
+
[async-controlsubscription]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-controlsubscription/
|
|
267
|
+
[async-open]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-open/
|
|
268
|
+
[async-scope-map]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-scope-map/
|
|
269
|
+
[async-server]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-server/
|
|
270
|
+
[async-server-open_control]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-server-open_control/
|
|
271
|
+
[async-server-run]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-server-run/
|
|
272
|
+
[async-server-wait_for]: https://libtmux.org/en/ruby/latest/reference/libtmux-async-server-wait_for/
|
|
273
|
+
[behavior-async-map]: ../../docs/reference/behavior.md#async-map
|
|
274
|
+
[behavior-async-scope]: ../../docs/reference/behavior.md#async-scope
|
|
275
|
+
[behavior-control]: ../../docs/reference/behavior.md#control-connections
|
|
276
|
+
[cancelled]: https://libtmux.org/en/ruby/latest/reference/libtmux-cancelled/
|
|
277
|
+
[commandresult]: https://libtmux.org/en/ruby/latest/reference/libtmux-commandresult/
|
|
278
|
+
[compat]: https://github.com/libtmux/libtmux-ruby/actions/workflows/compatibility.yml
|
|
279
|
+
[doc-modes]: ../../docs/modes.md
|
|
280
|
+
[doc-recipes]: ../../docs/recipes.md
|
|
281
|
+
[guardedreply]: https://libtmux.org/en/ruby/latest/reference/libtmux-guardedreply/
|
|
282
|
+
[server]: https://libtmux.org/en/ruby/latest/reference/libtmux-server/
|
|
283
|
+
[server-start]: https://libtmux.org/en/ruby/latest/reference/libtmux-server-start/
|
|
284
|
+
[unsupportedfeatureerror]: https://libtmux.org/en/ruby/latest/reference/libtmux-unsupportedfeatureerror/
|
|
@@ -23,30 +23,34 @@ module LibTmux
|
|
|
23
23
|
raise ArgumentError, "timeout must be finite and nonnegative"
|
|
24
24
|
end
|
|
25
25
|
deadline = timeout && clock + timeout
|
|
26
|
-
loop
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
# Kernel#loop would swallow the StopIteration that ends the stream and
|
|
27
|
+
# return nil from next.
|
|
28
|
+
while true
|
|
29
|
+
begin
|
|
30
|
+
@mutex.synchronize do
|
|
31
|
+
if @gap
|
|
32
|
+
gap, @gap = @gap, nil
|
|
33
|
+
return gap
|
|
34
|
+
end
|
|
35
|
+
unless @queue.empty?
|
|
36
|
+
event = @queue.shift
|
|
37
|
+
@bytes -= event.bytesize
|
|
38
|
+
return event
|
|
39
|
+
end
|
|
40
|
+
raise @failure if @failure
|
|
41
|
+
raise StopIteration if @closed
|
|
36
42
|
end
|
|
37
|
-
|
|
38
|
-
raise
|
|
39
|
-
end
|
|
40
|
-
remaining = deadline && deadline - clock
|
|
41
|
-
raise DeadlineExceeded.new("control event deadline elapsed", phase: :subscription) if remaining && remaining <= 0
|
|
43
|
+
remaining = deadline && deadline - clock
|
|
44
|
+
raise DeadlineExceeded.new("control event deadline elapsed", phase: :subscription) if remaining && remaining <= 0
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
if remaining
|
|
47
|
+
::Async::Task.current.with_timeout(remaining) { @changed.wait }
|
|
48
|
+
else
|
|
49
|
+
@changed.wait
|
|
50
|
+
end
|
|
51
|
+
rescue ::Async::TimeoutError
|
|
52
|
+
raise DeadlineExceeded.new("control event deadline elapsed", phase: :subscription)
|
|
47
53
|
end
|
|
48
|
-
rescue ::Async::TimeoutError
|
|
49
|
-
raise DeadlineExceeded.new("control event deadline elapsed", phase: :subscription)
|
|
50
54
|
end
|
|
51
55
|
end
|
|
52
56
|
|
|
@@ -60,6 +64,7 @@ module LibTmux
|
|
|
60
64
|
class ControlConnection < LibTmux::ControlConnection
|
|
61
65
|
def initialize(scope:, binding:, session_id:, reconnect: nil, **limits)
|
|
62
66
|
@scope = scope
|
|
67
|
+
@release = binding.release
|
|
63
68
|
@writer_changed = ::Async::Notification.new
|
|
64
69
|
@startup_changed = ::Async::Notification.new
|
|
65
70
|
@exchanges, @exchange_changed = {}, ::Async::Notification.new
|
|
@@ -81,6 +86,7 @@ module LibTmux
|
|
|
81
86
|
end
|
|
82
87
|
raise CapacityError.new("control command exceeds its byte limit", phase: :admission) if line.bytesize > @max_command
|
|
83
88
|
|
|
89
|
+
Internal::NativeGuard.check_line(line, @release)
|
|
84
90
|
deadline = clock + timeout
|
|
85
91
|
request = admit(line, cancel, flow: flow)
|
|
86
92
|
@exchanges[request.id] = true
|
data/lib/libtmux/async/scope.rb
CHANGED
|
@@ -186,6 +186,7 @@ module LibTmux
|
|
|
186
186
|
|
|
187
187
|
def open_control(binding:, session_id:, **options)
|
|
188
188
|
ensure_open
|
|
189
|
+
Internal::TmuxVersion.require_control(binding.release)
|
|
189
190
|
@controls.reject!(&:closed?)
|
|
190
191
|
raise CapacityError.new("Async control capacity is exhausted", phase: :admission) if @controls.length >= @max_controls
|
|
191
192
|
|
data/lib/libtmux/async/server.rb
CHANGED
|
@@ -12,14 +12,7 @@ module LibTmux
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def run(argv, input: "".b, timeout: 5.0, cancel: nil)
|
|
15
|
-
|
|
16
|
-
ensure_open
|
|
17
|
-
validate_argv(argv)
|
|
18
|
-
raise ArgumentError, "raw commands cannot override endpoint flags" if argv.first.start_with?("-")
|
|
19
|
-
|
|
20
|
-
fence, marker = Internal::TmuxVersion.fence(@release)
|
|
21
|
-
result = @scope.__send__(:execute, @pin.command_prefix + fence + argv, input: input, timeout: timeout, cancel: cancel)
|
|
22
|
-
Internal::TmuxVersion.check_fence(result, marker, @release)
|
|
15
|
+
dispatch(argv, input: input, timeout: timeout, cancel: cancel)
|
|
23
16
|
end
|
|
24
17
|
|
|
25
18
|
def close
|
|
@@ -66,6 +59,18 @@ module LibTmux
|
|
|
66
59
|
|
|
67
60
|
private
|
|
68
61
|
|
|
62
|
+
def dispatch(argv, input: "".b, timeout: 5.0, cancel: nil, repaired_break: false)
|
|
63
|
+
ensure_owner
|
|
64
|
+
ensure_open
|
|
65
|
+
validate_argv(argv)
|
|
66
|
+
raise ArgumentError, "raw commands cannot override endpoint flags" if argv.first.start_with?("-")
|
|
67
|
+
|
|
68
|
+
Internal::NativeGuard.check(argv, @release, repaired_break: repaired_break)
|
|
69
|
+
fence, marker = Internal::TmuxVersion.fence(@release)
|
|
70
|
+
result = @scope.__send__(:execute, @pin.command_prefix + fence + argv, input: input, timeout: timeout, cancel: cancel)
|
|
71
|
+
Internal::TmuxVersion.check_fence(result, marker, @release)
|
|
72
|
+
end
|
|
73
|
+
|
|
69
74
|
def ensure_owner
|
|
70
75
|
@scope.__send__(:ensure_owner)
|
|
71
76
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: libtmux-async
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.0.alpha.
|
|
4
|
+
version: 0.1.0.alpha.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- libtmux contributors
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - '='
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 0.1.0.alpha.
|
|
18
|
+
version: 0.1.0.alpha.3
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - '='
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: 0.1.0.alpha.
|
|
25
|
+
version: 0.1.0.alpha.3
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: async
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -59,7 +59,7 @@ licenses:
|
|
|
59
59
|
- MIT
|
|
60
60
|
metadata:
|
|
61
61
|
source_code_uri: https://github.com/libtmux/libtmux-ruby
|
|
62
|
-
documentation_uri: https://libtmux.org/en/ruby/v0.1.0.alpha.
|
|
62
|
+
documentation_uri: https://libtmux.org/en/ruby/v0.1.0.alpha.3/reference/
|
|
63
63
|
rdoc_options: []
|
|
64
64
|
require_paths:
|
|
65
65
|
- lib
|