foobara-sh-cli-connector 0.0.15 → 0.0.17
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/CHANGELOG.md +9 -0
- data/src/sh_cli_connector/action_parser.rb +8 -7
- data/src/sh_cli_connector/globalish_parser.rb +1 -1
- data/src/sh_cli_connector/inputs_parser/option/attributes.rb +10 -2
- data/src/sh_cli_connector/inputs_parser/option/flag.rb +12 -3
- data/src/sh_cli_connector/inputs_parser/option/model.rb +10 -2
- data/src/sh_cli_connector/inputs_parser/option.rb +33 -6
- data/src/sh_cli_connector/inputs_parser.rb +8 -6
- data/src/sh_cli_connector/request.rb +6 -4
- data/src/sh_cli_connector.rb +26 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59a7b3a60573d7c637f5526e2a6d028c48906c7b5a865f2d204d64a48a25cf1f
|
4
|
+
data.tar.gz: dfc47f6db70767c09e9cab51c0c569d0ddc291f2d1abe3e29e5c7a4ecb7c9e11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6846e7d9362da9319f52d7c281feb802511199cdd0000aa6e7f40a161dc44fabc3a7676f66aee4e7795cccd6b29795efffaa2685db4e731d3f49777a9b1b91e6
|
7
|
+
data.tar.gz: 43c0b652981b6b113f92ebaaaa5f639e2915e02cb78a6e930e3e499b5524c1aa674eae9a5d7e99a603af08fff9e70c4cae1fe7c390d22db33f643acdee7cf412
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## [0.0.17] - 2025-05-03
|
2
|
+
|
3
|
+
- Deal with recent CommandConnector interface changes
|
4
|
+
- Make ParseError a Foobara::Error
|
5
|
+
|
6
|
+
## [0.0.16] - 2025-04-23
|
7
|
+
|
8
|
+
- Give a way to force inputs to be fully prefixed even if they don't collide
|
9
|
+
|
1
10
|
## [0.0.15] - 2025-04-12
|
2
11
|
|
3
12
|
- Default run args to ARGV
|
@@ -14,11 +14,11 @@ module Foobara
|
|
14
14
|
def action=(action)
|
15
15
|
if @action
|
16
16
|
# :nocov:
|
17
|
-
raise ParseError
|
17
|
+
raise ParseError.new(message: "Action already set")
|
18
18
|
# :nocov:
|
19
19
|
elsif argument
|
20
20
|
# :nocov:
|
21
|
-
raise ParseError
|
21
|
+
raise ParseError.new(message: "Not expecting #{action} to appear after #{argument}")
|
22
22
|
# :nocov:
|
23
23
|
else
|
24
24
|
@action = action
|
@@ -28,7 +28,7 @@ module Foobara
|
|
28
28
|
def argument=(argument)
|
29
29
|
if @argument
|
30
30
|
# :nocov:
|
31
|
-
raise ParseError
|
31
|
+
raise ParseError.new(message: "Argument already set")
|
32
32
|
# :nocov:
|
33
33
|
end
|
34
34
|
|
@@ -37,17 +37,18 @@ module Foobara
|
|
37
37
|
|
38
38
|
def validate!
|
39
39
|
if action.nil?
|
40
|
-
raise ParseError
|
41
|
-
|
40
|
+
raise ParseError.new(
|
41
|
+
message: "Found invalid option #{remainder.first} but was expecting an action like 'run' or 'help'"
|
42
|
+
)
|
42
43
|
end
|
43
44
|
|
44
45
|
if action == "run"
|
45
46
|
unless argument
|
46
|
-
raise ParseError
|
47
|
+
raise ParseError.new(message: "Missing command to run")
|
47
48
|
end
|
48
49
|
elsif action == "describe"
|
49
50
|
unless argument
|
50
|
-
raise ParseError
|
51
|
+
raise ParseError.new(message: "Missing command or type to describe")
|
51
52
|
end
|
52
53
|
end
|
53
54
|
end
|
@@ -93,7 +93,7 @@ module Foobara
|
|
93
93
|
[result.parsed[:input_format], result.parsed[:output_format]].compact.uniq.each do |format|
|
94
94
|
if format
|
95
95
|
unless Serializer.serializer_from_symbol(format)
|
96
|
-
raise ParseError
|
96
|
+
raise ParseError.new(message: "Unknown format: #{format}")
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
@@ -9,7 +9,14 @@ module Foobara
|
|
9
9
|
attribute_type.extends?(BuiltinTypes[:attributes])
|
10
10
|
end
|
11
11
|
|
12
|
-
def attribute_to_options(
|
12
|
+
def attribute_to_options(
|
13
|
+
attribute_name,
|
14
|
+
attribute_type:,
|
15
|
+
prefix:,
|
16
|
+
is_required:,
|
17
|
+
default:,
|
18
|
+
always_prefix_inputs:
|
19
|
+
)
|
13
20
|
sub_required_attributes = if is_required
|
14
21
|
attribute_type.declaration_data[:required] || []
|
15
22
|
end || []
|
@@ -22,7 +29,8 @@ module Foobara
|
|
22
29
|
attribute_type: sub_attribute_type,
|
23
30
|
prefix: [*prefix, *attribute_name],
|
24
31
|
is_required: is_required && sub_required_attributes.include?(sub_attribute_name),
|
25
|
-
default: defaults[sub_attribute_name]
|
32
|
+
default: defaults[sub_attribute_name],
|
33
|
+
always_prefix_inputs:
|
26
34
|
)
|
27
35
|
end.flatten
|
28
36
|
end
|
@@ -9,7 +9,14 @@ module Foobara
|
|
9
9
|
attribute_type.extends?(BuiltinTypes[:boolean])
|
10
10
|
end
|
11
11
|
|
12
|
-
def attribute_to_options(
|
12
|
+
def attribute_to_options(
|
13
|
+
attribute_name,
|
14
|
+
attribute_type:,
|
15
|
+
prefix:,
|
16
|
+
is_required:,
|
17
|
+
default:,
|
18
|
+
always_prefix_inputs:
|
19
|
+
)
|
13
20
|
klasses = []
|
14
21
|
|
15
22
|
klasses << OnFlag if default != true
|
@@ -21,7 +28,8 @@ module Foobara
|
|
21
28
|
attribute_type:,
|
22
29
|
is_required:,
|
23
30
|
default:,
|
24
|
-
prefix
|
31
|
+
prefix:,
|
32
|
+
always_prefix_inputs:
|
25
33
|
)
|
26
34
|
else
|
27
35
|
klasses.map do |klass|
|
@@ -30,7 +38,8 @@ module Foobara
|
|
30
38
|
attribute_type:,
|
31
39
|
is_required:,
|
32
40
|
default:,
|
33
|
-
prefix
|
41
|
+
prefix:,
|
42
|
+
always_prefix_inputs:
|
34
43
|
)
|
35
44
|
end
|
36
45
|
end
|
@@ -9,13 +9,21 @@ module Foobara
|
|
9
9
|
attribute_type.extends?(BuiltinTypes[:model]) && !attribute_type.extends?(BuiltinTypes[:entity])
|
10
10
|
end
|
11
11
|
|
12
|
-
def attribute_to_options(
|
12
|
+
def attribute_to_options(
|
13
|
+
attribute_name,
|
14
|
+
attribute_type:,
|
15
|
+
prefix:,
|
16
|
+
is_required:,
|
17
|
+
default:,
|
18
|
+
always_prefix_inputs:
|
19
|
+
)
|
13
20
|
Option.attribute_to_options(
|
14
21
|
attribute_name,
|
15
22
|
attribute_type: attribute_type.target_class.attributes_type,
|
16
23
|
prefix:,
|
17
24
|
is_required:,
|
18
|
-
default
|
25
|
+
default:,
|
26
|
+
always_prefix_inputs:
|
19
27
|
)
|
20
28
|
end
|
21
29
|
end
|
@@ -4,7 +4,14 @@ module Foobara
|
|
4
4
|
class InputsParser
|
5
5
|
class Option
|
6
6
|
class << self
|
7
|
-
def attribute_to_options(
|
7
|
+
def attribute_to_options(
|
8
|
+
attribute_name,
|
9
|
+
attribute_type:,
|
10
|
+
prefix:,
|
11
|
+
is_required:,
|
12
|
+
default:,
|
13
|
+
always_prefix_inputs:
|
14
|
+
)
|
8
15
|
[Model, Attributes, Flag].each do |klass|
|
9
16
|
if klass.applicable?(attribute_type)
|
10
17
|
return klass.attribute_to_options(
|
@@ -12,23 +19,39 @@ module Foobara
|
|
12
19
|
attribute_type:,
|
13
20
|
prefix:,
|
14
21
|
is_required:,
|
15
|
-
default
|
22
|
+
default:,
|
23
|
+
always_prefix_inputs:
|
16
24
|
)
|
17
25
|
end
|
18
26
|
end
|
19
27
|
|
20
|
-
new(
|
28
|
+
new(
|
29
|
+
attribute_name:,
|
30
|
+
attribute_type:,
|
31
|
+
prefix:,
|
32
|
+
is_required:,
|
33
|
+
default:,
|
34
|
+
always_prefix_inputs:
|
35
|
+
)
|
21
36
|
end
|
22
37
|
end
|
23
38
|
|
24
|
-
attr_accessor :attribute_type, :attribute_name, :is_required, :prefix, :default
|
39
|
+
attr_accessor :attribute_type, :attribute_name, :is_required, :prefix, :default, :always_prefix_inputs
|
25
40
|
|
26
|
-
def initialize(
|
41
|
+
def initialize(
|
42
|
+
attribute_name:,
|
43
|
+
attribute_type:,
|
44
|
+
prefix:,
|
45
|
+
is_required:,
|
46
|
+
default:,
|
47
|
+
always_prefix_inputs:
|
48
|
+
)
|
27
49
|
self.attribute_type = attribute_type
|
28
50
|
self.attribute_name = attribute_name
|
29
51
|
self.prefix = prefix
|
30
52
|
self.is_required = is_required
|
31
53
|
self.default = default
|
54
|
+
self.always_prefix_inputs = always_prefix_inputs
|
32
55
|
|
33
56
|
# TODO: support this
|
34
57
|
# args << attributes_type.declaration_data[:one_of] if attributes_type.declaration_data.key?(:one_of)
|
@@ -96,7 +119,11 @@ module Foobara
|
|
96
119
|
end
|
97
120
|
|
98
121
|
def _prefixed_name(full_paths)
|
99
|
-
|
122
|
+
if always_prefix_inputs
|
123
|
+
full_path.join("_")
|
124
|
+
else
|
125
|
+
_non_colliding_path(full_paths).join("_")
|
126
|
+
end
|
100
127
|
end
|
101
128
|
|
102
129
|
def _long_option_name(prefixed_name)
|
@@ -13,15 +13,16 @@ module Foobara
|
|
13
13
|
unless remainder.empty?
|
14
14
|
# TODO: let's invert the order for single command mode: parse inputs first, then global from remainder,
|
15
15
|
# and then raise if there's anything left
|
16
|
-
raise ParseError
|
16
|
+
raise ParseError.new(message: "Unexpected argument: #{remainder.first}")
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
attr_accessor :inputs_type, :parser, :current_array, :result
|
21
|
+
attr_accessor :inputs_type, :parser, :current_array, :result, :always_prefix_inputs
|
22
22
|
|
23
|
-
def initialize(inputs_type)
|
23
|
+
def initialize(inputs_type, always_prefix_inputs:)
|
24
24
|
self.inputs_type = inputs_type
|
25
|
+
self.always_prefix_inputs = always_prefix_inputs
|
25
26
|
self.parser = OptionParser.new
|
26
27
|
|
27
28
|
setup_parser
|
@@ -53,7 +54,7 @@ module Foobara
|
|
53
54
|
parser.set_summary_indent " "
|
54
55
|
|
55
56
|
if inputs_type&.element_types&.any?
|
56
|
-
attribute_to_option
|
57
|
+
attribute_to_option(always_prefix_inputs:)
|
57
58
|
# This feels wrong but the parser callback needs to access our result.
|
58
59
|
# TODO: figure out this smell and fix it
|
59
60
|
option_set.prepare_parser(self)
|
@@ -61,12 +62,12 @@ module Foobara
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def option_set
|
64
|
-
# TODO: this feels wrong to pass self here...
|
65
65
|
@option_set ||= OptionSet.new
|
66
66
|
end
|
67
67
|
|
68
68
|
def attribute_to_option(
|
69
69
|
attribute_name = nil,
|
70
|
+
always_prefix_inputs:,
|
70
71
|
attribute_type: inputs_type,
|
71
72
|
is_required: true,
|
72
73
|
default: nil,
|
@@ -77,7 +78,8 @@ module Foobara
|
|
77
78
|
attribute_type:,
|
78
79
|
prefix:,
|
79
80
|
is_required:,
|
80
|
-
default
|
81
|
+
default:,
|
82
|
+
always_prefix_inputs:
|
81
83
|
)
|
82
84
|
|
83
85
|
if options.is_a?(::Array)
|
@@ -1,7 +1,9 @@
|
|
1
1
|
module Foobara
|
2
2
|
module CommandConnectors
|
3
3
|
class ShCliConnector < CommandConnector
|
4
|
-
class ParseError <
|
4
|
+
class ParseError < Foobara::Error
|
5
|
+
context({})
|
6
|
+
end
|
5
7
|
|
6
8
|
class Request < CommandConnector::Request
|
7
9
|
attr_accessor :argv,
|
@@ -51,7 +53,7 @@ module Foobara
|
|
51
53
|
|
52
54
|
unless serializer_class
|
53
55
|
# :nocov:
|
54
|
-
raise ParseError
|
56
|
+
raise ParseError.new(message: "Unknown input format: #{input_format}")
|
55
57
|
# :nocov:
|
56
58
|
end
|
57
59
|
|
@@ -79,7 +81,7 @@ module Foobara
|
|
79
81
|
end
|
80
82
|
|
81
83
|
def inputs_parser_for(command_class = self.command_class)
|
82
|
-
InputsParser.new(command_class.inputs_type)
|
84
|
+
InputsParser.new(command_class.inputs_type, always_prefix_inputs: command_connector.always_prefix_inputs)
|
83
85
|
end
|
84
86
|
|
85
87
|
def globalish_parser
|
@@ -151,7 +153,7 @@ module Foobara
|
|
151
153
|
|
152
154
|
if result.remainder.any?
|
153
155
|
# :nocov:
|
154
|
-
raise ParseError
|
156
|
+
raise ParseError.new(message: "Found invalid options #{globalish_parser.remainder}")
|
155
157
|
# :nocov:
|
156
158
|
end
|
157
159
|
|
data/src/sh_cli_connector.rb
CHANGED
@@ -3,10 +3,18 @@ module Foobara
|
|
3
3
|
class AlreadyHasAConnectedCommand < StandardError; end
|
4
4
|
|
5
5
|
class ShCliConnector < CommandConnector
|
6
|
-
attr_accessor :program_name, :single_command_mode
|
7
|
-
|
8
|
-
def initialize(
|
6
|
+
attr_accessor :program_name, :single_command_mode, :always_prefix_inputs
|
7
|
+
|
8
|
+
def initialize(
|
9
|
+
*,
|
10
|
+
program_name: File.basename($PROGRAM_NAME),
|
11
|
+
single_command_mode: false,
|
12
|
+
always_prefix_inputs: false,
|
13
|
+
**,
|
14
|
+
&
|
15
|
+
)
|
9
16
|
self.program_name = program_name
|
17
|
+
self.always_prefix_inputs = always_prefix_inputs
|
10
18
|
|
11
19
|
connect_args = if single_command_mode
|
12
20
|
self.single_command_mode = true
|
@@ -62,7 +70,21 @@ module Foobara
|
|
62
70
|
response
|
63
71
|
end
|
64
72
|
|
65
|
-
def
|
73
|
+
def request_to_command_class(request)
|
74
|
+
super
|
75
|
+
rescue CommandConnector::NoCommandFoundError, ParseError => e
|
76
|
+
request.error = e
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def request_to_command_inputs(request)
|
81
|
+
super
|
82
|
+
rescue CommandConnector::NoCommandFoundError, ParseError => e
|
83
|
+
request.error = e
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
|
87
|
+
def request_to_command_instance(request)
|
66
88
|
super
|
67
89
|
rescue CommandConnector::NoCommandFoundError, ParseError => e
|
68
90
|
request.error = e
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foobara-sh-cli-connector
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Miles Georgi
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 2025-05-03 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: foobara
|
@@ -76,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
76
76
|
- !ruby/object:Gem::Version
|
77
77
|
version: '0'
|
78
78
|
requirements: []
|
79
|
-
rubygems_version: 3.6.
|
79
|
+
rubygems_version: 3.6.2
|
80
80
|
specification_version: 4
|
81
81
|
summary: Command-line connector for Foobara
|
82
82
|
test_files: []
|