command_kit 0.4.0 → 0.5.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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +2 -0
  3. data/.rubocop.yml +3 -0
  4. data/ChangeLog.md +18 -0
  5. data/LICENSE.txt +1 -1
  6. data/README.md +4 -1
  7. data/command_kit.gemspec +7 -2
  8. data/examples/subcommands/cli/config/get.rb +47 -0
  9. data/examples/subcommands/cli/config/set.rb +44 -0
  10. data/examples/subcommands/cli/config.rb +23 -0
  11. data/examples/subcommands/cli/list.rb +35 -0
  12. data/examples/subcommands/cli/update.rb +47 -0
  13. data/examples/subcommands/cli.rb +55 -0
  14. data/lib/command_kit/completion/install.rb +276 -0
  15. data/lib/command_kit/env/home.rb +1 -1
  16. data/lib/command_kit/env/prefix.rb +41 -0
  17. data/lib/command_kit/env/shell.rb +58 -0
  18. data/lib/command_kit/inflector.rb +1 -1
  19. data/lib/command_kit/options/parser.rb +1 -1
  20. data/lib/command_kit/os/linux.rb +1 -1
  21. data/lib/command_kit/os.rb +1 -1
  22. data/lib/command_kit/printing/tables/table_formatter.rb +2 -2
  23. data/lib/command_kit/version.rb +1 -1
  24. data/lib/command_kit/xdg.rb +1 -1
  25. metadata +12 -66
  26. data/spec/arguments/argument_spec.rb +0 -133
  27. data/spec/arguments/argument_value_spec.rb +0 -66
  28. data/spec/arguments_spec.rb +0 -279
  29. data/spec/bug_report_spec.rb +0 -266
  30. data/spec/colors_spec.rb +0 -771
  31. data/spec/command_kit_spec.rb +0 -8
  32. data/spec/command_name_spec.rb +0 -130
  33. data/spec/command_spec.rb +0 -123
  34. data/spec/commands/auto_load/subcommand_spec.rb +0 -82
  35. data/spec/commands/auto_load_spec.rb +0 -159
  36. data/spec/commands/auto_require_spec.rb +0 -142
  37. data/spec/commands/fixtures/test_auto_load/cli/commands/test1.rb +0 -10
  38. data/spec/commands/fixtures/test_auto_load/cli/commands/test2.rb +0 -10
  39. data/spec/commands/fixtures/test_auto_require/lib/test_auto_require/cli/commands/test1.rb +0 -10
  40. data/spec/commands/help_spec.rb +0 -66
  41. data/spec/commands/parent_command_spec.rb +0 -40
  42. data/spec/commands/subcommand_spec.rb +0 -99
  43. data/spec/commands_spec.rb +0 -839
  44. data/spec/description_spec.rb +0 -179
  45. data/spec/edit_spec.rb +0 -72
  46. data/spec/env/home_spec.rb +0 -46
  47. data/spec/env/path_spec.rb +0 -84
  48. data/spec/env_spec.rb +0 -123
  49. data/spec/examples_spec.rb +0 -211
  50. data/spec/exception_handler_spec.rb +0 -103
  51. data/spec/file_utils_spec.rb +0 -59
  52. data/spec/fixtures/template.erb +0 -5
  53. data/spec/help/man_spec.rb +0 -345
  54. data/spec/help_spec.rb +0 -94
  55. data/spec/inflector_spec.rb +0 -166
  56. data/spec/interactive_spec.rb +0 -415
  57. data/spec/main_spec.rb +0 -179
  58. data/spec/man_spec.rb +0 -46
  59. data/spec/open_app_spec.rb +0 -85
  60. data/spec/options/option_spec.rb +0 -343
  61. data/spec/options/option_value_spec.rb +0 -171
  62. data/spec/options/parser_spec.rb +0 -255
  63. data/spec/options/quiet_spec.rb +0 -51
  64. data/spec/options/verbose_spec.rb +0 -51
  65. data/spec/options/version_spec.rb +0 -146
  66. data/spec/options_spec.rb +0 -465
  67. data/spec/os/linux_spec.rb +0 -164
  68. data/spec/os_spec.rb +0 -233
  69. data/spec/package_manager_spec.rb +0 -806
  70. data/spec/pager_spec.rb +0 -217
  71. data/spec/printing/fields_spec.rb +0 -167
  72. data/spec/printing/indent_spec.rb +0 -132
  73. data/spec/printing/lists_spec.rb +0 -99
  74. data/spec/printing/tables/border_style.rb +0 -43
  75. data/spec/printing/tables/cell_builer_spec.rb +0 -135
  76. data/spec/printing/tables/row_builder_spec.rb +0 -165
  77. data/spec/printing/tables/style_spec.rb +0 -377
  78. data/spec/printing/tables/table_builder_spec.rb +0 -252
  79. data/spec/printing/tables/table_formatter_spec.rb +0 -1180
  80. data/spec/printing/tables_spec.rb +0 -1069
  81. data/spec/printing_spec.rb +0 -106
  82. data/spec/program_name_spec.rb +0 -70
  83. data/spec/spec_helper.rb +0 -3
  84. data/spec/stdio_spec.rb +0 -264
  85. data/spec/sudo_spec.rb +0 -51
  86. data/spec/terminal_spec.rb +0 -231
  87. data/spec/usage_spec.rb +0 -237
  88. data/spec/xdg_spec.rb +0 -191
