luban-cli 0.3.1 → 0.3.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/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
|