phlex-stimulus 0.1.0

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.
Files changed (147) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +16 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +341 -0
  6. data/Rakefile +12 -0
  7. data/lib/generators/phlex/stimulus/controller/USAGE +5 -0
  8. data/lib/generators/phlex/stimulus/controller/controller_generator.rb +49 -0
  9. data/lib/generators/phlex/stimulus/controller/templates/component.rb.erb +30 -0
  10. data/lib/generators/phlex/stimulus/controller/templates/controller.ts.erb +23 -0
  11. data/lib/generators/phlex/stimulus/generator_mixin.rb +21 -0
  12. data/lib/generators/phlex/stimulus/install/USAGE +5 -0
  13. data/lib/generators/phlex/stimulus/install/install_generator.rb +111 -0
  14. data/lib/generators/phlex/stimulus/install/templates/app/components/base.rb.erb +29 -0
  15. data/lib/generators/phlex/stimulus/install/templates/app/components/chain_controller.rb.erb +29 -0
  16. data/lib/generators/phlex/stimulus/install/templates/app/components/classlist_controller.rb.erb +30 -0
  17. data/lib/generators/phlex/stimulus/install/templates/app/components/controller.rb.erb +10 -0
  18. data/lib/generators/phlex/stimulus/install/templates/app/components/controller_chain.rb.erb +32 -0
  19. data/lib/generators/phlex/stimulus/install/templates/app/components/controller_template.rb.erb +24 -0
  20. data/lib/generators/phlex/stimulus/install/templates/app/components/log_controller.rb.erb +33 -0
  21. data/lib/generators/phlex/stimulus/install/templates/app/components/sleep_controller.rb.erb +30 -0
  22. data/lib/generators/phlex/stimulus/install/templates/app/components.rb.erb +7 -0
  23. data/lib/generators/phlex/stimulus/install/templates/app/javascript/application.ts.erb +5 -0
  24. data/lib/generators/phlex/stimulus/install/templates/app/javascript/controllers/application.ts.erb +10 -0
  25. data/lib/generators/phlex/stimulus/install/templates/app/javascript/controllers/chain_controller.ts.erb +32 -0
  26. data/lib/generators/phlex/stimulus/install/templates/app/javascript/controllers/chainable_controller.ts.erb +44 -0
  27. data/lib/generators/phlex/stimulus/install/templates/app/javascript/controllers/classlist_controller.ts.erb +30 -0
  28. data/lib/generators/phlex/stimulus/install/templates/app/javascript/controllers/index.ts.erb +4 -0
  29. data/lib/generators/phlex/stimulus/install/templates/app/javascript/controllers/log_controller.ts.erb +25 -0
  30. data/lib/generators/phlex/stimulus/install/templates/app/javascript/controllers/sleep_controller.ts.erb +19 -0
  31. data/lib/generators/phlex/stimulus/install/templates/app/javascript/controllers/typed_controller.ts.erb +53 -0
  32. data/lib/generators/phlex/stimulus/install/templates/app/javascript/utils/misc.ts.erb +37 -0
  33. data/lib/generators/phlex/stimulus/install/templates/app/javascript/utils/template.ts.erb +11 -0
  34. data/lib/phlex/stimulus/components/base.rb +81 -0
  35. data/lib/phlex/stimulus/components/controller.rb +170 -0
  36. data/lib/phlex/stimulus/components.rb +9 -0
  37. data/lib/phlex/stimulus/version.rb +8 -0
  38. data/lib/phlex/stimulus.rb +15 -0
  39. data/sorbet/config +7 -0
  40. data/sorbet/rbi/annotations/.gitattributes +1 -0
  41. data/sorbet/rbi/annotations/actionmailer.rbi +15 -0
  42. data/sorbet/rbi/annotations/actionpack.rbi +430 -0
  43. data/sorbet/rbi/annotations/actionview.rbi +75 -0
  44. data/sorbet/rbi/annotations/activejob.rbi +50 -0
  45. data/sorbet/rbi/annotations/activemodel.rbi +119 -0
  46. data/sorbet/rbi/annotations/activerecord.rbi +172 -0
  47. data/sorbet/rbi/annotations/activesupport.rbi +561 -0
  48. data/sorbet/rbi/annotations/globalid.rbi +30 -0
  49. data/sorbet/rbi/annotations/minitest.rbi +116 -0
  50. data/sorbet/rbi/annotations/railties.rbi +104 -0
  51. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  52. data/sorbet/rbi/dsl/.gitattributes +1 -0
  53. data/sorbet/rbi/dsl/active_support/callbacks.rbi +21 -0
  54. data/sorbet/rbi/gems/.gitattributes +1 -0
  55. data/sorbet/rbi/gems/action_text-trix@2.1.19.rbi +9 -0
  56. data/sorbet/rbi/gems/actioncable@8.1.3.rbi +9 -0
  57. data/sorbet/rbi/gems/actionmailbox@8.1.3.rbi +9 -0
  58. data/sorbet/rbi/gems/actionmailer@8.1.3.rbi +9 -0
  59. data/sorbet/rbi/gems/actionpack@8.1.3.rbi +20478 -0
  60. data/sorbet/rbi/gems/actiontext@8.1.3.rbi +9 -0
  61. data/sorbet/rbi/gems/actionview@8.1.3.rbi +14722 -0
  62. data/sorbet/rbi/gems/activejob@8.1.3.rbi +9 -0
  63. data/sorbet/rbi/gems/activemodel@8.1.3.rbi +9 -0
  64. data/sorbet/rbi/gems/activerecord@8.1.3.rbi +9 -0
  65. data/sorbet/rbi/gems/activestorage@8.1.3.rbi +9 -0
  66. data/sorbet/rbi/gems/activesupport@8.1.3.rbi +20153 -0
  67. data/sorbet/rbi/gems/ast@2.4.3.rbi +550 -0
  68. data/sorbet/rbi/gems/base64@0.3.0.rbi +545 -0
  69. data/sorbet/rbi/gems/benchmark@0.5.0.rbi +621 -0
  70. data/sorbet/rbi/gems/booleans@0.1.3.rbi +31 -0
  71. data/sorbet/rbi/gems/builder@3.3.0.rbi +9 -0
  72. data/sorbet/rbi/gems/byebug@12.0.0.rbi +49 -0
  73. data/sorbet/rbi/gems/concurrent-ruby@1.3.8.rbi +10656 -0
  74. data/sorbet/rbi/gems/connection_pool@3.0.2.rbi +9 -0
  75. data/sorbet/rbi/gems/crass@1.0.7.rbi +648 -0
  76. data/sorbet/rbi/gems/date@3.5.1.rbi +391 -0
  77. data/sorbet/rbi/gems/drb@2.2.3.rbi +9 -0
  78. data/sorbet/rbi/gems/erb@6.0.6.rbi +1600 -0
  79. data/sorbet/rbi/gems/erubi@1.13.1.rbi +155 -0
  80. data/sorbet/rbi/gems/globalid@1.4.0.rbi +9 -0
  81. data/sorbet/rbi/gems/i18n@1.15.2.rbi +2285 -0
  82. data/sorbet/rbi/gems/io-console@0.8.2.rbi +9 -0
  83. data/sorbet/rbi/gems/json@2.21.1.rbi +2289 -0
  84. data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +189 -0
  85. data/sorbet/rbi/gems/logger@1.7.0.rbi +896 -0
  86. data/sorbet/rbi/gems/loofah@2.25.2.rbi +1134 -0
  87. data/sorbet/rbi/gems/mail@2.9.1.rbi +9 -0
  88. data/sorbet/rbi/gems/marcel@1.2.1.rbi +9 -0
  89. data/sorbet/rbi/gems/mini_mime@1.1.5.rbi +9 -0
  90. data/sorbet/rbi/gems/minitest@6.0.6.rbi +1482 -0
  91. data/sorbet/rbi/gems/net-imap@0.6.4.1.rbi +9 -0
  92. data/sorbet/rbi/gems/net-pop@0.1.2.rbi +9 -0
  93. data/sorbet/rbi/gems/net-protocol@0.2.2.rbi +244 -0
  94. data/sorbet/rbi/gems/net-smtp@0.5.1.rbi +9 -0
  95. data/sorbet/rbi/gems/netrc@0.11.0.rbi +147 -0
  96. data/sorbet/rbi/gems/nio4r@2.7.5.rbi +9 -0
  97. data/sorbet/rbi/gems/nokogiri@1.19.4.rbi +8168 -0
  98. data/sorbet/rbi/gems/parallel@1.28.0.rbi +270 -0
  99. data/sorbet/rbi/gems/phlex-rails@2.4.0.rbi +1945 -0
  100. data/sorbet/rbi/gems/phlex@2.4.1.rbi +1413 -0
  101. data/sorbet/rbi/gems/pp@0.6.4.rbi +387 -0
  102. data/sorbet/rbi/gems/prettyprint@0.2.0.rbi +455 -0
  103. data/sorbet/rbi/gems/prism@1.9.0.rbi +42226 -0
  104. data/sorbet/rbi/gems/racc@1.8.1.rbi +165 -0
  105. data/sorbet/rbi/gems/rack-session@2.1.2.rbi +756 -0
  106. data/sorbet/rbi/gems/rack-test@2.2.0.rbi +681 -0
  107. data/sorbet/rbi/gems/rack@3.2.6.rbi +4653 -0
  108. data/sorbet/rbi/gems/rackup@2.3.1.rbi +9 -0
  109. data/sorbet/rbi/gems/rails-dom-testing@2.3.0.rbi +517 -0
  110. data/sorbet/rbi/gems/rails-html-sanitizer@1.7.1.rbi +620 -0
  111. data/sorbet/rbi/gems/rails@8.1.3.rbi +9 -0
  112. data/sorbet/rbi/gems/railties@8.1.3.rbi +3507 -0
  113. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +362 -0
  114. data/sorbet/rbi/gems/rake@13.4.2.rbi +3130 -0
  115. data/sorbet/rbi/gems/rbi@0.4.0.rbi +5706 -0
  116. data/sorbet/rbi/gems/rbs@4.0.3.rbi +6908 -0
  117. data/sorbet/rbi/gems/refract@1.1.0.rbi +9 -0
  118. data/sorbet/rbi/gems/reline@0.6.3.rbi +2446 -0
  119. data/sorbet/rbi/gems/require-hooks@0.4.0.rbi +152 -0
  120. data/sorbet/rbi/gems/rexml@3.4.4.rbi +4905 -0
  121. data/sorbet/rbi/gems/rubocop-espago@1.3.0.rbi +9 -0
  122. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +988 -0
  123. data/sorbet/rbi/gems/rubydex@0.2.9.rbi +841 -0
  124. data/sorbet/rbi/gems/securerandom@0.4.1.rbi +75 -0
  125. data/sorbet/rbi/gems/shoulda-context@2.0.0.rbi +544 -0
  126. data/sorbet/rbi/gems/spoom@1.8.4.rbi +6738 -0
  127. data/sorbet/rbi/gems/tapioca@0.19.2.rbi +3599 -0
  128. data/sorbet/rbi/gems/thor@1.5.0.rbi +3870 -0
  129. data/sorbet/rbi/gems/timeout@0.6.1.rbi +200 -0
  130. data/sorbet/rbi/gems/tsort@0.2.0.rbi +389 -0
  131. data/sorbet/rbi/gems/tzinfo@2.0.6.rbi +5474 -0
  132. data/sorbet/rbi/gems/unicode-display_width@3.2.0.rbi +130 -0
  133. data/sorbet/rbi/gems/unicode-emoji@4.2.0.rbi +332 -0
  134. data/sorbet/rbi/gems/uri@1.1.1.rbi +2402 -0
  135. data/sorbet/rbi/gems/useragent@0.16.11.rbi +9 -0
  136. data/sorbet/rbi/gems/websocket-driver@0.8.2.rbi +9 -0
  137. data/sorbet/rbi/gems/websocket-extensions@0.1.5.rbi +9 -0
  138. data/sorbet/rbi/gems/zeitwerk@2.8.2.rbi +9 -0
  139. data/sorbet/rbi/shims/gems/parser.rbi +12 -0
  140. data/sorbet/rbi/shims/gems/rails.rbi +55 -0
  141. data/sorbet/rbi/shims/gems/refract.rbi +13 -0
  142. data/sorbet/rbi/shims/gems/shoulda-context.rbi +16 -0
  143. data/sorbet/tapioca/compilers/phlex_controller.rb +80 -0
  144. data/sorbet/tapioca/config.yml +26 -0
  145. data/sorbet/tapioca/extensions/load_gem.rb +1 -0
  146. data/sorbet/tapioca/require.rb +4 -0
  147. metadata +266 -0