@@ -1,171 +0,0 @@
1
- require 'spec_helper'
2
- require 'command_kit/options/option_value'
3
-
4
- describe CommandKit::Options::OptionValue do
5
- let(:type) { Integer }
6
- let(:usage) { 'COUNT' }
7
- let(:required) { true }
8
- let(:default) { 1 }
9
-
10
- describe ".default_usage" do
11
- subject { described_class }
12
-
13
- context "when given a Hash" do
14
- let(:type) do
15
- {'foo' => :foo, "bar" => :bar}
16
- end
17
-
18
- it "must join the Hash's keys with a '|' character" do
19
- expect(subject.default_usage(type)).to eq(type.keys.join('|'))
20
- end
21
- end
22
-
23
- context "when given an Array" do
24
- let(:type) do
25
- ['foo', 'bar', 'baz']
26
- end
27
-
28
- it "must join the Array's elements with a '|' character" do
29
- expect(subject.default_usage(type)).to eq(type.join('|'))
30
- end
31
- end
32
-
33
- context "when given a Regexp" do
34
- let(:type) { /[0-9a-f]+/ }
35
-
36
- it "must return the Regexp's source" do
37
- expect(subject.default_usage(type)).to eq(type.source)
38
- end
39
- end
40
-
41
- context "when given a Class" do
42
- module TestOptionValue
43
- class FooBarBaz
44
- end
45
- end
46
-
47
- let(:type) { TestOptionValue::FooBarBaz }
48
-
49
- it "must return the uppercase and underscored version of it's name" do
50
- expect(subject.default_usage(type)).to eq("FOO_BAR_BAZ")
51
- end
52
- end
53
-
54
- context "when given another kind of Object" do
55
- let(:type) { Object.new }
56
-
57
- it do
58
- expect {
59
- subject.default_usage(type)
60
- }.to raise_error(TypeError,"unsupported option type: #{type.inspect}")
61
- end
62
- end
63
- end
64
-
65
- describe "#initialize" do
66
- context "when the type: keyword is given" do
67
- let(:type) { Integer }
68
-
69
- subject { described_class.new(type: type) }
70
-
71
- it "must default #type to String" do
72
- expect(subject.type).to eq(type)
73
- end
74
- end
75
-
76
- context "when the type: keyword is not given" do
77
- subject { described_class.new }
78
-
79
- it "must default #type to String" do
80
- expect(subject.type).to eq(String)
81
- end
82
- end
83
-
84
- context "when the default: keyword is given" do
85
- subject { described_class.new(default: default) }
86
-
87
- it "must set #default" do
88
- expect(subject.default).to eq(default)
89
- end
90
- end
91
-
92
- context "when the default: keyword is not given" do
93
- subject { described_class.new() }
94
-
95
- it "default #default to String" do
96
- expect(subject.default).to eq(nil)
97
- end
98
- end
99
-
100
- context "when the usage: keyword is given" do
101
- let(:usage) { 'FOO' }
102
-
103
- subject { described_class.new(usage: usage) }
104
-
105
- it "must default #usage to String" do
106
- expect(subject.usage).to eq(usage)
107
- end
108
- end
109
-
110
- context "when the usage: keyword is not given" do
111
- subject { described_class.new }
112
-
113
- it "must default #usage based on #type" do
114
- expect(subject.usage).to eq(described_class.default_usage(subject.type))
115
- end
116
- end
117
- end
118
-
119
- subject do
120
- described_class.new(
121
- type: type,
122
- usage: usage,
123
- required: required,
124
- default: default
125
- )
126
- end
127
-
128
- describe "#usage" do
129
- let(:usage) { 'FOO' }
130
-
131
- context "when #optional? is true" do
132
- let(:required) { false }
133
-
134
- it "must wrap the usage within [ ] brackets" do
135
- expect(subject.usage).to eq("[#{usage}]")
136
- end
137
- end
138
-
139
- context "when #optional? is false" do
140
- let(:required) { true }
141
-
142
- it "should return the usage string unchanged" do
143
- expect(subject.usage).to eq(usage)
144
- end
145
- end
146
- end
147
-
148
- describe "#default_value" do
149
- context "when initialized with a default: that responded to #call" do
150
- let(:default) do
151
- ->{ [] }
152
- end
153
-
154
- it "must call the default #call method" do
155
- expect(subject.default_value).to eq(default.call)
156
- end
157
- end
158
-
159
- context "when initialized with a default: that it's an Object" do
160
- let(:default) { "" }
161
-
162
- it "must return the default: object" do
163
- expect(subject.default_value).to eq(default)
164
- end
165
-
166
- it "must duplicate the default: object each time" do
167
- expect(subject.default_value).to_not be(subject.default_value)
168
- end
169
- end
170
- end
171
- end
@@ -1,255 +0,0 @@
1
- require 'spec_helper'
2
- require 'command_kit/options/parser'
3
-
4
- describe CommandKit::Options::Parser do
5
- module TestOptionsParser
6
- class TestCommand
7
- include CommandKit::Options::Parser
8
-
9
- command_name 'cmd'
10
-
11
- end
12
- end
13
-
14
- let(:command_class) { TestOptionsParser::TestCommand }
15
-
16
- describe ".included" do
17
- subject { command_class }
18
-
19
- it { expect(subject).to include(CommandKit::Main) }
20
- it { expect(subject).to include(CommandKit::Usage) }
21
- it { expect(subject.usage).to eq('[options]') }
22
- end
23
-
24
- subject { command_class.new }
25
-
26
- describe "#initialize" do
27
- it "must initialize #option_parser" do
28
- expect(subject.option_parser).to be_kind_of(OptionParser)
29
- end
30
- end
31
-
32
- describe "#option_parser" do
33
- it "must have a default #banner" do
34
- expect(subject.option_parser.banner).to eq("Usage: #{subject.usage}")
35
- end
36
-
37
- it "must define a default --help option" do
38
- expect(subject.option_parser.to_s).to include(
39
- [
40
- '',
41
- ' -h, --help Print help information',
42
- ''
43
- ].join($/)
44
- )
45
- end
46
- end
47
-
48
- module TestOptionsParser
49
- class CommandWithOptions
50
-
51
- include CommandKit::Options::Parser
52
-
53
- command_name 'cmd'
54
-
55
- attr_reader :foo
56
-
57
- attr_reader :bar
58
-
59
- attr_reader :argv
60
-
61
- def initialize(**kwargs)
62
- super(**kwargs)
63
-
64
- @option_parser.on('-f','--foo','Foo option') do
65
- @foo = true
66
- end
67
-
68
- @option_parser.on('-b','--bar BAR',Integer,'Bar option') do |bar|
69
- @bar = bar
70
- end
71
- end
72
-
73
- def run(*argv)
74
- @argv = argv
75
- end
76
-
77
- end
78
- end
79
-
80
- let(:command_class) { TestOptionsParser::CommandWithOptions }
81
- subject { command_class.new }
82
-
83
- describe "#option_parser" do
84
- it { expect(subject.option_parser).to be_kind_of(OptionParser) }
85
- end
86
-
87
- describe "#main" do
88
- context "when --help is given as an argument" do
89
- it "must call #help" do
90
- expect(subject).to receive(:help)
91
-
92
- subject.main(['--help'])
93
- end
94
-
95
- it "must return 0" do
96
- allow(subject).to receive(:help)
97
-
98
- expect(subject.main(['--help'])).to eq(0)
99
- end
100
-
101
- it "must stop parsing options" do
102
- allow(subject).to receive(:help)
103
- subject.main(['--help', '--foo', '1'])
104
-
105
- expect(subject.foo).to be(nil)
106
- expect(subject.argv).to be(nil)
107
- end
108
- end
109
- end
110
-
111
- describe "#parse_options" do
112
- it "must parse options and return any additional arguments" do
113
- additional_args = %w[arg1 arg2]
114
- bar = 2
115
- argv = ['--foo', '--bar', bar.to_s, *additional_args]
116
-
117
- expect(subject.parse_options(argv)).to eq(additional_args)
118
- expect(subject.foo).to eq(true)
119
- expect(subject.bar).to eq(bar)
120
- end
121
-
122
- context "when -h,--help is passed" do
123
- it "must call #help and exit with 0" do
124
- expect(subject).to receive(:help)
125
- expect(subject).to receive(:exit).with(0)
126
-
127
- subject.parse_options(['--help'])
128
- end
129
- end
130
-
131
- context "when an invalid option is given" do
132
- it "must call #on_invalid_option" do
133
- expect(subject).to receive(:on_invalid_option).with(OptionParser::InvalidOption)
134
-
135
- subject.parse_options(['--xxx'])
136
- end
137
- end
138
-
139
- context "when an invalid argument is given" do
140
- it "must call #on_invalid_argument" do
141
- expect(subject).to receive(:on_invalid_argument).with(OptionParser::InvalidArgument)
142
-
143
- subject.parse_options(['--bar', 'xxx'])
144
- end
145
- end
146
-
147
- context "when a required argument is missing" do
148
- it "must call #on_missing_argument" do
149
- expect(subject).to receive(:on_missing_argument).with(OptionParser::MissingArgument)
150
-
151
- subject.parse_options(['--bar'])
152
- end
153
- end
154
-
155
- context "when a needless argument is given" do
156
- it "must call #on_needless_argument" do
157
- expect(subject).to receive(:on_needless_argument).with(OptionParser::NeedlessArgument)
158
-
159
- subject.parse_options(['--foo=xxx'])
160
- end
161
- end
162
- end
163
-
164
- describe "#on_parse_error" do
165
- let(:error) { OptionParser::InvalidOption.new("--xxx") }
166
-
167
- it "must print an error message and exit with 1" do
168
- expect(subject).to receive(:exit).with(1)
169
-
170
- expect { subject.on_parse_error(error) }.to output(
171
- [
172
- "#{subject.command_name}: #{error.message}",
173
- "Try '#{subject.command_name} --help' for more information.",
174
- ''
175
- ].join($/)
176
- ).to_stderr
177
- end
178
- end
179
-
180
- describe "#on_invalid_option" do
181
- let(:error) { OptionParser::InvalidOption.new('--xxx') }
182
-
183
- it "must call #on_parse_error by default" do
184
- expect(subject).to receive(:on_parse_error).with(error)
185
-
186
- subject.on_invalid_option(error)
187
- end
188
- end
189
-
190
- describe "#on_ambiguous_option" do
191
- let(:error) { OptionParser::AmbiguousOption.new('--xxx') }
192
-
193
- it "must call #on_parse_error by default" do
194
- expect(subject).to receive(:on_parse_error).with(error)
195
-
196
- subject.on_ambiguous_option(error)
197
- end
198
- end
199
-
200
- describe "#on_invalid_argument" do
201
- let(:error) { OptionParser::InvalidArgument.new('--xxx') }
202
-
203
- it "must call #on_parse_error by default" do
204
- expect(subject).to receive(:on_parse_error).with(error)
205
-
206
- subject.on_invalid_argument(error)
207
- end
208
- end
209
-
210
- describe "#on_missing_argument" do
211
- let(:error) { OptionParser::MissingArgument.new('--xxx') }
212
-
213
- it "must call #on_parse_error by default" do
214
- expect(subject).to receive(:on_parse_error).with(error)
215
-
216
- subject.on_missing_argument(error)
217
- end
218
- end
219
-
220
- describe "#on_needless_argument" do
221
- let(:error) { OptionParser::NeedlessArgument.new('--xxx') }
222
-
223
- it "must call #on_parse_error by default" do
224
- expect(subject).to receive(:on_parse_error).with(error)
225
-
226
- subject.on_needless_argument(error)
227
- end
228
- end
229
-
230
- describe "#on_ambiguous_argument" do
231
- let(:error) { OptionParser::AmbiguousArgument.new('--xxx') }
232
-
233
- it "must call #on_parse_error by default" do
234
- expect(subject).to receive(:on_parse_error).with(error)
235
-
236
- subject.on_ambiguous_argument(error)
237
- end
238
- end
239
-
240
- describe "#help_options" do
241
- it "must print the #option_parser" do
242
- expect { subject.help_options }.to output(
243
- subject.option_parser.to_s
244
- ).to_stdout
245
- end
246
- end
247
-
248
- describe "#help" do
249
- it "must call #help_options" do
250
- expect(subject).to receive(:help_options)
251
-
252
- subject.help
253
- end
254
- end
255
- end
@@ -1,51 +0,0 @@
1
- require 'spec_helper'
2
- require 'command_kit/options/quiet'
3
-
4
- describe CommandKit::Options::Quiet do
5
- module TestOptionsQuiet
6
- class TestCommand
7
- include CommandKit::Options::Quiet
8
- end
9
- end
10
-
11
- let(:command_class) { TestOptionsQuiet::TestCommand }
12
-
13
- describe ".included" do
14
- subject { command_class }
15
-
16
- it "must include CommandKit::Options" do
17
- expect(subject).to include(CommandKit::Options)
18
- end
19
-
20
- it "must define a quiet option" do
21
- expect(subject.options[:quiet]).to_not be(nil)
22
- expect(subject.options[:quiet].short).to eq('-q')
23
- expect(subject.options[:quiet].long).to eq('--quiet')
24
- expect(subject.options[:quiet].desc).to eq('Enables quiet output')
25
- end
26
- end
27
-
28
- subject { command_class.new }
29
-
30
- describe "#quiet?" do
31
- context "when @quiet is true" do
32
- before do
33
- subject.instance_variable_set('@quiet',true)
34
- end
35
-
36
- it "must return true" do
37
- expect(subject.quiet?).to be(true)
38
- end
39
- end
40
-
41
- context "when @quiet is false" do
42
- before do
43
- subject.instance_variable_set('@quiet',false)
44
- end
45
-
46
- it "must return false" do
47
- expect(subject.quiet?).to be(false)
48
- end
49
- end
50
- end
51
- end
@@ -1,51 +0,0 @@
1
- require 'spec_helper'
2
- require 'command_kit/options/verbose'
3
-
4
- describe CommandKit::Options::Verbose do
5
- module TestOptionsVerbose
6
- class TestCommand
7
- include CommandKit::Options::Verbose
8
- end
9
- end
10
-
11
- let(:command_class) { TestOptionsVerbose::TestCommand }
12
-
13
- describe ".included" do
14
- subject { command_class }
15
-
16
- it "must include CommandKit::Options" do
17
- expect(subject).to include(CommandKit::Options)
18
- end
19
-
20
- it "must define a verbose option" do
21
- expect(subject.options[:verbose]).to_not be(nil)
22
- expect(subject.options[:verbose].short).to eq('-v')
23
- expect(subject.options[:verbose].long).to eq('--verbose')
24
- expect(subject.options[:verbose].desc).to eq('Enables verbose output')
25
- end
26
- end
27
-
28
- subject { command_class.new }
29
-
30
- describe "#verbose?" do
31
- context "when @verbose is true" do
32
- before do
33
- subject.instance_variable_set('@verbose',true)
34
- end
35
-
36
- it "must return true" do
37
- expect(subject.verbose?).to be(true)
38
- end
39
- end
40
-
41
- context "when @verbose is false" do
42
- before do
43
- subject.instance_variable_set('@verbose',false)
44
- end
45
-
46
- it "must return false" do
47
- expect(subject.verbose?).to be(false)
48
- end
49
- end
50
- end
51
- end
@@ -1,146 +0,0 @@
1
- require 'spec_helper'
2
- require 'command_kit/options/version'
3
-
4
- require 'stringio'
5
-
6
- describe CommandKit::Options::Version do
7
- module TestOptionsVersion
8
- class TestCommandWithoutVersion
9
-
10
- include CommandKit::Options::Version
11
-
12
- command_name 'test'
13
-
14
- end
15
-
16
- class TestCommandWithVersion
17
-
18
- include CommandKit::Options::Version
19
-
20
- command_name 'test'
21
- version '0.1.0'
22
-
23
- end
24
- end
25
-
26
- describe ".included" do
27
- subject { TestOptionsVersion::TestCommandWithVersion }
28
-
29
- it "must include CommandKit::Options" do
30
- expect(subject).to include(CommandKit::Options)
31
- end
32
- end
33
-
34
- describe ".version" do
35
- context "when no .version has been previously set" do
36
- subject { TestOptionsVersion::TestCommandWithoutVersion }
37
-
38
- it "must return nil" do
39
- expect(subject.version).to be(nil)
40
- end
41
- end
42
-
43
- context "when a .version has been set" do
44
- subject { TestOptionsVersion::TestCommandWithVersion }
45
-
46
- it "must return the set version" do
47
- expect(subject.version).to eq('0.1.0')
48
- end
49
- end
50
-
51
- context "when the command class inherites from another class" do
52
- context "but no version are defined" do
53
- module TestOptionsVersion
54
- class InheritedCommandWithoutVersion < TestCommandWithoutVersion
55
- end
56
- end
57
-
58
- subject { TestOptionsVersion::InheritedCommandWithoutVersion }
59
-
60
- it "must return nil" do
61
- expect(subject.version).to be(nil)
62
- end
63
- end
64
-
65
- context "when the superclass defines the version" do
66
- module TestOptionsVersion
67
- class InheritedCommandWithInheritedVersion < TestCommandWithVersion
68
- end
69
- end
70
-
71
- let(:super_class) { TestOptionsVersion::TestCommandWithVersion }
72
- subject { TestOptionsVersion::InheritedCommandWithInheritedVersion }
73
-
74
- it "must return the version defined in the superclass" do
75
- expect(subject.version).to eq(super_class.version)
76
- end
77
- end
78
-
79
- context "when the subclass defines the version" do
80
- module TestOptionsVersion
81
- class InheritedCommandWithOwnVersion < TestCommandWithoutVersion
82
-
83
- version '0.1.0'
84
-
85
- end
86
- end
87
-
88
- let(:super_subject) { TestOptionsVersion::TestCommandWithoutVersion }
89
- subject { TestOptionsVersion::InheritedCommandWithOwnVersion }
90
-
91
- it "must return the version set in the subclass" do
92
- expect(subject.version).to eq('0.1.0')
93
- end
94
-
95
- it "must not change the superclass'es version" do
96
- expect(super_subject.version).to be(nil)
97
- end
98
- end
99
-
100
- context "when subclass overrides the superclass's version" do
101
- module TestOptionsVersion
102
- class InheritedCommandThatOverridesVersion < TestCommandWithVersion
103
-
104
- version '0.2.0'
105
-
106
- end
107
- end
108
-
109
- let(:super_subject) { TestOptionsVersion::TestCommandWithVersion }
110
- subject { TestOptionsVersion::InheritedCommandThatOverridesVersion }
111
-
112
- it "must return the version set in the subclass" do
113
- expect(subject.version).to eq('0.2.0')
114
- end
115
-
116
- it "must not change the superclass'es version" do
117
- expect(super_subject.version).to eq('0.1.0')
118
- end
119
- end
120
- end
121
- end
122
-
123
- let(:command_class) { TestOptionsVersion::TestCommandWithVersion }
124
-
125
- subject { command_class.new }
126
-
127
- describe "#version" do
128
- it "must return the class'es .version value" do
129
- expect(subject.version).to eq(command_class.version)
130
- end
131
- end
132
-
133
- describe "#print_version" do
134
- let(:stdout) { StringIO.new }
135
-
136
- subject { command_class.new(stdout: stdout) }
137
-
138
- it "must print the #command_name and #version" do
139
- subject.print_version
140
-
141
- expect(stdout.string).to eq(
142
- "#{subject.command_name} #{subject.version}#{$/}"
143
- )
144
- end
145
- end
146
- end