luban-cli 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -22
- data/README.md +64 -8
- data/lib/luban/cli/base/core.rb +7 -2
- data/lib/luban/cli/base/dsl.rb +3 -1
- data/lib/luban/cli/command.rb +1 -1
- data/lib/luban/cli/commands.rb +28 -11
- 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: 5cefeb5c04a0122c4ddbcfe60ec89f10fa448986
|
4
|
+
data.tar.gz: 63308ba45f262576aa6208d7017accbbefcc71fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9783ade21c7ca9ae041262c692730fd3db7fe6cd8eaa880ff910568d57729a88688c5583edbb297b6996797d4d04deb88e7231551e9686e189d2339a0904539
|
7
|
+
data.tar.gz: a3724c927f17da7c1933b69ccd82e06371c982040bf8e7840f6cf569049974373ec4961551afe7d49d0f405715da63748fa5ca206242bf989914117b6067500f
|
data/CHANGELOG.md
CHANGED
@@ -1,26 +1,24 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
-
## Version 0.
|
3
|
+
## Version 0.3.2 (Apr 28, 2015)
|
4
4
|
|
5
|
-
|
5
|
+
Minor enhancements:
|
6
|
+
* Add use_commands DSL to inject command definitions to a given Luban app or command
|
7
|
+
* Add an example to demonstrate command injection
|
6
8
|
|
7
|
-
|
8
|
-
*
|
9
|
-
|
10
|
-
* Support switches (boolean options)
|
11
|
-
* Support arguments
|
12
|
-
* Support subcommand
|
13
|
-
* Provide base class (Luban::CLI::Base) for command-line application
|
9
|
+
Bug fixes:
|
10
|
+
* Add validation to help command
|
11
|
+
* Command dispatching within the correct context
|
14
12
|
|
15
|
-
## Version 0.
|
13
|
+
## Version 0.3.1 (Apr 15, 2015)
|
16
14
|
|
17
15
|
Minor enhancements:
|
18
|
-
*
|
19
|
-
*
|
20
|
-
*
|
21
|
-
|
22
|
-
|
23
|
-
*
|
16
|
+
* Simplify keyword arguments for dispatch_command and action handler
|
17
|
+
* Include command chain as part of action method name for commands
|
18
|
+
* Enrich README with more documentation
|
19
|
+
|
20
|
+
Bug fixes:
|
21
|
+
* Handle validation for multiple values correctly
|
24
22
|
|
25
23
|
## Version 0.3.0 (Apr 11, 2015)
|
26
24
|
|
@@ -40,12 +38,24 @@ Bug fixes:
|
|
40
38
|
* Dispatch command under the right class context
|
41
39
|
* Show correct command chain between program name and synopsis when composing parser banner
|
42
40
|
|
43
|
-
## Version 0.
|
41
|
+
## Version 0.2.0 (Apr 02, 2015)
|
44
42
|
|
45
43
|
Minor enhancements:
|
46
|
-
*
|
47
|
-
*
|
48
|
-
*
|
44
|
+
* Refactor error class
|
45
|
+
* Refactor argument validation
|
46
|
+
* Validate required options/arguments in Luban::CLI::Base
|
47
|
+
* Create singleton action handler method on application instance
|
48
|
+
* Move parse error handling to action handler
|
49
|
+
* Exclude examples and spec from the gem itself
|
49
50
|
|
50
|
-
|
51
|
-
|
51
|
+
## Version 0.1.0 (Mar 31, 2015)
|
52
|
+
|
53
|
+
Bootstrapped Luban::CLI
|
54
|
+
|
55
|
+
New features:
|
56
|
+
* Support general command-line parsing
|
57
|
+
* Support options
|
58
|
+
* Support switches (boolean options)
|
59
|
+
* Support arguments
|
60
|
+
* Support subcommand
|
61
|
+
* Provide base class (Luban::CLI::Base) for command-line application
|
data/README.md
CHANGED
@@ -180,13 +180,13 @@ Invalid value of argument AGE: 90 (Luban::CLI::Argument::InvalidArgumentValue)
|
|
180
180
|
... ...
|
181
181
|
|
182
182
|
$ ruby my_app.rb john male 30 2
|
183
|
-
{:
|
183
|
+
{:args=>{:name=>"john", :gender=>:male, :age=>30, :level=>2, :email=>nil}, :opts=>{:help=>false}}
|
184
184
|
|
185
185
|
$ ruby my_app.rb john male 30 2 john@company.com
|
186
|
-
{:
|
186
|
+
{:args=>{:name=>"john", :gender=>:male, :age=>30, :level=>2, :email=>["john@company.com"]}, :opts=>{:help=>false}}
|
187
187
|
|
188
188
|
$ ruby my_app.rb john male 30 2 john@company.com john@personal.com
|
189
|
-
{:
|
189
|
+
{:args=>{:name=>"john", :gender=>:male, :age=>30, :level=>2, :email=>["john@company.com", "john@personal.com"]}, :opts=>{:help=>false}}
|
190
190
|
```
|
191
191
|
|
192
192
|
### option
|
@@ -222,10 +222,10 @@ MyApp.new.run
|
|
222
222
|
|
223
223
|
```
|
224
224
|
$ ruby my_app.rb --require bundler
|
225
|
-
{:
|
225
|
+
{:args=>{}, :opts=>{:libraries=>["bundler"], :help=>false}}
|
226
226
|
|
227
227
|
$ ruby my_app.rb -r bundler,rails
|
228
|
-
{:
|
228
|
+
{:args=>{}, :opts=>{:libraries=>["bundler", "rails"], :help=>false}}
|
229
229
|
```
|
230
230
|
|
231
231
|
Occassionally an option might take an optional argument, e.g. --inplace [EXTENSION]. This kind of option is called nullable option. The nullable option is set to true if the optional argument is not provided; otherwise, the value of the option is set to the value of the argument. To declare a nullable option, you can explicitly turn off nullable modifier which is off by default.
|
@@ -248,13 +248,13 @@ MyApp.new.run
|
|
248
248
|
|
249
249
|
```
|
250
250
|
$ ruby my_app.rb
|
251
|
-
{:
|
251
|
+
{:args=>{}, :opts=>{:inplace=>nil, :help=>false}}
|
252
252
|
|
253
253
|
$ ruby my_app.rb --inplace
|
254
|
-
{:
|
254
|
+
{:args=>{}, :opts=>{:inplace=>true, :help=>false}}
|
255
255
|
|
256
256
|
$ ruby my_app.rb --inplace .bak
|
257
|
-
{:
|
257
|
+
{:args=>{}, :opts=>{:inplace=>".bak", :help=>false}}
|
258
258
|
```
|
259
259
|
|
260
260
|
### switch
|
@@ -449,6 +449,62 @@ end
|
|
449
449
|
|
450
450
|
DSL method #auto_help_command is used to define a command to list all commands or help for one command. Under rare circumstances that you need to customize the help command (i.e., use a different command name like :manual), you can use DSL method #help_command which accepts the same parameters that for #command.
|
451
451
|
|
452
|
+
### Command injection
|
453
|
+
|
454
|
+
Commands can be defined directly within the Luban app class like examples shown in the previous sections. In addition, commands can be defined separately and injected into a given Luban app later. Command definition can be also namespaced by using module. With this feature, commands can be designed in a more re-usable and scalable way. This feature also implies that Luban CLI application supports namespaced commands.
|
455
|
+
|
456
|
+
Below is an example demonstrating how command injection is supposed to work.
|
457
|
+
|
458
|
+
```ruby
|
459
|
+
module App
|
460
|
+
module ControlTasks
|
461
|
+
class Task1Command < Luban::CLI::Command
|
462
|
+
configure do
|
463
|
+
... ...
|
464
|
+
end
|
465
|
+
end
|
466
|
+
|
467
|
+
class Task2Command < Luban::CLI::Command
|
468
|
+
configure do
|
469
|
+
... ...
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
class MyApp < Luban::CLI::Application
|
476
|
+
configure do
|
477
|
+
... ...
|
478
|
+
end
|
479
|
+
|
480
|
+
# Inject Luban commands directly defined under the given module
|
481
|
+
use_commands 'app:control_tasks'
|
482
|
+
|
483
|
+
# Alternatively, commands can be injected individually
|
484
|
+
# The following has the same effect
|
485
|
+
# command 'app:control_tasks:task1'
|
486
|
+
# command 'app:control_tasks:task2'
|
487
|
+
end
|
488
|
+
```
|
489
|
+
|
490
|
+
```
|
491
|
+
$ ruby my_app.rb app:control_tasks:task1
|
492
|
+
|
493
|
+
$ ruby my_app.rb app:control_tasks:task2
|
494
|
+
```
|
495
|
+
|
496
|
+
As shown above, there are a few naming conventions about the command class naming and injection:
|
497
|
+
|
498
|
+
* Command class should has suffix "Command"
|
499
|
+
* For instances, Task1Command, Task2Command
|
500
|
+
* Module name to be injected should be fully qualified
|
501
|
+
* namespaces/modules should be in snake case and
|
502
|
+
* Separated by colon as the delimiter
|
503
|
+
* For instances, 'app:control_tasks'
|
504
|
+
* Alternatively, commands can be injected individually
|
505
|
+
* Command name should be fully qualified
|
506
|
+
* Suffix "Command" is no more needed
|
507
|
+
|
452
508
|
## Applications
|
453
509
|
|
454
510
|
Luban::CLI provides a base class for cli application, Luban::CLI::Application. You can define your own cli application by inheriting it as examples shown in the previous sections.
|
data/lib/luban/cli/base/core.rb
CHANGED
@@ -61,7 +61,7 @@ module Luban
|
|
61
61
|
def default_prefix; ''; end
|
62
62
|
|
63
63
|
def action_method
|
64
|
-
@action_method ||= "#{@prefix}#{@action_name}"
|
64
|
+
@action_method ||= "#{@prefix}#{@action_name.to_s.gsub(':', '_')}"
|
65
65
|
end
|
66
66
|
|
67
67
|
def parser
|
@@ -94,7 +94,12 @@ module Luban
|
|
94
94
|
|
95
95
|
def dispatch_command(context, cmd:, argv:)
|
96
96
|
validate_command(cmd)
|
97
|
-
|
97
|
+
cmd_method = commands[cmd].action_method
|
98
|
+
if respond_to?(cmd_method)
|
99
|
+
send(cmd_method, argv)
|
100
|
+
else
|
101
|
+
context.send(cmd_method, argv)
|
102
|
+
end
|
98
103
|
end
|
99
104
|
|
100
105
|
def validate_command(cmd)
|
data/lib/luban/cli/base/dsl.rb
CHANGED
@@ -12,10 +12,12 @@ module Luban
|
|
12
12
|
if block_given?
|
13
13
|
command(**opts, &blk)
|
14
14
|
else
|
15
|
+
validator = method(:has_command?)
|
15
16
|
command(:help, **opts) do
|
16
17
|
desc "List all commands or help for one command"
|
17
18
|
argument :command, "Command to help for",
|
18
|
-
type: :symbol, required: false
|
19
|
+
type: :symbol, required: false,
|
20
|
+
assure: validator
|
19
21
|
action :show_help_for_command
|
20
22
|
end
|
21
23
|
end
|
data/lib/luban/cli/command.rb
CHANGED
@@ -13,7 +13,7 @@ module Luban
|
|
13
13
|
def default_prefix; '__command_'; end
|
14
14
|
|
15
15
|
def action_method
|
16
|
-
@action_method ||= "#{@prefix}#{command_chain.map(&:to_s).join('_')}"
|
16
|
+
@action_method ||= "#{@prefix}#{command_chain.map(&:to_s).join('_').gsub(':', '_')}"
|
17
17
|
end
|
18
18
|
|
19
19
|
protected
|
data/lib/luban/cli/commands.rb
CHANGED
@@ -18,6 +18,31 @@ module Luban
|
|
18
18
|
def has_commands?
|
19
19
|
!commands.empty?
|
20
20
|
end
|
21
|
+
|
22
|
+
def use_commands(mod_name)
|
23
|
+
mod_class = Kernel.const_get(camelcase(mod_name.to_s))
|
24
|
+
mod_class.constants.map { |c| mod_class.const_get(c) }.each do |c|
|
25
|
+
command(snakecase(c.name.sub(/Command$/, ''))) if c < Luban::CLI::Command
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def camelcase(str)
|
32
|
+
str = str.to_s.dup
|
33
|
+
str.gsub!(/\:(.?)/){ "::#{$1.upcase}" }
|
34
|
+
str.gsub!(/(?:_+|-+)([a-z])/){ $1.upcase }
|
35
|
+
str.gsub!(/(\A|\s)([a-z])/){ $1 + $2.upcase }
|
36
|
+
str
|
37
|
+
end
|
38
|
+
|
39
|
+
def snakecase(str)
|
40
|
+
str.gsub(/::/, ':').
|
41
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
42
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
43
|
+
tr("-", "_").
|
44
|
+
downcase
|
45
|
+
end
|
21
46
|
end
|
22
47
|
|
23
48
|
module ClassMethods
|
@@ -28,10 +53,11 @@ module Luban
|
|
28
53
|
end
|
29
54
|
|
30
55
|
def command_class(cmd)
|
31
|
-
"#{
|
56
|
+
"#{camelcase(cmd)}Command"
|
32
57
|
end
|
33
58
|
|
34
59
|
def command(app = self, cmd, **opts, &blk)
|
60
|
+
cmd = cmd.to_sym
|
35
61
|
cmd_class = command_class(cmd)
|
36
62
|
klass = if self.const_defined?(command_class(cmd))
|
37
63
|
self.const_get(command_class(cmd))
|
@@ -44,16 +70,6 @@ module Luban
|
|
44
70
|
def undef_command(cmd)
|
45
71
|
undef_method(commands.delete(cmd).action_method)
|
46
72
|
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
|
56
|
-
end
|
57
73
|
end
|
58
74
|
|
59
75
|
module InstanceMethods
|
@@ -64,6 +80,7 @@ module Luban
|
|
64
80
|
end
|
65
81
|
|
66
82
|
def command(cmd, **opts, &blk)
|
83
|
+
cmd = cmd.to_sym
|
67
84
|
if self.is_a?(Command)
|
68
85
|
opts[:command_chain] = self.command_chain.clone.push(cmd)
|
69
86
|
self.class.command(self.app, cmd, **opts, &blk)
|
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.3.
|
4
|
+
version: 0.3.2
|
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-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|