dencli 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.
- checksums.yaml +4 -4
- data/bin/example.rb +13 -5
- data/lib/dencli/cmd.rb +73 -43
- data/lib/dencli/sub.rb +64 -8
- data/lib/dencli/version.rb +1 -1
- data/lib/dencli.rb +16 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b59309b03abb2d1a44eda112c289335eed1a252bccd89404a4e5017ff876657f
|
4
|
+
data.tar.gz: 0ecfaff2dd2928bfdc134ee3dc92737ae2776737e6ada66fd1432de5b470ab76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d27d7f9d307e1e86684ebb7e771ff865d0d10e4cde501951947997e98d25aafff123826c1973e7615ab45edd7c2bd3d60eacefa56835eacd976a4e9a9f4ed2d8
|
7
|
+
data.tar.gz: 70f63e628dcd9b7c2cc8da2302ef0dc33a170efc6281173c05f31b09657c0f4b616cd71faaa3ea09738e629b021e51e6018fda33535d2d34d8570caa0db32acc
|
data/bin/example.rb
CHANGED
@@ -5,15 +5,23 @@ $:.unshift Pathname.new(__FILE__).dirname.dirname.join('lib').to_s
|
|
5
5
|
require 'dencli'
|
6
6
|
|
7
7
|
cli = DenCli.new 'example', "This is an example for generate a DenCli-API"
|
8
|
-
cli.cmd( :example, "I have an example command") { STDERR.puts "This is an example" }
|
9
|
-
cli.cmd( :help, "", aliases: [nil, '-h', '--help']) {|*args| STDERR.puts cli.help(*args) }
|
10
|
-
|
11
8
|
cli.cmd( :args, "Expects and prints given arguments", &lambda {|a, b, c:, d:, e:|
|
12
9
|
p a: a, b: b, c: c, d: d, e: e
|
13
10
|
}).
|
14
11
|
opt( :c, '-c=ForC', "Option c").
|
15
12
|
opt( :d, '-d=ForD', "Option d", default: "something").
|
16
|
-
opt( :e, '-e', "Toggle e", default: false)
|
13
|
+
opt( :e, '-e', "Toggle e", default: false).
|
14
|
+
opt( :f, '--[no-]f', "Toggle f", default: false)
|
15
|
+
|
16
|
+
cli.cmd( :example, "I have an example command") { STDERR.puts "This is an example" }
|
17
|
+
cli.cmd( :help, "", aliases: [nil, '-h', '--help'], &lambda {|*args, full:|
|
18
|
+
if full
|
19
|
+
cli.help_full *args, output: STDERR
|
20
|
+
else
|
21
|
+
cli.help *args, output: STDERR
|
22
|
+
end
|
23
|
+
}).
|
24
|
+
opt( :full, '-f', '--[no-]full', "Print all commands and sub-commands.", default: false)
|
17
25
|
|
18
26
|
cli.sub( :more, "Sub-Commands are also possible with a new cli") do |sub|
|
19
27
|
sub.cmd( :help, "", aliases: [nil, '-h', '--help']) {|*args| STDERR.puts sub.help(*args) }
|
@@ -29,7 +37,7 @@ cli.sub( :more, "Sub-Commands are also possible with a new cli") do |sub|
|
|
29
37
|
opt( :e, '-e', "Toggle e")
|
30
38
|
|
31
39
|
sub.sub( :deeper, "You want to have Sub-Sub-Commands?") do |sub2|
|
32
|
-
sub2.cmd( :help, "", aliases: [nil, '-h', '--help'], &lambda {|*args|
|
40
|
+
sub2.cmd( :help, "", aliases: [nil, '-h', '--help'], &lambda {|*args| sub2.help( *args, output: STDERR) })
|
33
41
|
sub2.cmd( :last, "The last example", &lambda { STDERR.puts "The last example" })
|
34
42
|
|
35
43
|
sub2.sub( :'sub-commands', "Endless Sub-Sub- ...") do |sub3|
|
data/lib/dencli/cmd.rb
CHANGED
@@ -23,10 +23,11 @@ class DenCli::CMD
|
|
23
23
|
def options_required() @exe.parameters.select {|e| :keyreq == e[0] }.map {|e| e[1] } end
|
24
24
|
def options_additional() @exe.parameters.select {|e| :key == e[0] }.map {|e| e[1] } end
|
25
25
|
|
26
|
-
def
|
27
|
-
|
26
|
+
def complete *pre, str
|
27
|
+
@completion.call *pre, str
|
28
|
+
end
|
28
29
|
|
29
|
-
def call
|
30
|
+
def call *as
|
30
31
|
os = {}
|
31
32
|
unless @options.empty?
|
32
33
|
# options like --abc | -x will be provided in os
|
@@ -53,25 +54,58 @@ class DenCli::CMD
|
|
53
54
|
end
|
54
55
|
kr = @options.select {|_, o| o.required? and not os.has_key? o.name }
|
55
56
|
unless kr.empty?
|
56
|
-
raise DenCli::UsageError, "Missing argument(s): #{kr.map {|o| o.
|
57
|
+
raise DenCli::UsageError, "Missing argument(s): #{kr.map {|o| o.long || o.short }.join ', '}"
|
57
58
|
end
|
58
59
|
end
|
59
60
|
@exe.call *as, **os
|
60
61
|
end
|
61
62
|
|
62
|
-
def usage
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
63
|
+
def usage output: nil
|
64
|
+
output ||= ''
|
65
|
+
_usage output
|
66
|
+
output
|
67
|
+
end
|
68
|
+
|
69
|
+
def _usage output
|
70
|
+
output << full_cmd.join( ' ')
|
71
|
+
@options.each do |_, o|
|
72
|
+
s = "#{o.short||o.long}#{o.val ? ?= : ''}#{o.val}"
|
73
|
+
output << (o.required? ? " #{s}" : " [#{s}]")
|
74
|
+
end
|
75
|
+
if @exe.lambda?
|
76
|
+
required.each {|s| output << " <#{s}>" }
|
77
|
+
output << " [#{additional.map{|s|"<#{s}>"}.join " "}]" unless additional.empty?
|
78
|
+
else
|
79
|
+
output << ' ...'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def commands *args, &exe
|
84
|
+
yield self
|
72
85
|
end
|
73
86
|
|
74
|
-
def
|
87
|
+
def goto *args
|
88
|
+
self
|
89
|
+
end
|
90
|
+
|
91
|
+
def help output: nil
|
92
|
+
output ||= ''
|
93
|
+
_help output
|
94
|
+
output
|
95
|
+
end
|
96
|
+
|
97
|
+
def _help output
|
98
|
+
output << "Usage: #{usage}\n#{description}\n"
|
99
|
+
_help_options output
|
100
|
+
end
|
101
|
+
|
102
|
+
def help_options output: nil
|
103
|
+
output ||= ''
|
104
|
+
_help_options output
|
105
|
+
output
|
106
|
+
end
|
107
|
+
|
108
|
+
def _help_options output
|
75
109
|
sc, lc, dc = 0, 0, 0
|
76
110
|
@options.each do |_, o|
|
77
111
|
s = o.short&.length || 0
|
@@ -89,8 +123,8 @@ class DenCli::CMD
|
|
89
123
|
end
|
90
124
|
dc = d if dc < d
|
91
125
|
end
|
92
|
-
format = " %-#{sc}s%s %-#{lc}s %s"
|
93
|
-
@options.map
|
126
|
+
format = " %-#{sc}s%s %-#{lc}s %s\n"
|
127
|
+
@options.map do |_, o|
|
94
128
|
s, l, v, y = o.short, o.long, o.val, ','
|
95
129
|
if l.nil?
|
96
130
|
s += "=#{v}" if v
|
@@ -101,8 +135,8 @@ class DenCli::CMD
|
|
101
135
|
end
|
102
136
|
d = o.desc || ''
|
103
137
|
d += " (#{o.default})" if o.default?
|
104
|
-
format % [ s, y, l, d ]
|
105
|
-
|
138
|
+
output << format % [ s, y, l, d ]
|
139
|
+
end
|
106
140
|
end
|
107
141
|
|
108
142
|
def completion &exe
|
@@ -116,34 +150,29 @@ class DenCli::CMD
|
|
116
150
|
def default?() NilClass != @default end
|
117
151
|
def default() NilClass == @default ? nil : @default end
|
118
152
|
|
119
|
-
def
|
120
|
-
long = short = val = nil
|
153
|
+
def parse_opt_string opt
|
121
154
|
case opt
|
122
|
-
when /\A(
|
123
|
-
long, val = $1,
|
124
|
-
when /\A(--[
|
125
|
-
long, val = $1,
|
155
|
+
when /\A(--\[no-\][^=]+)\z/
|
156
|
+
@long, @val = $1, nil
|
157
|
+
when /\A(--[^=]+)=(.+)\z/
|
158
|
+
@long, @val = $1, $2 || @val
|
159
|
+
when /\A(--[^=]+)\z/
|
160
|
+
@long, @val = $1, nil
|
126
161
|
when /\A(-[^=-]+)=(.+)\z/
|
127
|
-
short, val = $1, $2
|
162
|
+
@short, @val = $1, $2 || @val
|
128
163
|
when /\A(-[^=-]+)\z/
|
129
|
-
short, val = $1, nil
|
130
|
-
else
|
131
|
-
|
132
|
-
alts.each do |alt|
|
133
|
-
case alt
|
134
|
-
when /\A(--[^=-]+)=(.+)\z/
|
135
|
-
long, val = $1, val || $2
|
136
|
-
when /\A(--[^=-]+)\z/
|
137
|
-
long, val = $1, nil
|
138
|
-
when /\A(-[^=-]+)=(.+)\z/
|
139
|
-
short, val = $1, val || $2
|
140
|
-
when /\A(-[^=-]+)\z/
|
141
|
-
short, val = $1, nil
|
142
|
-
else raise ArgumentError, "Unexpected format for option: #{alt.inspect}"
|
143
|
-
end
|
164
|
+
@short, @val = $1, nil
|
165
|
+
else
|
166
|
+
raise ArgumentError, "Unexpected format for option: #{opt.inspect}"
|
144
167
|
end
|
145
|
-
|
146
|
-
|
168
|
+
end
|
169
|
+
private :parse_opt_string
|
170
|
+
|
171
|
+
def initialize cmd, name, opt, *alts, desc, default: NilClass, **os, &conv
|
172
|
+
@name, @desc, @default, @os, @conv, @val =
|
173
|
+
name.to_s.to_sym, desc, default, os, conv || lambda{|v|v}, nil
|
174
|
+
parse_opt_string opt
|
175
|
+
alts.each &method( :parse_opt_string)
|
147
176
|
@req =
|
148
177
|
if NilClass != default
|
149
178
|
false
|
@@ -155,6 +184,7 @@ class DenCli::CMD
|
|
155
184
|
end
|
156
185
|
|
157
186
|
def on parser, store
|
187
|
+
store[@name] = @default if default?
|
158
188
|
parser.on "#{@short}#{@val ? ?= : ''}#{@val}", "#{@long}#{@val ? ?= : ''}#{@val}", **@os do |val|
|
159
189
|
store[@name] = @conv[val]
|
160
190
|
end
|
data/lib/dencli/sub.rb
CHANGED
@@ -15,16 +15,72 @@ class DenCli::Sub
|
|
15
15
|
"#{full_cmd.join ' '} ..."
|
16
16
|
end
|
17
17
|
|
18
|
-
def help n = nil, *a
|
18
|
+
def help n = nil, *a, output: nil
|
19
|
+
output ||= ''
|
20
|
+
_help output, n, *a
|
21
|
+
output
|
22
|
+
end
|
23
|
+
|
24
|
+
def _help output, n = nil, *a
|
19
25
|
if n.nil?
|
20
|
-
|
21
|
-
|
22
|
-
@subs.each do |k, c|
|
23
|
-
r += " % -#{m}s %s\n" % [c.usage, c.description] unless k.nil?
|
24
|
-
end
|
25
|
-
r
|
26
|
+
output << "#{full_cmd.join ' '}: #{description}\n\n"
|
27
|
+
self.class._help_commands output, @subs
|
26
28
|
elsif @aliases.has_key? n
|
27
|
-
@aliases[n].
|
29
|
+
@aliases[n]._help output, *a
|
30
|
+
else
|
31
|
+
raise DenCli::UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def commands &exe
|
36
|
+
yield self
|
37
|
+
@subs.each {|k, c| c.commands &exe }
|
38
|
+
end
|
39
|
+
|
40
|
+
def help_commands output: nil
|
41
|
+
output ||= ''
|
42
|
+
self.class._help_commands output, subs.map {|_,c| c}
|
43
|
+
output
|
44
|
+
end
|
45
|
+
|
46
|
+
def self._help_commands output, subs
|
47
|
+
m = subs.map {|c| x = c.usage.length; 25 < x ? 0 : x }.max
|
48
|
+
subs.each do |c|
|
49
|
+
if 25 < c.usage.length
|
50
|
+
output << "% -#{m}s\n#{' ' * m} " % [c.usage]
|
51
|
+
else
|
52
|
+
output << "% -#{m}s " % [c.usage]
|
53
|
+
end
|
54
|
+
n = m+2
|
55
|
+
prefix = nil
|
56
|
+
c.description.split /\n/ do |l|
|
57
|
+
c = 0
|
58
|
+
l.split %r< > do |w|
|
59
|
+
if prefix
|
60
|
+
output << prefix
|
61
|
+
prefix = nil
|
62
|
+
end
|
63
|
+
wl = w.length
|
64
|
+
if 75 < c+wl
|
65
|
+
output << "\n#{' ' * n}#{w}"
|
66
|
+
c = n+2+wl
|
67
|
+
else
|
68
|
+
output << " #{w}"
|
69
|
+
c += 1 + wl
|
70
|
+
end
|
71
|
+
end
|
72
|
+
prefix = "\n#{' ' * n}"
|
73
|
+
end
|
74
|
+
output << "\n"
|
75
|
+
end
|
76
|
+
output
|
77
|
+
end
|
78
|
+
|
79
|
+
def goto *a
|
80
|
+
return self if a.empty?
|
81
|
+
n, *a = *a
|
82
|
+
if @aliases.has_key? n
|
83
|
+
@aliases[n].goto *a
|
28
84
|
else
|
29
85
|
raise DenCli::UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
|
30
86
|
end
|
data/lib/dencli/version.rb
CHANGED
data/lib/dencli.rb
CHANGED
@@ -80,8 +80,22 @@ class DenCli
|
|
80
80
|
@subs.call *a
|
81
81
|
end
|
82
82
|
|
83
|
-
def
|
84
|
-
@subs.
|
83
|
+
def usage *args, **opts
|
84
|
+
@subs.usage *args, **opts
|
85
|
+
end
|
86
|
+
|
87
|
+
def help *args, **opts
|
88
|
+
@subs.help *args, **opts
|
89
|
+
end
|
90
|
+
|
91
|
+
def help_full *args, output: nil
|
92
|
+
output ||= STDOUT
|
93
|
+
x = @subs.goto *args
|
94
|
+
_help_full output, x
|
95
|
+
end
|
96
|
+
|
97
|
+
def _help_full output, subs
|
98
|
+
Sub._help_commands output, subs.to_enum( :commands)
|
85
99
|
end
|
86
100
|
|
87
101
|
def [] k
|