lino 3.2.0.pre.4 → 3.2.0.pre.6

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +95 -60
  3. data/Rakefile +1 -3
  4. data/lib/lino/builders/command_line.rb +59 -0
  5. data/lib/lino/builders/mixins/appliables.rb +27 -0
  6. data/lib/lino/builders/mixins/arguments.rb +38 -0
  7. data/lib/lino/builders/mixins/defaulting.rb +19 -0
  8. data/lib/lino/builders/mixins/environment_variables.rb +46 -0
  9. data/lib/lino/builders/mixins/executor.rb +24 -0
  10. data/lib/lino/builders/mixins/option_config.rb +50 -0
  11. data/lib/lino/builders/mixins/options.rb +118 -0
  12. data/lib/lino/builders/mixins/state_boundary.rb +22 -0
  13. data/lib/lino/builders/mixins/subcommands.rb +52 -0
  14. data/lib/lino/builders/mixins/validation.rb +21 -0
  15. data/lib/lino/builders/mixins/working_directory.rb +24 -0
  16. data/lib/lino/builders/subcommand.rb +47 -0
  17. data/lib/lino/builders.rb +9 -0
  18. data/lib/lino/errors/execution_error.rb +18 -0
  19. data/lib/lino/errors.rb +8 -0
  20. data/lib/lino/executors/childprocess.rb +63 -0
  21. data/lib/lino/executors/open4.rb +42 -0
  22. data/lib/lino/executors.rb +9 -0
  23. data/lib/lino/model/argument.rb +41 -0
  24. data/lib/lino/model/command_line.rb +117 -0
  25. data/lib/lino/model/environment_variable.rb +63 -0
  26. data/lib/lino/model/flag.rb +53 -0
  27. data/lib/lino/model/option.rb +73 -0
  28. data/lib/lino/model/subcommand.rb +52 -0
  29. data/lib/lino/model.rb +13 -0
  30. data/lib/lino/version.rb +1 -1
  31. data/lib/lino.rb +11 -2
  32. metadata +72 -10
  33. data/lib/lino/appliables.rb +0 -23
  34. data/lib/lino/command_line.rb +0 -28
  35. data/lib/lino/command_line_builder.rb +0 -225
  36. data/lib/lino/options.rb +0 -72
  37. data/lib/lino/subcommand_builder.rb +0 -49
  38. data/lib/lino/utilities.rb +0 -59
data/lib/lino/model.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'model/command_line'
4
+ require_relative 'model/subcommand'
5
+ require_relative 'model/option'
6
+ require_relative 'model/flag'
7
+ require_relative 'model/argument'
8
+ require_relative 'model/environment_variable'
9
+
10
+ module Lino
11
+ module Model
12
+ end
13
+ end
data/lib/lino/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lino
4
- VERSION = '3.2.0.pre.4'
4
+ VERSION = '3.2.0.pre.6'
5
5
  end
data/lib/lino.rb CHANGED
@@ -1,8 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'lino/version'
4
- require 'lino/command_line'
5
- require 'lino/command_line_builder'
4
+ require 'lino/model'
5
+ require 'lino/builders'
6
+ require 'lino/executors'
7
+ require 'lino/errors'
6
8
 
7
9
  module Lino
10
+ class CommandLineBuilder
11
+ class << self
12
+ def for_command(command)
13
+ Lino::Builders::CommandLine.new(command:)
14
+ end
15
+ end
16
+ end
8
17
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lino
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0.pre.4
4
+ version: 3.2.0.pre.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - InfraBlocks Maintainers
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-10-30 00:00:00.000000000 Z
11
+ date: 2024-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: childprocess
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 5.0.0
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: hamster
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +80,34 @@ dependencies:
66
80
  - - ">="
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
69
111
  - !ruby/object:Gem::Dependency
70
112
  name: rake
71
113
  requirement: !ruby/object:Gem::Requirement
@@ -250,12 +292,32 @@ files:
250
292
  - bin/console
251
293
  - bin/setup
252
294
  - lib/lino.rb
