libtmux-async 0.1.0.alpha.1

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.
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LibTmux
4
+ module Async
5
+ class Server < LibTmux::Server
6
+ def initialize(scope, source)
7
+ raise ArgumentError, "server must be a bound LibTmux::Server" unless source.is_a?(LibTmux::Server)
8
+
9
+ @scope, @source = scope, source
10
+ @mutex = Mutex.new
11
+ source.__send__(:with_bound_endpoint) { |endpoint, pin| @endpoint, @pin = endpoint, pin }
12
+ end
13
+
14
+ def run(argv, input: "".b, timeout: 5.0, cancel: nil)
15
+ ensure_owner
16
+ ensure_open
17
+ validate_argv(argv)
18
+ raise ArgumentError, "raw commands cannot override endpoint flags" if argv.first.start_with?("-")
19
+
20
+ @scope.__send__(:execute, @pin.command_prefix + argv, input: input, timeout: timeout, cancel: cancel)
21
+ end
22
+
23
+ def close
24
+ @scope.close
25
+ end
26
+
27
+ # Scope counters remain readable after this facade closes its scope.
28
+ def diagnostics
29
+ @scope.diagnostics
30
+ end
31
+
32
+ def open_control(session:, **options)
33
+ session_id = target(session, :session)
34
+ control = @scope.__send__(:open_control, binding: @pin, session_id: session_id, **options)
35
+ return control unless block_given?
36
+
37
+ failure = result = nil
38
+ begin
39
+ result = yield control
40
+ rescue Exception => error
41
+ failure = error
42
+ ensure
43
+ begin
44
+ control.close
45
+ rescue Exception => error
46
+ details = ["Async control close failed (#{error.class})"]
47
+ details.concat(error.cleanup_errors) if error.is_a?(Error)
48
+ Async.__send__(:attach_cleanup, failure, details) if failure
49
+ failure ||= error
50
+ end
51
+ end
52
+ raise failure if failure
53
+
54
+ result
55
+ end
56
+
57
+ def attach(**)
58
+ raise UnsupportedFeatureError.new("interactive terminal attachment requires the blocking core facade", phase: :admission)
59
+ end
60
+
61
+ def self.start(**)
62
+ raise UnsupportedFeatureError.new("create an owned core server before opening its Async scope", phase: :admission)
63
+ end
64
+
65
+ private
66
+
67
+ def ensure_owner
68
+ @scope.__send__(:ensure_owner)
69
+ end
70
+
71
+ def ensure_open
72
+ @scope.__send__(:ensure_open)
73
+ @source.__send__(:with_bound_endpoint) { nil }
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LibTmux
4
+ module Async
5
+ VERSION = "0.1.0.alpha.1"
6
+ end
7
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "libtmux"
4
+ require "async"
5
+ require "libtmux/async/version"
6
+ require "libtmux/async/server"
7
+ require "libtmux/async/scope"
8
+ require "libtmux/async/control"
9
+
10
+ module LibTmux
11
+ module Async
12
+ module CleanupDetails
13
+ attr_reader :async_cleanup_errors
14
+ end
15
+ private_constant :CleanupDetails
16
+
17
+ def self.attach_cleanup(error, details)
18
+ return if details.empty?
19
+
20
+ if error.is_a?(Error)
21
+ error.__send__(:attach_cleanup_errors, details)
22
+ else
23
+ error.extend(CleanupDetails)
24
+ error.instance_variable_set(:@async_cleanup_errors, ((error.async_cleanup_errors || []) + details).freeze)
25
+ end
26
+ rescue FrozenError, TypeError
27
+ nil
28
+ end
29
+ private_class_method :attach_cleanup
30
+
31
+ def self.open(server:, parent: ::Async::Task.current, **options)
32
+ raise ArgumentError, "Async scope requires a block" unless block_given?
33
+
34
+ scope = Scope.new(parent: parent, server: server, **options)
35
+ failure = result = nil
36
+ begin
37
+ result = yield scope
38
+ rescue Exception => error
39
+ failure = error
40
+ ensure
41
+ begin
42
+ scope.close
43
+ rescue Exception => error
44
+ details = ["Async scope close failed (#{error.class})"]
45
+ details.concat(error.cleanup_errors) if error.is_a?(Error)
46
+ attach_cleanup(failure, details) if failure
47
+ failure ||= error
48
+ end
49
+ end
50
+ raise failure if failure
51
+
52
+ result
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,58 @@
1
+ module LibTmux
2
+ module Async
3
+ VERSION: String
4
+
5
+ def self.open: [T] (server: LibTmux::Server, ?parent: untyped, **untyped) { (Scope) -> T } -> T
6
+
7
+ type scope_diagnostics = {
8
+ transport: :async_process, closed: bool, admitted_requests: Integer,
9
+ reserved_process_slots: Integer,
10
+ waiting_requests: Integer, active_process_slots: Integer,
11
+ reserved_request_bytes: Integer, retained_output_bytes: Integer,
12
+ control_connections: Integer, maps: Integer,
13
+ limits: {concurrency: Integer, max_requests: Integer, max_controls: Integer,
14
+ max_queue_bytes: Integer, max_output_bytes: Integer,
15
+ stdout_limit: Integer, stderr_limit: Integer, input_limit: Integer,
16
+ argv_limit: Integer, cleanup_timeout: Numeric, drain_timeout: Numeric,
17
+ close_timeout: Numeric}
18
+ }
19
+
20
+ class Scope
21
+ def initialize: (parent: untyped, server: LibTmux::Server, ?concurrency: Integer, ?max_requests: Integer,
22
+ ?max_controls: Integer, ?max_queue_bytes: Integer, ?max_output_bytes: Integer,
23
+ ?stdout_limit: Integer, ?stderr_limit: Integer, ?input_limit: Integer, ?argv_limit: Integer,
24
+ ?cleanup_timeout: Numeric, ?drain_timeout: Numeric) -> void
25
+ attr_reader server: Server
26
+ def map: [Input, Output] (Enumerable[Input], ?concurrency: Integer, ?max_items: Integer,
27
+ ?max_bytes: Integer, ?result_bytes: ^(Output) -> Integer) { (Input) -> Output } -> Array[Output]
28
+ def close: () -> nil
29
+ def closed?: () -> bool
30
+ def diagnostics: () -> scope_diagnostics
31
+ end
32
+
33
+ class Server < LibTmux::Server
34
+ def initialize: (Scope, LibTmux::Server) -> void
35
+ def run: (Array[String], ?input: String, ?timeout: Numeric, ?cancel: untyped) -> CommandResult
36
+ def close: () -> nil
37
+ def diagnostics: () -> scope_diagnostics
38
+ def open_control: [T] (session: EntityRef, ?reconnect: LibTmux::ControlConnection?, **Integer) { (ControlConnection) -> T } -> T
39
+ | (session: EntityRef, ?reconnect: LibTmux::ControlConnection?, **Integer) -> ControlConnection
40
+ def attach: (**untyped) -> bot
41
+ def self.start: (**untyped) -> bot
42
+ end
43
+
44
+ class ControlConnection < LibTmux::ControlConnection
45
+ def initialize: (scope: Scope, binding: untyped, session_id: String, ?reconnect: LibTmux::ControlConnection?, **Integer) -> void
46
+ attr_reader events: ControlSubscription
47
+ def exchange: (String, ?timeout: Numeric, ?cancel: untyped) -> GuardedReply
48
+ def subscribe: (?pane_id: String?, ?mode: :reliable | :tail, ?max_bytes: Integer, ?max_events: Integer) -> ControlSubscription
49
+ def close: (?timeout: Numeric) -> nil
50
+ def closed?: () -> bool
51
+ end
52
+
53
+ class ControlSubscription < LibTmux::ControlSubscription
54
+ def initialize: (scope: Scope, **untyped) -> void
55
+ def next: (?timeout: Numeric?) -> ControlEvent
56
+ end
57
+ end
58
+ end
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: libtmux-async
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.alpha.1
5
+ platform: ruby
6
+ authors:
7
+ - libtmux contributors
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: libtmux
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - '='
17
+ - !ruby/object:Gem::Version
18
+ version: 0.1.0.alpha.1
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - '='
24
+ - !ruby/object:Gem::Version
25
+ version: 0.1.0.alpha.1
26
+ - !ruby/object:Gem::Dependency
27
+ name: async
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: 2.46.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 2.46.0
40
+ description: Run concurrent libtmux commands and bounded control subscriptions inside
41
+ application-owned Async tasks.
42
+ executables: []
43
+ extensions: []
44
+ extra_rdoc_files: []
45
+ files:
46
+ - LICENSE
47
+ - README.md
48
+ - lib/libtmux/async.rb
49
+ - lib/libtmux/async/control.rb
50
+ - lib/libtmux/async/process.rb
51
+ - lib/libtmux/async/scope.rb
52
+ - lib/libtmux/async/server.rb
53
+ - lib/libtmux/async/version.rb
54
+ - sig/libtmux-async.rbs
55
+ homepage: https://github.com/libtmux/libtmux-ruby
56
+ licenses:
57
+ - MIT
58
+ metadata:
59
+ source_code_uri: https://github.com/libtmux/libtmux-ruby
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '3.3'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubygems_version: 4.0.20
75
+ specification_version: 4
76
+ summary: Optional Async integration for libtmux
77
+ test_files: []