@@ -0,0 +1,200 @@
1
+ # typed: true
2
+
3
+ # DO NOT EDIT MANUALLY
4
+ # This is an autogenerated file for types exported from the `timeout` gem.
5
+ # Please instead update this file by running `bin/tapioca gem timeout`.
6
+
7
+
8
+ # Timeout long-running blocks
9
+ #
10
+ # == Synopsis
11
+ #
12
+ # require 'timeout'
13
+ # status = Timeout.timeout(5) {
14
+ # # Something that should be interrupted if it takes more than 5 seconds...
15
+ # }
16
+ #
17
+ # == Description
18
+ #
19
+ # Timeout provides a way to auto-terminate a potentially long-running
20
+ # operation if it hasn't finished in a fixed amount of time.
21
+ #
22
+ # == Copyright
23
+ #
24
+ # Copyright:: (C) 2000 Network Applied Communication Laboratory, Inc.
25
+ # Copyright:: (C) 2000 Information-technology Promotion Agency, Japan
26
+ #
27
+ # pkg:gem/timeout#lib/timeout.rb:21
28
+ module Timeout
29
+ private
30
+
31
+ # See Timeout.timeout
32
+ #
33
+ # pkg:gem/timeout#lib/timeout.rb:311
34
+ def timeout(*args, &block); end
35
+
36
+ class << self
37
+ # Perform an operation in a block, raising an exception if it takes longer than
38
+ # +sec+ seconds to complete.
39
+ #
40
+ # +sec+:: Number of seconds to wait for the block to terminate. Any non-negative number
41
+ # or nil may be used, including Floats to specify fractional seconds. A
42
+ # value of 0 or +nil+ will execute the block without any timeout.
43
+ # Any negative number will raise an ArgumentError.
44
+ # +klass+:: Exception Class to raise if the block fails to terminate
45
+ # in +sec+ seconds. Omitting will use the default, Timeout::Error.
46
+ # +message+:: Error message to raise with Exception Class.
47
+ # Omitting will use the default, <tt>"execution expired"</tt>.
48
+ #
49
+ # Returns the result of the block *if* the block completed before
50
+ # +sec+ seconds, otherwise raises an exception, based on the value of +klass+.
51
+ #
52
+ # The exception raised to terminate the given block is the given +klass+, or
53
+ # Timeout::ExitException if +klass+ is not given. The reason for that behavior
54
+ # is that Timeout::Error inherits from RuntimeError and might be caught unexpectedly by +rescue+.
55
+ # Timeout::ExitException inherits from Exception so it will only be rescued by <tt>rescue Exception</tt>.
56
+ # Note that the Timeout::ExitException is translated to a Timeout::Error once it reaches the Timeout.timeout call,
57
+ # so outside that call it will be a Timeout::Error.
58
+ #
59
+ # In general, be aware that the code block may rescue the exception, and in such a case not respect the timeout.
60
+ # Also, the block can use +ensure+ to prevent the handling of the exception.
61
+ # For those reasons, this method cannot be relied on to enforce timeouts for untrusted blocks.
62
+ #
63
+ # If a scheduler is defined, it will be used to handle the timeout by invoking
64
+ # Fiber::Scheduler#timeout_after.
65
+ #
66
+ # Note that this is both a method of module Timeout, so you can <tt>include
67
+ # Timeout</tt> into your classes so they have a #timeout method, as well as
68
+ # a module method, so you can call it directly as Timeout.timeout().
69
+ #
70
+ # ==== Ensuring the exception does not fire inside ensure blocks
71
+ #
72
+ # When using Timeout.timeout, it can be desirable to ensure the timeout exception does not fire inside an +ensure+ block.
73
+ # The simplest and best way to do so is to put the Timeout.timeout call inside the body of the +begin+/+ensure+/+end+:
74
+ #
75
+ # begin
76
+ # Timeout.timeout(sec) { some_long_operation }
77
+ # ensure
78
+ # cleanup # safe, cannot be interrupted by timeout
79
+ # end
80
+ #
81
+ # If that is not feasible, e.g. if there are +ensure+ blocks inside +some_long_operation+,
82
+ # they need to not be interrupted by timeout, and it's not possible to move these ensure blocks outside,
83
+ # one can use Thread.handle_interrupt to delay the timeout exception like so:
84
+ #
85
+ # Thread.handle_interrupt(Timeout::Error => :never) {
86
+ # Timeout.timeout(sec, Timeout::Error) do
87
+ # setup # timeout cannot happen here, no matter how long it takes
88
+ # Thread.handle_interrupt(Timeout::Error => :immediate) {
89
+ # some_long_operation # timeout can happen here
90
+ # }
91
+ # ensure
92
+ # cleanup # timeout cannot happen here, no matter how long it takes
93
+ # end
94
+ # }
95
+ #
96
+ # An important thing to note is the need to pass an exception +klass+ to Timeout.timeout,
97
+ # otherwise it does not work. Specifically, using <tt>Thread.handle_interrupt(Timeout::ExitException => ...)</tt>
98
+ # is unsupported and causes subtle errors like raising the wrong exception outside the block, do not use that.
99
+ #
100
+ # Note that Thread.handle_interrupt is somewhat dangerous because if setup or cleanup hangs
101
+ # then the current thread will hang too and the timeout will never fire.
102
+ # Also note the block might run for longer than +sec+ seconds:
103
+ # e.g. +some_long_operation+ executes for +sec+ seconds + whatever time cleanup takes.
104
+ #
105
+ # If you want the timeout to only happen on blocking operations, one can use +:on_blocking+
106
+ # instead of +:immediate+. However, that means if the block uses no blocking operations after +sec+ seconds,
107
+ # the block will not be interrupted.
108
+ #
109
+ # pkg:gem/timeout#lib/timeout.rb:278
110
+ def timeout(sec, klass = T.unsafe(nil), message = T.unsafe(nil), &block); end
111
+ end
112
+ end
113
+
114
+ # Raised by Timeout.timeout when the block times out.
115
+ #
116
+ # pkg:gem/timeout#lib/timeout.rb:33
117
+ class Timeout::Error < ::RuntimeError
118
+ class << self
119
+ # pkg:gem/timeout#lib/timeout.rb:34
120
+ def handle_timeout(message); end
121
+ end
122
+ end
123
+
124
+ # Internal exception raised to when a timeout is triggered.
125
+ #
126
+ # pkg:gem/timeout#lib/timeout.rb:26
127
+ class Timeout::ExitException < ::Exception
128
+ # pkg:gem/timeout#lib/timeout.rb:27
129
+ def exception(*_arg0); end
130
+ end
131
+
132
+ # We keep a private reference so that time mocking libraries won't break Timeout.
133
+ #
134
+ # pkg:gem/timeout#lib/timeout.rb:49
135
+ Timeout::GET_TIME = T.let(T.unsafe(nil), Method)
136
+
137
+ # pkg:gem/timeout#lib/timeout.rb:143
138
+ class Timeout::Request
139
+ # pkg:gem/timeout#lib/timeout.rb:146
140
+ def initialize(thread, timeout, exception_class, message); end
141
+
142
+ # pkg:gem/timeout#lib/timeout.rb:144
143
+ def deadline; end
144
+
145
+ # Only called by the timeout thread, so does not need Sync.synchronize
146
+ #
147
+ # pkg:gem/timeout#lib/timeout.rb:157
148
+ def done?; end
149
+
150
+ # pkg:gem/timeout#lib/timeout.rb:163
151
+ def expired?(now); end
152
+
153
+ # pkg:gem/timeout#lib/timeout.rb:177
154
+ def finished; end
155
+
156
+ # Only called by the timeout thread, so does not need Sync.synchronize
157
+ #
158
+ # pkg:gem/timeout#lib/timeout.rb:168
159
+ def interrupt; end
160
+ end
161
+
162
+ # pkg:gem/timeout#lib/timeout.rb:56
163
+ class Timeout::State
164
+ # pkg:gem/timeout#lib/timeout.rb:57
165
+ def initialize; end
166
+
167
+ # pkg:gem/timeout#lib/timeout.rb:134
168
+ def add_request(request); end
169
+
170
+ # pkg:gem/timeout#lib/timeout.rb:83
171
+ def create_timeout_thread; end
172
+
173
+ # pkg:gem/timeout#lib/timeout.rb:120
174
+ def ensure_timeout_thread_created; end
175
+
176
+ class << self
177
+ # Ractor support if
178
+ # 1. Ractor.store_if_absent is available
179
+ # 2. Method object can be shareable (4.0~)
180
+ #
181
+ # pkg:gem/timeout#lib/timeout.rb:70
182
+ def instance; end
183
+ end
184
+ end
185
+
186
+ # pkg:gem/timeout#lib/timeout.rb:185
187
+ module Timeout::Sync
188
+ class << self
189
+ # Calls mutex.synchronize(&block) but if that fails on CRuby due to being in a trap handler,
190
+ # run mutex.synchronize(&block) in a separate Thread instead.
191
+ #
192
+ # pkg:gem/timeout#lib/timeout.rb:188
193
+ def synchronize(mutex, &block); end
194
+ end
195
+ end
196
+
197
+ # The version
198
+ #
199
+ # pkg:gem/timeout#lib/timeout.rb:23
200
+ Timeout::VERSION = T.let(T.unsafe(nil), String)
@@ -0,0 +1,389 @@
1
+ # typed: true
2
+
3
+ # DO NOT EDIT MANUALLY
4
+ # This is an autogenerated file for types exported from the `tsort` gem.
5
+ # Please instead update this file by running `bin/tapioca gem tsort`.
6
+
7
+
8
+ # TSort implements topological sorting using Tarjan's algorithm for
9
+ # strongly connected components.
10
+ #
11
+ # TSort is designed to be able to be used with any object which can be
12
+ # interpreted as a directed graph.
13
+ #
14
+ # TSort requires two methods to interpret an object as a graph,
15
+ # tsort_each_node and tsort_each_child.
16
+ #
17
+ # * tsort_each_node is used to iterate for all nodes over a graph.
18
+ # * tsort_each_child is used to iterate for child nodes of a given node.
19
+ #
20
+ # The equality of nodes are defined by eql? and hash since
21
+ # TSort uses Hash internally.
22
+ #
23
+ # == A Simple Example
24
+ #
25
+ # The following example demonstrates how to mix the TSort module into an
26
+ # existing class (in this case, Hash). Here, we're treating each key in
27
+ # the hash as a node in the graph, and so we simply alias the required
28
+ # #tsort_each_node method to Hash's #each_key method. For each key in the
29
+ # hash, the associated value is an array of the node's child nodes. This
30
+ # choice in turn leads to our implementation of the required #tsort_each_child
31
+ # method, which fetches the array of child nodes and then iterates over that
32
+ # array using the user-supplied block.
33
+ #
34
+ # require 'tsort'
35
+ #
36
+ # class Hash
37
+ # include TSort
38
+ # alias tsort_each_node each_key
39
+ # def tsort_each_child(node, &block)
40
+ # fetch(node).each(&block)
41
+ # end
42
+ # end
43
+ #
44
+ # {1=>[2, 3], 2=>[3], 3=>[], 4=>[]}.tsort
45
+ # #=> [3, 2, 1, 4]
46
+ #
47
+ # {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}.strongly_connected_components
48
+ # #=> [[4], [2, 3], [1]]
49
+ #
50
+ # == A More Realistic Example
51
+ #
52
+ # A very simple `make' like tool can be implemented as follows:
53
+ #
54
+ # require 'tsort'
55
+ #
56
+ # class Make
57
+ # def initialize
58
+ # @dep = {}
59
+ # @dep.default = []
60
+ # end
61
+ #
62
+ # def rule(outputs, inputs=[], &block)
63
+ # triple = [outputs, inputs, block]
64
+ # outputs.each {|f| @dep[f] = [triple]}
65
+ # @dep[triple] = inputs
66
+ # end
67
+ #
68
+ # def build(target)
69
+ # each_strongly_connected_component_from(target) {|ns|
70
+ # if ns.length != 1
71
+ # fs = ns.delete_if {|n| Array === n}
72
+ # raise TSort::Cyclic.new("cyclic dependencies: #{fs.join ', '}")
73
+ # end
74
+ # n = ns.first
75
+ # if Array === n
76
+ # outputs, inputs, block = n
77
+ # inputs_time = inputs.map {|f| File.mtime f}.max
78
+ # begin
79
+ # outputs_time = outputs.map {|f| File.mtime f}.min
80
+ # rescue Errno::ENOENT
81
+ # outputs_time = nil
82
+ # end
83
+ # if outputs_time == nil ||
84
+ # inputs_time != nil && outputs_time <= inputs_time
85
+ # sleep 1 if inputs_time != nil && inputs_time.to_i == Time.now.to_i
86
+ # block.call
87
+ # end
88
+ # end
89
+ # }
90
+ # end
91
+ #
92
+ # def tsort_each_child(node, &block)
93
+ # @dep[node].each(&block)
94
+ # end
95
+ # include TSort
96
+ # end
97
+ #
98
+ # def command(arg)
99
+ # print arg, "\n"
100
+ # system arg
101
+ # end
102
+ #
103
+ # m = Make.new
104
+ # m.rule(%w[t1]) { command 'date > t1' }
105
+ # m.rule(%w[t2]) { command 'date > t2' }
106
+ # m.rule(%w[t3]) { command 'date > t3' }
107
+ # m.rule(%w[t4], %w[t1 t3]) { command 'cat t1 t3 > t4' }
108
+ # m.rule(%w[t5], %w[t4 t2]) { command 'cat t4 t2 > t5' }
109
+ # m.build('t5')
110
+ #
111
+ # == Bugs
112
+ #
113
+ # * 'tsort.rb' is wrong name because this library uses
114
+ # Tarjan's algorithm for strongly connected components.
115
+ # Although 'strongly_connected_components.rb' is correct but too long.
116
+ #
117
+ # == References
118
+ #
119
+ # R. E. Tarjan, "Depth First Search and Linear Graph Algorithms",
120
+ # <em>SIAM Journal on Computing</em>, Vol. 1, No. 2, pp. 146-160, June 1972.
121
+ #
122
+ # pkg:gem/tsort#lib/tsort.rb:124
123
+ module TSort
124
+ # The iterator version of the #strongly_connected_components method.
125
+ # <tt><em>obj</em>.each_strongly_connected_component</tt> is similar to
126
+ # <tt><em>obj</em>.strongly_connected_components.each</tt>, but
127
+ # modification of _obj_ during the iteration may lead to unexpected results.
128
+ #
129
+ # #each_strongly_connected_component returns +nil+.
130
+ #
131
+ # class G
132
+ # include TSort
133
+ # def initialize(g)
134
+ # @g = g
135
+ # end
136
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
137
+ # def tsort_each_node(&b) @g.each_key(&b) end
138
+ # end
139
+ #
140
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
141
+ # graph.each_strongly_connected_component {|scc| p scc }
142
+ # #=> [4]
143
+ # # [2]
144
+ # # [3]
145
+ # # [1]
146
+ #
147
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
148
+ # graph.each_strongly_connected_component {|scc| p scc }
149
+ # #=> [4]
150
+ # # [2, 3]
151
+ # # [1]
152
+ #
153
+ # pkg:gem/tsort#lib/tsort.rb:316
154
+ def each_strongly_connected_component(&block); end
155
+
156
+ # Iterates over strongly connected component in the subgraph reachable from
157
+ # _node_.
158
+ #
159
+ # Return value is unspecified.
160
+ #
161
+ # #each_strongly_connected_component_from doesn't call #tsort_each_node.
162
+ #
163
+ # class G
164
+ # include TSort
165
+ # def initialize(g)
166
+ # @g = g
167
+ # end
168
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
169
+ # def tsort_each_node(&b) @g.each_key(&b) end
170
+ # end
171
+ #
172
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
173
+ # graph.each_strongly_connected_component_from(2) {|scc| p scc }
174
+ # #=> [4]
175
+ # # [2]
176
+ #
177
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
178
+ # graph.each_strongly_connected_component_from(2) {|scc| p scc }
179
+ # #=> [4]
180
+ # # [2, 3]
181
+ #
182
+ # pkg:gem/tsort#lib/tsort.rb:386
183
+ def each_strongly_connected_component_from(node, id_map = T.unsafe(nil), stack = T.unsafe(nil), &block); end
184
+
185
+ # Returns strongly connected components as an array of arrays of nodes.
186
+ # The array is sorted from children to parents.
187
+ # Each elements of the array represents a strongly connected component.
188
+ #
189
+ # class G
190
+ # include TSort
191
+ # def initialize(g)
192
+ # @g = g
193
+ # end
194
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
195
+ # def tsort_each_node(&b) @g.each_key(&b) end
196
+ # end
197
+ #
198
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
199
+ # p graph.strongly_connected_components #=> [[4], [2], [3], [1]]
200
+ #
201
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
202
+ # p graph.strongly_connected_components #=> [[4], [2, 3], [1]]
203
+ #
204
+ # pkg:gem/tsort#lib/tsort.rb:257
205
+ def strongly_connected_components; end
206
+
207
+ # Returns a topologically sorted array of nodes.
208
+ # The array is sorted from children to parents, i.e.
209
+ # the first element has no child and the last node has no parent.
210
+ #
211
+ # If there is a cycle, TSort::Cyclic is raised.
212
+ #
213
+ # class G
214
+ # include TSort
215
+ # def initialize(g)
216
+ # @g = g
217
+ # end
218
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
219
+ # def tsort_each_node(&b) @g.each_key(&b) end
220
+ # end
221
+ #
222
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
223
+ # p graph.tsort #=> [4, 2, 3, 1]
224
+ #
225
+ # graph = G.new({1=>[2], 2=>[3, 4], 3=>[2], 4=>[]})
226
+ # p graph.tsort # raises TSort::Cyclic
227
+ #
228
+ # pkg:gem/tsort#lib/tsort.rb:152
229
+ def tsort; end
230
+
231
+ # The iterator version of the #tsort method.
232
+ # <tt><em>obj</em>.tsort_each</tt> is similar to <tt><em>obj</em>.tsort.each</tt>, but
233
+ # modification of _obj_ during the iteration may lead to unexpected results.
234
+ #
235
+ # #tsort_each returns +nil+.
236
+ # If there is a cycle, TSort::Cyclic is raised.
237
+ #
238
+ # class G
239
+ # include TSort
240
+ # def initialize(g)
241
+ # @g = g
242
+ # end
243
+ # def tsort_each_child(n, &b) @g[n].each(&b) end
244
+ # def tsort_each_node(&b) @g.each_key(&b) end
245
+ # end
246
+ #
247
+ # graph = G.new({1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]})
248
+ # graph.tsort_each {|n| p n }
249
+ # #=> 4
250
+ # # 2
251
+ # # 3
252
+ # # 1
253
+ #
254
+ # pkg:gem/tsort#lib/tsort.rb:205
255
+ def tsort_each(&block); end
256
+
257
+ # Should be implemented by a extended class.
258
+ #
259
+ # #tsort_each_child is used to iterate for child nodes of _node_.
260
+ #
261
+ # pkg:gem/tsort#lib/tsort.rb:452
262
+ def tsort_each_child(node); end
263
+
264
+ # Should be implemented by a extended class.
265
+ #
266
+ # #tsort_each_node is used to iterate for all nodes over a graph.
267
+ #
268
+ # pkg:gem/tsort#lib/tsort.rb:444
269
+ def tsort_each_node; end
270
+
271
+ class << self
272
+ # The iterator version of the TSort.strongly_connected_components method.
273
+ #
274
+ # The graph is represented by _each_node_ and _each_child_.
275
+ # _each_node_ should have +call+ method which yields for each node in the graph.
276
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
277
+ #
278
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
279
+ # each_node = lambda {|&b| g.each_key(&b) }
280
+ # each_child = lambda {|n, &b| g[n].each(&b) }
281
+ # TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
282
+ # #=> [4]
283
+ # # [2]
284
+ # # [3]
285
+ # # [1]
286
+ #
287
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
288
+ # each_node = lambda {|&b| g.each_key(&b) }
289
+ # each_child = lambda {|n, &b| g[n].each(&b) }
290
+ # TSort.each_strongly_connected_component(each_node, each_child) {|scc| p scc }
291
+ # #=> [4]
292
+ # # [2, 3]
293
+ # # [1]
294
+ #
295
+ # pkg:gem/tsort#lib/tsort.rb:345
296
+ def each_strongly_connected_component(each_node, each_child); end
297
+
298
+ # Iterates over strongly connected components in a graph.
299
+ # The graph is represented by _node_ and _each_child_.
300
+ #
301
+ # _node_ is the first node.
302
+ # _each_child_ should have +call+ method which takes a node argument
303
+ # and yields for each child node.
304
+ #
305
+ # Return value is unspecified.
306
+ #
307
+ # #TSort.each_strongly_connected_component_from is a class method and
308
+ # it doesn't need a class to represent a graph which includes TSort.
309
+ #
310
+ # graph = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
311
+ # each_child = lambda {|n, &b| graph[n].each(&b) }
312
+ # TSort.each_strongly_connected_component_from(1, each_child) {|scc|
313
+ # p scc
314
+ # }
315
+ # #=> [4]
316
+ # # [2, 3]
317
+ # # [1]
318
+ #
319
+ # pkg:gem/tsort#lib/tsort.rb:411
320
+ def each_strongly_connected_component_from(node, each_child, id_map = T.unsafe(nil), stack = T.unsafe(nil)); end
321
+
322
+ # Returns strongly connected components as an array of arrays of nodes.
323
+ # The array is sorted from children to parents.
324
+ # Each elements of the array represents a strongly connected component.
325
+ #
326
+ # The graph is represented by _each_node_ and _each_child_.
327
+ # _each_node_ should have +call+ method which yields for each node in the graph.
328
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
329
+ #
330
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
331
+ # each_node = lambda {|&b| g.each_key(&b) }
332
+ # each_child = lambda {|n, &b| g[n].each(&b) }
333
+ # p TSort.strongly_connected_components(each_node, each_child)
334
+ # #=> [[4], [2], [3], [1]]
335
+ #
336
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
337
+ # each_node = lambda {|&b| g.each_key(&b) }
338
+ # each_child = lambda {|n, &b| g[n].each(&b) }
339
+ # p TSort.strongly_connected_components(each_node, each_child)
340
+ # #=> [[4], [2, 3], [1]]
341
+ #
342
+ # pkg:gem/tsort#lib/tsort.rb:283
343
+ def strongly_connected_components(each_node, each_child); end
344
+
345
+ # Returns a topologically sorted array of nodes.
346
+ # The array is sorted from children to parents, i.e.
347
+ # the first element has no child and the last node has no parent.
348
+ #
349
+ # The graph is represented by _each_node_ and _each_child_.
350
+ # _each_node_ should have +call+ method which yields for each node in the graph.
351
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
352
+ #
353
+ # If there is a cycle, TSort::Cyclic is raised.
354
+ #
355
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
356
+ # each_node = lambda {|&b| g.each_key(&b) }
357
+ # each_child = lambda {|n, &b| g[n].each(&b) }
358
+ # p TSort.tsort(each_node, each_child) #=> [4, 2, 3, 1]
359
+ #
360
+ # g = {1=>[2], 2=>[3, 4], 3=>[2], 4=>[]}
361
+ # each_node = lambda {|&b| g.each_key(&b) }
362
+ # each_child = lambda {|n, &b| g[n].each(&b) }
363
+ # p TSort.tsort(each_node, each_child) # raises TSort::Cyclic
364
+ #
365
+ # pkg:gem/tsort#lib/tsort.rb:178
366
+ def tsort(each_node, each_child); end
367
+
368
+ # The iterator version of the TSort.tsort method.
369
+ #
370
+ # The graph is represented by _each_node_ and _each_child_.
371
+ # _each_node_ should have +call+ method which yields for each node in the graph.
372
+ # _each_child_ should have +call+ method which takes a node argument and yields for each child node.
373
+ #
374
+ # g = {1=>[2, 3], 2=>[4], 3=>[2, 4], 4=>[]}
375
+ # each_node = lambda {|&b| g.each_key(&b) }
376
+ # each_child = lambda {|n, &b| g[n].each(&b) }
377
+ # TSort.tsort_each(each_node, each_child) {|n| p n }
378
+ # #=> 4
379
+ # # 2
380
+ # # 3
381
+ # # 1
382
+ #
383
+ # pkg:gem/tsort#lib/tsort.rb:226
384
+ def tsort_each(each_node, each_child); end
385
+ end
386
+ end
387
+
388
+ # pkg:gem/tsort#lib/tsort.rb:126
389
+ TSort::VERSION = T.let(T.unsafe(nil), String)