luban-cli 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -3
- data/lib/luban/cli/application.rb +2 -2
- data/lib/luban/cli/base/core.rb +17 -13
- data/lib/luban/cli/base/dsl.rb +34 -19
- data/lib/luban/cli/command.rb +7 -3
- data/lib/luban/cli/commands.rb +43 -27
- data/lib/luban/cli/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad584f0174c5361200ed88f252387ac294ff8768
|
4
|
+
data.tar.gz: 9af48be33bc18fa6d049780354d0a6dc3abb34fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 932c919d74edc1e23cc4a45fe10240913603864aa25cf71a24b76e0a542da0a54296d20348fb5f7dc5c645b1b143e3557d897a6fbaf36df2ae88b5a0ba1bd400
|
7
|
+
data.tar.gz: 889e415204354c2c6db2440e1297fb52a85e4f59a0d662707c3bc404066eeb835c592b156fc3594bb35562c9db64f463504b2ab3bb1ebd97934de4a0e0b465b1
|
data/CHANGELOG.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
Bootstrapped Luban::CLI
|
6
6
|
|
7
|
-
|
7
|
+
New features:
|
8
8
|
* Support general command-line parsing
|
9
9
|
* Support options
|
10
10
|
* Support switches (boolean options)
|
@@ -15,9 +15,27 @@ Features:
|
|
15
15
|
## Version 0.2.0 (Apr 02, 2015)
|
16
16
|
|
17
17
|
Minor enhancements:
|
18
|
-
*
|
19
|
-
*
|
18
|
+
* Refactor error class
|
19
|
+
* Refactor argument validation
|
20
20
|
* Validate required options/arguments in Luban::CLI::Base
|
21
21
|
* Create singleton action handler method on application instance
|
22
22
|
* Move parse error handling to action handler
|
23
23
|
* Exclude examples and spec from the gem itself
|
24
|
+
|
25
|
+
## Version 0.3.0 (Apr 11, 2015)
|
26
|
+
|
27
|
+
New features:
|
28
|
+
* Support prefix for action name
|
29
|
+
* By default, subcommand method is prefixed with "__command_"
|
30
|
+
* By default, application action method has no prefix
|
31
|
+
* Support nested subcommands
|
32
|
+
* Add help option by default in Luban::CLI::Base in order to turn on auto help by default
|
33
|
+
|
34
|
+
Minor enhancements:
|
35
|
+
* Refactor action creation to be more readable
|
36
|
+
* Add an example for subcommands and nested subcommands
|
37
|
+
|
38
|
+
Bug fixes:
|
39
|
+
* Apply the correct method creator when defining action method
|
40
|
+
* Dispatch command under the right class context
|
41
|
+
* Show correct command chain between program name and synopsis when composing parser banner
|
@@ -5,8 +5,8 @@ module Luban
|
|
5
5
|
class Application < Base
|
6
6
|
attr_reader :rc
|
7
7
|
|
8
|
-
def initialize(
|
9
|
-
super(self,
|
8
|
+
def initialize(action_name = :run, **opts, &config_blk)
|
9
|
+
super(self, action_name, **opts, &config_blk)
|
10
10
|
@rc = init_rc
|
11
11
|
validate
|
12
12
|
end
|
data/lib/luban/cli/base/core.rb
CHANGED
@@ -19,6 +19,9 @@ module Luban
|
|
19
19
|
DefaultSummaryIndent = 4
|
20
20
|
DefaultTitleIndent = 2
|
21
21
|
|
22
|
+
attr_reader :app
|
23
|
+
attr_reader :prefix
|
24
|
+
attr_reader :action_method
|
22
25
|
attr_reader :program_name
|
23
26
|
attr_reader :options
|
24
27
|
attr_reader :arguments
|
@@ -32,9 +35,11 @@ module Luban
|
|
32
35
|
attr_accessor :summary_width
|
33
36
|
attr_accessor :summary_indent
|
34
37
|
|
35
|
-
def initialize(app,
|
38
|
+
def initialize(app, action_name, prefix: default_prefix, auto_help: true, &config_blk)
|
36
39
|
@app = app
|
37
|
-
@
|
40
|
+
@action_name = action_name
|
41
|
+
@prefix = prefix
|
42
|
+
@action_method = "#{@prefix}#{@action_name}"
|
38
43
|
@action_defined = false
|
39
44
|
|
40
45
|
@program_name = default_program_name
|
@@ -51,9 +56,12 @@ module Luban
|
|
51
56
|
@summary_indent = DefaultSummaryIndent
|
52
57
|
|
53
58
|
configure(&config_blk)
|
54
|
-
|
59
|
+
setup_default_action unless @action_defined
|
60
|
+
self.auto_help if auto_help
|
55
61
|
end
|
56
62
|
|
63
|
+
def default_prefix; ''; end
|
64
|
+
|
57
65
|
def parser
|
58
66
|
@parser ||= create_parser
|
59
67
|
end
|
@@ -75,20 +83,16 @@ module Luban
|
|
75
83
|
instance_eval(&config_blk) unless config_blk.nil?
|
76
84
|
end
|
77
85
|
|
78
|
-
def
|
79
|
-
method = @
|
80
|
-
|
81
|
-
|
82
|
-
else
|
83
|
-
action do |**opts|
|
84
|
-
raise NotImplementedError, "#{self.class.name}##{method} is an abstract method."
|
85
|
-
end
|
86
|
+
def setup_default_action
|
87
|
+
method = @action_method
|
88
|
+
action do |**opts|
|
89
|
+
raise NotImplementedError, "#{self.class.name}##{method} is an abstract method."
|
86
90
|
end
|
87
91
|
end
|
88
92
|
|
89
|
-
def dispatch_command(cmd:, argv:, **params)
|
93
|
+
def dispatch_command(context, cmd:, argv:, **params)
|
90
94
|
validate_command(cmd)
|
91
|
-
send(cmd, argv)
|
95
|
+
context.send(commands[cmd].action_method, argv)
|
92
96
|
end
|
93
97
|
|
94
98
|
def validate_command(cmd)
|
data/lib/luban/cli/base/dsl.rb
CHANGED
@@ -8,15 +8,14 @@ module Luban
|
|
8
8
|
|
9
9
|
def configure(&blk); @config_blk = blk; end
|
10
10
|
|
11
|
-
def help_command(
|
11
|
+
def help_command(**opts, &blk)
|
12
12
|
if block_given?
|
13
|
-
command(
|
13
|
+
command(**opts, &blk)
|
14
14
|
else
|
15
|
-
command(:help) do
|
15
|
+
command(:help, **opts) do
|
16
16
|
desc "List all commands or help for one command"
|
17
17
|
argument :command, "Command to help for",
|
18
18
|
type: :symbol, required: false
|
19
|
-
self.auto_help if auto_help
|
20
19
|
action :show_help_for_command
|
21
20
|
end
|
22
21
|
end
|
@@ -99,29 +98,45 @@ module Luban
|
|
99
98
|
blk
|
100
99
|
end
|
101
100
|
if handler.nil?
|
102
|
-
raise ArgumentError, "Code block to execute command #{@
|
101
|
+
raise ArgumentError, "Code block to execute command #{@action_name} is MISSING."
|
103
102
|
end
|
104
103
|
_base = self
|
105
104
|
parse_method = preserve_argv ? :parse : :parse!
|
106
|
-
|
107
|
-
_base.send(parse_method, argv)
|
108
|
-
|
109
|
-
if _base.result[:opts][:help]
|
110
|
-
_base.show_help
|
111
|
-
elsif _base.result[:opts][:version]
|
112
|
-
_base.show_version
|
113
|
-
else
|
114
|
-
_base.validate_required_options
|
115
|
-
_base.validate_required_arguments
|
116
|
-
instance_exec(**_base.result, &handler)
|
117
|
-
end
|
118
|
-
rescue OptionParser::ParseError, Error => e
|
119
|
-
_base.on_parse_error(e)
|
105
|
+
define_action_method do |argv = _base.default_argv|
|
106
|
+
_base.send(:process, self, parse_method, argv) do |result|
|
107
|
+
instance_exec(**result, &handler)
|
120
108
|
end
|
121
109
|
end
|
122
110
|
@action_defined = true
|
123
111
|
end
|
124
112
|
|
113
|
+
def define_action_method(&action_blk)
|
114
|
+
@app.send(method_creator, action_method, &action_blk)
|
115
|
+
end
|
116
|
+
|
117
|
+
def method_creator
|
118
|
+
@method_creator ||= @app.is_a?(Class) ? :define_method : :define_singleton_method
|
119
|
+
end
|
120
|
+
|
121
|
+
def process(context, parse_method, argv)
|
122
|
+
send(parse_method, argv)
|
123
|
+
if result[:opts][:help]
|
124
|
+
show_help
|
125
|
+
elsif result[:opts][:version]
|
126
|
+
show_version
|
127
|
+
else
|
128
|
+
if has_commands?
|
129
|
+
dispatch_command(context, **result)
|
130
|
+
else
|
131
|
+
validate_required_options
|
132
|
+
validate_required_arguments
|
133
|
+
yield result
|
134
|
+
end
|
135
|
+
end
|
136
|
+
rescue OptionParser::ParseError, Error => e
|
137
|
+
on_parse_error(e)
|
138
|
+
end
|
139
|
+
|
125
140
|
def on_parse_error(error)
|
126
141
|
show_error_and_exit(error)
|
127
142
|
end
|
data/lib/luban/cli/command.rb
CHANGED
@@ -2,16 +2,20 @@ module Luban
|
|
2
2
|
module CLI
|
3
3
|
class Command < Base
|
4
4
|
attr_reader :name
|
5
|
+
attr_reader :command_chain
|
5
6
|
|
6
|
-
def initialize(app, name, &config_blk)
|
7
|
-
super
|
7
|
+
def initialize(app, name, command_chain: [name], **opts, &config_blk)
|
8
8
|
@name = name
|
9
|
+
@command_chain = command_chain
|
10
|
+
super(app, name, **opts, &config_blk)
|
9
11
|
end
|
10
12
|
|
13
|
+
def default_prefix; '__command_'; end
|
14
|
+
|
11
15
|
protected
|
12
16
|
|
13
17
|
def compose_banner
|
14
|
-
"Usage: #{program_name} #{
|
18
|
+
"Usage: #{program_name} #{command_chain.map(&:to_s).join(' ')} #{compose_synopsis}"
|
15
19
|
end
|
16
20
|
end
|
17
21
|
end
|
data/lib/luban/cli/commands.rb
CHANGED
@@ -6,21 +6,7 @@ module Luban
|
|
6
6
|
base.send(:include, InstanceMethods)
|
7
7
|
end
|
8
8
|
|
9
|
-
module
|
10
|
-
def inherited(subclass)
|
11
|
-
# Ensure commands from base class
|
12
|
-
# got inherited to its subclasses
|
13
|
-
subclass.instance_variable_set(
|
14
|
-
'@commands',
|
15
|
-
Marshal.load(Marshal.dump(instance_variable_get('@commands')))
|
16
|
-
)
|
17
|
-
super
|
18
|
-
end
|
19
|
-
|
20
|
-
def commands
|
21
|
-
@commands ||= {}
|
22
|
-
end
|
23
|
-
|
9
|
+
module CommonMethods
|
24
10
|
def list_commands
|
25
11
|
commands.keys
|
26
12
|
end
|
@@ -32,32 +18,62 @@ module Luban
|
|
32
18
|
def has_commands?
|
33
19
|
!commands.empty?
|
34
20
|
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
include CommonMethods
|
25
|
+
|
26
|
+
def commands
|
27
|
+
@commands ||= {}
|
28
|
+
end
|
35
29
|
|
36
|
-
def
|
37
|
-
|
30
|
+
def command_class(cmd)
|
31
|
+
"#{classify(cmd)}Command"
|
32
|
+
end
|
33
|
+
|
34
|
+
def command(app = self, cmd, **opts, &blk)
|
35
|
+
cmd_class = command_class(cmd)
|
36
|
+
klass = if self.const_defined?(command_class(cmd))
|
37
|
+
self.const_get(command_class(cmd))
|
38
|
+
else
|
39
|
+
self.const_set(command_class(cmd), Class.new(Command))
|
40
|
+
end
|
41
|
+
commands[cmd] = klass.new(app, cmd, **opts, &blk)
|
38
42
|
end
|
39
43
|
|
40
44
|
def undef_command(cmd)
|
41
|
-
commands.delete(cmd)
|
42
|
-
|
45
|
+
undef_method(commands.delete(cmd).action_method)
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
|
50
|
+
def classify(cmd)
|
51
|
+
cmd = cmd.to_s.dup
|
52
|
+
cmd.gsub!(/\/(.?)/){ "::#{$1.upcase}" }
|
53
|
+
cmd.gsub!(/(?:_+|-+)([a-z])/){ $1.upcase }
|
54
|
+
cmd.gsub!(/(\A|\s)([a-z])/){ $1 + $2.upcase }
|
55
|
+
cmd
|
43
56
|
end
|
44
57
|
end
|
45
58
|
|
46
59
|
module InstanceMethods
|
60
|
+
include CommonMethods
|
61
|
+
|
47
62
|
def commands
|
48
63
|
self.class.commands
|
49
64
|
end
|
50
65
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
66
|
+
def command(cmd, **opts, &blk)
|
67
|
+
if self.is_a?(Command)
|
68
|
+
opts[:command_chain] = self.command_chain.clone.push(cmd)
|
69
|
+
self.class.command(self.app, cmd, **opts, &blk)
|
70
|
+
else
|
71
|
+
self.class.command(cmd, **opts, &blk)
|
72
|
+
end
|
57
73
|
end
|
58
74
|
|
59
|
-
def
|
60
|
-
self.class.
|
75
|
+
def undef_command(cmd)
|
76
|
+
self.class.undef_command(cmd)
|
61
77
|
end
|
62
78
|
end
|
63
79
|
end
|
data/lib/luban/cli/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: luban-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rubyist Chi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|