subcommand-optparse 0.0.1 → 0.0.2
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/.rspec +2 -0
- data/README.md +6 -2
- data/examples/sample_command.rb +6 -2
- data/lib/subcommand_optparse/version.rb +1 -1
- data/lib/subcommand_optparse.rb +116 -30
- data/spec/spec_helper.rb +20 -0
- data/spec/subcommand_optparse_spec.rb +50 -0
- metadata +22 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 634e18a8f111dd35ab12a98897abb16db057d351
|
4
|
+
data.tar.gz: 63beca167bd690d821b878f3265f6e1f876b62ca
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aed83c4d4aa0a5abad231e614c7c41e66827353695d19faa91dc3d771635c480330cdd2720a068920f205796091e62518278cc5db90e2efddc874e5133a01179
|
7
|
+
data.tar.gz: cf9879e2f5d5fc11b900ffd169b14d12937950fb23dfea2feda4796c483c8a9f3537addec92d7ce97545681fbaf130f535a7e127ff03031a5a5bc5cacd414b7d
|
data/.rspec
ADDED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# subcommand-optparse
|
2
2
|
|
3
3
|
Option parser for a command with subcommands, which is parsed by library 'optparse'
|
4
4
|
|
@@ -18,7 +18,11 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
For now, please see the files in the directory 'examples' and source codes.
|
22
|
+
|
23
|
+
## License
|
24
|
+
|
25
|
+
GPLv3
|
22
26
|
|
23
27
|
## Contributing
|
24
28
|
|
data/examples/sample_command.rb
CHANGED
@@ -4,18 +4,22 @@ require "subcommand_optparse"
|
|
4
4
|
options = {}
|
5
5
|
|
6
6
|
parser = SubCmdOptParser.new(:help_command => true) do |sc|
|
7
|
+
sc.program_name = "sample_command.rb"
|
8
|
+
sc.version = "0.0.1"
|
9
|
+
sc.release = "hello world"
|
10
|
+
|
7
11
|
sc.global_option do |opt|
|
8
12
|
opt.on("--global-option", "Banner of global option") do |v|
|
9
13
|
options[:global_option] = true
|
10
14
|
end
|
11
15
|
end
|
12
|
-
sc.subcommand("foo", "
|
16
|
+
sc.subcommand("foo", "Description of foo") do |opt|
|
13
17
|
opt.on("--foo-option", "Foo option") do |v|
|
14
18
|
options[:foo] = true
|
15
19
|
end
|
16
20
|
end
|
17
21
|
sc.subcommand("bar") do |opt|
|
18
|
-
opt.on("--bar-option", "
|
22
|
+
opt.on("--bar-option", "Description of bar") do |v|
|
19
23
|
options[:bar] = true
|
20
24
|
end
|
21
25
|
end
|
data/lib/subcommand_optparse.rb
CHANGED
@@ -5,31 +5,59 @@ require "active_support/core_ext/array/extract_options"
|
|
5
5
|
class SubCmdOptParser
|
6
6
|
class OptionParserForSubCmd < OptionParser
|
7
7
|
attr_accessor :subcommand_name
|
8
|
+
attr_accessor :description
|
9
|
+
|
10
|
+
def initialize(subcmd, description, width, indent)
|
11
|
+
@subcommand_name = subcmd
|
12
|
+
@description = description
|
13
|
+
super(nil, width, indent)
|
14
|
+
end
|
8
15
|
|
9
16
|
def banner
|
10
17
|
unless @banner
|
11
18
|
@banner = "Usage: #{program_name} #{@subcommand_name || '<command>'} [options]"
|
19
|
+
if @description
|
20
|
+
@banner << "\n\n#{@description}"
|
21
|
+
end
|
12
22
|
visit(:add_banner, @banner)
|
13
23
|
end
|
14
24
|
@banner
|
15
25
|
end
|
16
26
|
end
|
17
27
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
28
|
+
attr_accessor :program_name
|
29
|
+
attr_accessor :summary_width
|
30
|
+
attr_accessor :summary_indent
|
31
|
+
attr_accessor :version
|
32
|
+
attr_accessor :release
|
33
|
+
alias set_program_name program_name=
|
34
|
+
alias set_summary_width summary_width=
|
35
|
+
alias set_summary_indent summary_indent=
|
36
|
+
|
37
|
+
# @overload initialize(width = 32, indent = ' ' * 4, opts = {})
|
38
|
+
# @param [Fixnum] width Width of summary
|
39
|
+
# @param [String] indent Indent of summary
|
22
40
|
# @param [Hash] opts Options hash
|
23
|
-
# @option opts [boolean] :help_command
|
41
|
+
# @option opts [boolean] :help_command
|
42
|
+
# If the value is false then command "help" is not set automatically. Default is true
|
43
|
+
# @option opts [boolean] :version_command
|
44
|
+
# If the value is false then command "version" is not set automatically. Default is true
|
45
|
+
# @option opts [boolean] :accept_undefined_command
|
46
|
+
# If the value is false then show help for undefined commands. Default is false
|
47
|
+
# @option opts [boolean] :parse_only
|
48
|
+
# Commands (help and version) do not exit with printing messages and just parse options
|
24
49
|
# @yield [sc]
|
25
50
|
# @yieldparam [SubCmdOptParser] sc Option parser
|
26
51
|
def initialize(*args, &block)
|
27
52
|
opts = args.extract_options!
|
28
|
-
@
|
29
|
-
@
|
53
|
+
@summary_width = args[0] || 32
|
54
|
+
@summary_indent = args[1] || ' ' * 4
|
30
55
|
@global_option_setting = nil
|
31
56
|
@subcommand = []
|
32
57
|
@help_subcommand_use_p = (!opts.has_key?(:help_command) || opts[:help_command])
|
58
|
+
@version_subcommand_use_p = (!opts.has_key?(:version_command) || opts[:version_command])
|
59
|
+
@accept_undefined_command = opts[:accept_undefined_command]
|
60
|
+
@parse_only = opts[:parse_only]
|
33
61
|
if block_given?
|
34
62
|
yield(self)
|
35
63
|
end
|
@@ -42,24 +70,36 @@ class SubCmdOptParser
|
|
42
70
|
@global_option_setting = block
|
43
71
|
end
|
44
72
|
|
45
|
-
|
73
|
+
def subcommand_defined?(subcmd)
|
74
|
+
!!@subcommand.assoc(subcmd)
|
75
|
+
end
|
76
|
+
|
77
|
+
# @overload subcommand(name, description = nil, opts = {})
|
46
78
|
# @param [String] name Name of subcommand
|
79
|
+
# @param [String] description Description of subcommand whose first line is shows in list of subcommands
|
47
80
|
# @param [Hash] opts Options hash
|
48
81
|
# @option opts [boolean] :load_global_options If the value is false then global options are not loaded
|
49
82
|
# @yield [opt]
|
50
83
|
# @yieldparam [OptionParserForSubCmd] opt Option parser for the subcommand
|
51
84
|
def subcommand(name, *args, &block)
|
85
|
+
if subcommand_defined?(name)
|
86
|
+
raise ArgumentError, "Command '#{name}' has been already defined"
|
87
|
+
end
|
52
88
|
opts = args.extract_options!
|
53
|
-
|
54
|
-
|
89
|
+
description = args.shift
|
90
|
+
if args.size > 0
|
91
|
+
raise ArgumentError, "Too many arguments"
|
92
|
+
end
|
93
|
+
h = { :description => description, :setting => block }
|
55
94
|
h[:load_global_options] = !(opts.has_key?(:load_global_options) && !opts[:load_global_options])
|
56
95
|
@subcommand << [name, h]
|
57
96
|
end
|
58
97
|
|
59
|
-
def
|
60
|
-
|
98
|
+
def subcommand_clear(name)
|
99
|
+
@subcommand.delete_if do |subcmd, data|
|
100
|
+
subcmd == name
|
101
|
+
end
|
61
102
|
end
|
62
|
-
private :get_banner
|
63
103
|
|
64
104
|
def get_subcmd_data(subcmd)
|
65
105
|
subcmd_data = nil
|
@@ -71,11 +111,12 @@ class SubCmdOptParser
|
|
71
111
|
private :get_subcmd_data
|
72
112
|
|
73
113
|
def get_option_parser(subcmd, subcmd_data)
|
74
|
-
|
75
|
-
opt
|
76
|
-
|
77
|
-
|
78
|
-
|
114
|
+
desc = subcmd_data && subcmd_data[:description]
|
115
|
+
opt = OptionParserForSubCmd.new(subcmd, desc, @summary_width, @summary_indent)
|
116
|
+
opt.program_name = program_name if @program_name
|
117
|
+
opt.version = version if @version
|
118
|
+
opt.release = release if @release
|
119
|
+
subcmd_data[:setting].call(opt) if subcmd_data && subcmd_data[:setting]
|
79
120
|
if @global_option_setting && (!subcmd_data || subcmd_data[:load_global_options])
|
80
121
|
@global_option_setting.call(opt)
|
81
122
|
end
|
@@ -83,35 +124,80 @@ class SubCmdOptParser
|
|
83
124
|
end
|
84
125
|
private :get_option_parser
|
85
126
|
|
86
|
-
def message_list_subcommands
|
87
|
-
mes = "
|
127
|
+
def message_list_subcommands
|
128
|
+
mes = "Commands are:\n"
|
129
|
+
max_size_subcmd = (@subcommand.map { |name, val| name.size }).max
|
130
|
+
str_size = (max_size_subcmd.even? ? max_size_subcmd : max_size_subcmd + 1) + 4
|
88
131
|
@subcommand.each do |name, val|
|
89
|
-
|
132
|
+
desc = ((val && val[:description]) ? val[:description].each_line.first.strip : "")
|
133
|
+
mes << (" %-#{str_size}s" % name) << desc << "\n"
|
90
134
|
end
|
91
135
|
mes
|
92
136
|
end
|
93
137
|
private :message_list_subcommands
|
94
138
|
|
95
|
-
def
|
139
|
+
def get_banner_help(opt)
|
140
|
+
"Usage: #{opt.program_name} <command> [options]\n\n" + message_list_subcommands
|
141
|
+
end
|
142
|
+
private :get_banner_help
|
143
|
+
|
144
|
+
def define_prepared_command
|
96
145
|
if @help_subcommand_use_p
|
97
|
-
|
146
|
+
unless subcommand_defined?("help")
|
147
|
+
subcommand("help", "Show help message", :load_global_options => false) do |opt|
|
148
|
+
opt.banner = get_banner_help(opt)
|
149
|
+
end
|
150
|
+
end
|
98
151
|
end
|
152
|
+
if @version_subcommand_use_p
|
153
|
+
unless subcommand_defined?("version")
|
154
|
+
subcommand("version", "Show version", :load_global_options => false)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
private :define_prepared_command
|
159
|
+
|
160
|
+
def exec_prepared_command(opt, argv)
|
161
|
+
unless @parse_only
|
162
|
+
case opt.subcommand_name
|
163
|
+
when "help"
|
164
|
+
if !argv.empty?
|
165
|
+
if !subcommand_defined?(argv[0])
|
166
|
+
puts "Unknown command: #{argv[0].inspect}"
|
167
|
+
else
|
168
|
+
opt = get_option_parser(argv[0], get_subcmd_data(argv[0]))
|
169
|
+
end
|
170
|
+
end
|
171
|
+
print opt.to_s
|
172
|
+
return true
|
173
|
+
when "version"
|
174
|
+
puts opt.ver || "Unknown version"
|
175
|
+
return true
|
176
|
+
end
|
177
|
+
end
|
178
|
+
nil
|
179
|
+
end
|
180
|
+
private :exec_prepared_command
|
99
181
|
|
182
|
+
def parse!(argv = ARGV)
|
183
|
+
define_prepared_command
|
100
184
|
subcmd = argv[0]
|
101
185
|
if subcmd_data = get_subcmd_data(subcmd)
|
102
186
|
argv.shift
|
103
187
|
else
|
104
188
|
subcmd = nil
|
189
|
+
unless @accept_undefined_command
|
190
|
+
subcmd = "help"
|
191
|
+
unless subcmd_data = get_subcmd_data(subcmd)
|
192
|
+
raise "Unknown command #{subcmd.inspect}"
|
193
|
+
end
|
194
|
+
end
|
105
195
|
end
|
106
196
|
opt = get_option_parser(subcmd, subcmd_data)
|
107
|
-
opt
|
108
|
-
|
109
|
-
if @help_subcommand_use_p && subcmd == "help"
|
110
|
-
print opt.to_s + "\n"
|
111
|
-
puts message_list_subcommands(opt)
|
112
|
-
exit
|
197
|
+
if exec_prepared_command(opt, argv)
|
198
|
+
exit(0)
|
113
199
|
end
|
114
|
-
|
200
|
+
opt.parse!(argv)
|
115
201
|
subcmd
|
116
202
|
end
|
117
203
|
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
$LOAD_PATH << File.expand_path(File.join(__dir__, "../lib"))
|
2
|
+
|
3
|
+
require "subcommand_optparse"
|
4
|
+
|
5
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
6
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
7
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
8
|
+
# loaded once.
|
9
|
+
#
|
10
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
11
|
+
RSpec.configure do |config|
|
12
|
+
config.run_all_when_everything_filtered = true
|
13
|
+
config.filter_run :focus => true
|
14
|
+
|
15
|
+
# Run specs in random order to surface order dependencies. If you find an
|
16
|
+
# order dependency and want to debug it, you can fix the order by providing
|
17
|
+
# the seed, which is printed after each run.
|
18
|
+
# --seed 1234
|
19
|
+
config.order = 'random'
|
20
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe SubCmdOptParser do
|
4
|
+
it "should raise error" do
|
5
|
+
opt = SubCmdOptParser.new do |opt_subcmd|
|
6
|
+
opt_subcmd.subcommand("hello")
|
7
|
+
expect do
|
8
|
+
opt_subcmd.subcommand("hello")
|
9
|
+
end.to raise_error
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when executing prepared commands" do
|
14
|
+
before(:each) do
|
15
|
+
$stdout = StringIO.new
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should exit in help command" do
|
19
|
+
opt = SubCmdOptParser.new
|
20
|
+
expect do
|
21
|
+
opt.parse!(["help"])
|
22
|
+
end.to raise_error(SystemExit)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should exit in version command" do
|
26
|
+
opt = SubCmdOptParser.new
|
27
|
+
expect do
|
28
|
+
opt.parse!(["version"])
|
29
|
+
end.to raise_error(SystemExit)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should not exit in help command" do
|
33
|
+
opt = SubCmdOptParser.new(:parse_only => true)
|
34
|
+
expect do
|
35
|
+
opt.parse!(["help"])
|
36
|
+
end.not_to raise_error
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not exit in version command" do
|
40
|
+
opt = SubCmdOptParser.new(:parse_only => true)
|
41
|
+
expect do
|
42
|
+
opt.parse!(["version"])
|
43
|
+
end.not_to raise_error
|
44
|
+
end
|
45
|
+
|
46
|
+
after(:each) do
|
47
|
+
$stdout = STDOUT
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
metadata
CHANGED
@@ -1,83 +1,83 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: subcommand-optparse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takayuki YAMAGUCHI
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: yard
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: activesupport
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
description: Option parser for subcommands
|
@@ -87,7 +87,8 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
-
- .gitignore
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
91
92
|
- Gemfile
|
92
93
|
- LICENSE.txt
|
93
94
|
- README.md
|
@@ -95,6 +96,8 @@ files:
|
|
95
96
|
- examples/sample_command.rb
|
96
97
|
- lib/subcommand_optparse.rb
|
97
98
|
- lib/subcommand_optparse/version.rb
|
99
|
+
- spec/spec_helper.rb
|
100
|
+
- spec/subcommand_optparse_spec.rb
|
98
101
|
- subcommand-optparse.gemspec
|
99
102
|
homepage: ''
|
100
103
|
licenses:
|
@@ -106,20 +109,22 @@ require_paths:
|
|
106
109
|
- lib
|
107
110
|
required_ruby_version: !ruby/object:Gem::Requirement
|
108
111
|
requirements:
|
109
|
-
- -
|
112
|
+
- - ">="
|
110
113
|
- !ruby/object:Gem::Version
|
111
114
|
version: '0'
|
112
115
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
113
116
|
requirements:
|
114
|
-
- -
|
117
|
+
- - ">="
|
115
118
|
- !ruby/object:Gem::Version
|
116
119
|
version: '0'
|
117
120
|
requirements: []
|
118
121
|
rubyforge_project:
|
119
|
-
rubygems_version: 2.
|
122
|
+
rubygems_version: 2.1.11
|
120
123
|
signing_key:
|
121
124
|
specification_version: 4
|
122
125
|
summary: Option parser for a command with subcommands, which is parsed by library
|
123
126
|
'optparse'
|
124
|
-
test_files:
|
127
|
+
test_files:
|
128
|
+
- spec/spec_helper.rb
|
129
|
+
- spec/subcommand_optparse_spec.rb
|
125
130
|
has_rdoc:
|