253
- - lib/lino/appliables.rb
254
- - lib/lino/command_line.rb
255
- - lib/lino/command_line_builder.rb
256
- - lib/lino/options.rb
257
- - lib/lino/subcommand_builder.rb
258
- - lib/lino/utilities.rb
295
+ - lib/lino/builders.rb
296
+ - lib/lino/builders/command_line.rb
297
+ - lib/lino/builders/mixins/appliables.rb
298
+ - lib/lino/builders/mixins/arguments.rb
299
+ - lib/lino/builders/mixins/defaulting.rb
300
+ - lib/lino/builders/mixins/environment_variables.rb
301
+ - lib/lino/builders/mixins/executor.rb
302
+ - lib/lino/builders/mixins/option_config.rb
303
+ - lib/lino/builders/mixins/options.rb
304
+ - lib/lino/builders/mixins/state_boundary.rb
305
+ - lib/lino/builders/mixins/subcommands.rb
306
+ - lib/lino/builders/mixins/validation.rb
307
+ - lib/lino/builders/mixins/working_directory.rb
308
+ - lib/lino/builders/subcommand.rb
309
+ - lib/lino/errors.rb
310
+ - lib/lino/errors/execution_error.rb
311
+ - lib/lino/executors.rb
312
+ - lib/lino/executors/childprocess.rb
313
+ - lib/lino/executors/open4.rb
314
+ - lib/lino/model.rb
315
+ - lib/lino/model/argument.rb
316
+ - lib/lino/model/command_line.rb
317
+ - lib/lino/model/environment_variable.rb
318
+ - lib/lino/model/flag.rb
319
+ - lib/lino/model/option.rb
320
+ - lib/lino/model/subcommand.rb
259
321
  - lib/lino/version.rb
260
322
  homepage: https://github.com/infrablocks/lino
261
323
  licenses:
@@ -270,14 +332,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
270
332
  requirements:
271
333
  - - ">="
272
334
  - !ruby/object:Gem::Version
273
- version: '2.7'
335
+ version: '3.1'
274
336
  required_rubygems_version: !ruby/object:Gem::Requirement
275
337
  requirements:
276
338
  - - ">"
277
339
  - !ruby/object:Gem::Version
278
340
  version: 1.3.1
279
341
  requirements: []
280
- rubygems_version: 3.1.6
342
+ rubygems_version: 3.3.7
281
343
  signing_key:
282
344
  specification_version: 4
283
345
  summary: Command line execution utilities
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'utilities'
4
-
5
- module Lino
6
- module Appliables
7
- include Lino::Utilities
8
-
9
- def with_appliable(appliable)
10
- return self if nil?(appliable)
11
-
12
- appliable.apply(self)
13
- end
14
-
15
- def with_appliables(appliables)
16
- return self if nil_or_empty?(appliables)
17
-
18
- appliables.inject(self) do |s, appliable|
19
- s.with_appliable(appliable)
20
- end
21
- end
22
- end
23
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'open4'
4
-
5
- module Lino
6
- class CommandLine
7
- def initialize(command_line)
8
- @command_line = command_line
9
- end
10
-
11
- def execute(
12
- stdin: '',
13
- stdout: $stdout,
14
- stderr: $stderr
15
- )
16
- Open4.spawn(
17
- @command_line,
18
- stdin: stdin,
19
- stdout: stdout,
20
- stderr: stderr
21
- )
22
- end
23
-
24
- def to_s
25
- @command_line
26
- end
27
- end
28
- end
@@ -1,225 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'hamster'
4
- require_relative 'utilities'
5
- require_relative 'command_line'
6
- require_relative 'subcommand_builder'
7
- require_relative 'options'
8
- require_relative 'appliables'
9
-
10
- module Lino
11
- # rubocop:disable Metrics/ClassLength
12
- class CommandLineBuilder
13
- include Lino::Utilities
14
- include Lino::Options
15
- include Lino::Appliables
16
-
17
- class << self
18
- def for_command(command)
19
- CommandLineBuilder.new(command: command)
20
- end
21
- end
22
-
23
- # rubocop:disable Metrics/ParameterLists
24
- def initialize(
25
- command: nil,
26
- subcommands: [],
27
- options: [],
28
- arguments: [],
29
- environment_variables: [],
30
- option_separator: ' ',
31
- option_quoting: nil,
32
- option_placement: :after_command
33
- )
34
- @command = command
35
- @subcommands = Hamster::Vector.new(subcommands)
36
- @options = Hamster::Vector.new(options)
37
- @arguments = Hamster::Vector.new(arguments)
38
- @environment_variables = Hamster::Vector.new(environment_variables)
39
- @option_separator = option_separator
40
- @option_quoting = option_quoting
41
- @option_placement = option_placement
42
- end
43
-
44
- # rubocop:enable Metrics/ParameterLists
45
-
46
- def with_subcommand(subcommand, &block)
47
- return self if nil?(subcommand)
48
-
49
- with(
50
- subcommands: @subcommands.add(
51
- (block || ->(sub) { sub }).call(
52
- SubcommandBuilder.for_subcommand(subcommand)
53
- )
54
- )
55
- )
56
- end
57
-
58
- def with_subcommands(subcommands, &block)
59
- return self if nil_or_empty?(subcommands)
60
-
61
- without_block = subcommands[0...-1]
62
- with_block = subcommands.last
63
-
64
- without_block
65
- .inject(self) { |s, sc| s.with_subcommand(sc) }
66
- .with_subcommand(with_block, &block)
67
- end
68
-
69
- def with_option_separator(option_separator)
70
- with(option_separator: option_separator)
71
- end
72
-
73
- def with_option_quoting(character)
74
- with(option_quoting: character)
75
- end
76
-
77
- def with_option_placement(option_placement)
78
- with(option_placement: option_placement)
79
- end
80
-
81
- def with_options_after_command
82
- with_option_placement(:after_command)
83
- end
84
-
85
- def with_options_after_subcommands
86
- with_option_placement(:after_subcommands)
87
- end
88
-
89
- def with_options_after_arguments
90
- with_option_placement(:after_arguments)
91
- end
92
-
93
- def with_argument(argument)
94
- return self if nil?(argument)
95
-
96
- with(arguments: @arguments.add({ components: [argument] }))
97
- end
98
-
99
- def with_arguments(arguments)
100
- return self if nil_or_empty?(arguments)
101
-
102
- arguments.inject(self) { |s, argument| s.with_argument(argument) }
103
- end
104
-
105
- def with_environment_variable(environment_variable, value)
106
- with(
107
- environment_variables:
108
- @environment_variables.add(
109
- [
110
- environment_variable, value
111
- ]
112
- )
113
- )
114
- end
115
-
116
- def with_environment_variables(environment_variables)
117
- return self if nil_or_empty?(environment_variables)
118
-
119
- environment_variables.entries.inject(self) do |s, var|
120
- s.with_environment_variable(
121
- var.include?(:name) ? var[:name] : var[0],
122
- var.include?(:value) ? var[:value] : var[1]
123
- )
124
- end
125
- end
126
-
127
- def build
128
- components = formatted_components
129
- command_line =
130
- component_paths
131
- .collect { |path| path.inject(components) { |c, p| c && c[p] } }
132
- .reject(&:empty?)
133
- .join(' ')
134
-
135
- CommandLine.new(command_line)
136
- end
137
-
138
- private
139
-
140
- def component_paths
141
- [
142
- %i[environment_variables],
143
- %i[command],
144
- %i[options after_command],
145
- %i[subcommands],
146
- %i[options after_subcommands],
147
- %i[arguments],
148
- %i[options after_arguments]
149
- ]
150
- end
151
-
152
- def formatted_components
153
- {
154
- environment_variables: formatted_environment_variables,
155
- command: @command,
156
- options: formatted_options,
157
- subcommands: formatted_subcommands,
158
- arguments: formatted_arguments
159
- }
160
- end
161
-
162
- def formatted_environment_variables
163
- map_and_join(@environment_variables) do |var|
164
- "#{var[0]}=\"#{var[1].to_s.gsub('"', '\\"')}\""
165
- end
166
- end
167
-
168
- def formatted_options_with_placement(placement)
169
- map_and_join(
170
- options_with_placement(placement),
171
- &(quote_with(@option_quoting) >> join_with(@option_separator))
172
- )
173
- end
174
-
175
- def formatted_options
176
- %i[
177
- after_command
178
- after_subcommands
179
- after_arguments
180
- ].inject({}) do |options, placement|
181
- options
182
- .merge({ placement => formatted_options_with_placement(placement) })
183
- end
184
- end
185
-
186
- def formatted_subcommands
187
- map_and_join(@subcommands) do |sub|
188
- sub.build(@option_separator, @option_quoting)
189
- end
190
- end
191
-
192
- def formatted_arguments
193
- map_and_join(
194
- @arguments,
195
- &join_with(' ')
196
- )
197
- end
198
-
199
- def options_with_placement(placement)
200
- @options.select { |o| o[:placement] == placement } +
201
- if @option_placement == placement
202
- @options.select { |o| o[:placement].nil? }
203
- end
204
- end
205
-
206
- def with(**replacements)
207
- CommandLineBuilder.new(**state.merge(replacements))
208
- end
209
-
210
- def state
211
- {
212
- command: @command,
213
- subcommands: @subcommands,
214
- options: @options,
215
- arguments: @arguments,
216
- environment_variables: @environment_variables,
217
- option_separator: @option_separator,
218
- option_quoting: @option_quoting,
219
- option_placement: @option_placement
220
- }
221
- end
222
- end
223
-
224
- # rubocop:enable Metrics/ClassLength
225
- end
data/lib/lino/options.rb DELETED
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'utilities'
4
-
5
- module Lino
6
- module Options
7
- include Lino::Utilities
8
-
9
- def with_option(
10
- option,
11
- value,
12
- separator: nil,
13
- quoting: nil,
14
- placement: nil
15
- )
16
- return self if nil?(value)
17
-
18
- with(options: @options.add(
19
- {
20
- components: [option, value],
21
- separator: separator,
22
- quoting: quoting,
23
- placement: placement
24
- }
25
- ))
26
- end
27
-
28
- def with_options(options)
29
- return self if nil_or_empty?(options)
30
-
31
- options.entries.inject(self) do |s, entry|
32
- s.with_option(
33
- or_nth(entry, :option, 0),
34
- or_nth(entry, :value, 1),
35
- separator: or_nil(entry, :separator),
36
- quoting: or_nil(entry, :quoting),
37
- placement: or_nil(entry, :placement)
38
- )
39
- end
40
- end
41
-
42
- def with_repeated_option(
43
- option,
44
- values,
45
- separator: nil,
46
- quoting: nil,
47
- placement: nil
48
- )
49
- values.inject(self) do |s, value|
50
- s.with_option(
51
- option,
52
- value,
53
- separator: separator,
54
- quoting: quoting,
55
- placement: placement
56
- )
57
- end
58
- end
59
-
60
- def with_flag(flag)
61
- return self if nil?(flag)
62
-
63
- with(options: @options.add({ components: [flag] }))
64
- end
65
-
66
- def with_flags(flags)
67
- return self if nil_or_empty?(flags)
68
-
69
- flags.inject(self) { |s, flag| s.with_flag(flag) }
70
- end
71
- end
72
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'hamster'
4
- require_relative 'utilities'
5
- require_relative 'options'
6
- require_relative 'appliables'
7
-
8
- module Lino
9
- class SubcommandBuilder
10
- include Lino::Utilities
11
- include Lino::Options
12
- include Lino::Appliables
13
-
14
- class << self
15
- def for_subcommand(subcommand)
16
- SubcommandBuilder.new(subcommand: subcommand)
17
- end
18
- end
19
-
20
- def initialize(subcommand: nil, options: [])
21
- @subcommand = subcommand
22
- @options = Hamster::Vector.new(options)
23
- end
24
-
25
- def build(option_separator, option_quoting)
26
- components = [
27
- @subcommand,
28
- map_and_join(
29
- @options,
30
- &(quote_with(option_quoting) >> join_with(option_separator))
31
- )
32
- ]
33
- components.reject(&:empty?).join(' ')
34
- end
35
-
36
- private
37
-
38
- def with(**replacements)
39
- SubcommandBuilder.new(**state.merge(replacements))
40
- end
41
-
42
- def state
43
- {
44
- subcommand: @subcommand,
45
- options: @options
46
- }
47
- end
48
- end
49
- end
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Lino
4
- module Utilities
5
- def map_and_join(collection, &block)
6
- collection.map { |item| block.call(item) }.join(' ')
7
- end
8
-
9
- def join_with(global_separator)
10
- lambda do |item|
11
- item[:components].join(item[:separator] || global_separator)
12
- end
13
- end
14
-
15
- def quote_with(global_character)
16
- lambda do |item|
17
- item.merge(
18
- components: resolve_components(item, global_character)
19
- )
20
- end
21
- end
22
-
23
- def nil?(value)
24
- value.nil?
25
- end
26
-
27
- def empty?(value)
28
- value.respond_to?(:empty?) && value.empty?
29
- end
30
-
31
- def nil_or_empty?(value)
32
- nil?(value) || empty?(value)
33
- end
34
-
35
- private
36
-
37
- def resolve_components(item, global_character)
38
- components = item[:components]
39
- switch = components[0]
40
-
41
- if components.count > 1
42
- character = item[:quoting] || global_character
43
- value = components[1]
44
-
45
- [switch, "#{character}#{value}#{character}"]
46
- else
47
- components
48
- end
49
- end
50
-
51
- def or_nil(enumerable, key)
52
- enumerable.include?(key) ? enumerable[key] : nil
53
- end
54
-
55
- def or_nth(enumerable, key, index)
56
- enumerable.include?(key) ? enumerable[key] : enumerable[index]
57
- end
58
- end
59
- end