dencli 0.5.5 → 0.5.6
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 +55 -44
- data/lib/dencli/cmd.rb +8 -8
- data/lib/dencli/interactive.rb +12 -7
- data/lib/dencli/sub.rb +60 -19
- data/lib/dencli/version.rb +1 -1
- data/lib/dencli.rb +3 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 567eaa6ae13836be53cfc492496ae089be944c0a352f55023ac413e4f051c8d4
|
4
|
+
data.tar.gz: 7c3cb0ff03f0a738b56e785e8d2f9da76db16d0afab5c29fd5a53881476968cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2bc0b876cc7eb05a8a778264c76c2721bc8328199042ae551793c4f744b4248845f2390558718cae07dd4da215b5d166caa391c0c503c7a65550549fe3e78a1
|
7
|
+
data.tar.gz: 634d5a0a2d0037b2c81e4b1d7b922413beb760b016b961560bd1bc8bfb85e5d34ed08e5947e38068ae6074f3f79f96cc5ab298d8c53b384d7a9adf6e809bb714
|
data/bin/example.rb
CHANGED
@@ -95,7 +95,62 @@ class Capture
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
+
cli.cmd( :args, "Expects and prints given arguments",
|
99
|
+
&lambda {|a, b, c:, d:, e:, f:, g:|
|
100
|
+
p a: a, b: b, c: c, d: d, e: e
|
101
|
+
}).
|
102
|
+
opt( :c, '-c=ForC', "Option c").
|
103
|
+
opt( :d, '-dForD', "Option d", default: "something").
|
104
|
+
opt( :e, '-e', "Toggle e", default: false).
|
105
|
+
opt( :f, '--[no-]f', "Toggle f", default: false).
|
106
|
+
opt( :g, '--long-option=sth', "Long option, no short option", default: "nothing").
|
107
|
+
opt( :h, '-hsth', "No long option, only short option", default: "nothing")
|
108
|
+
|
109
|
+
cli.cmd( :example, "I have an example command") { $stderr.puts "This is an example" }
|
110
|
+
cli.cmd( :help, "An example for help", aliases: [nil, '-h', '--help'], &lambda {|*commands, full:|
|
111
|
+
if full
|
112
|
+
cli.help_full *commands, output: $stderr
|
113
|
+
else
|
114
|
+
cli.help *commands, output: $stderr
|
115
|
+
end
|
116
|
+
}).
|
117
|
+
opt( :full, '-f', '--[no-]full', "Print all commands and sub-commands.", default: false)
|
118
|
+
|
119
|
+
cli.sub( :more, "Sub-Commands are also possible with a new cli") do |sub|
|
120
|
+
sub.cmd( :help, "", aliases: [nil, '-h', '--help']) {|*args| $stderr.puts sub.help(*args) }
|
121
|
+
sub.cmd( :example, "Here is an example, too") { $stderr.puts "This is an other example" }
|
122
|
+
sub.cmd( :foo, "BAR") { $stderr.puts "FOO bar"}
|
123
|
+
|
124
|
+
sub.cmd( :args, "Expects and prints given arguments", &lambda {|a, b=1, c:, d: 5, e:|
|
125
|
+
p a: a, b: b, c: c, d: d, e: e
|
126
|
+
}).
|
127
|
+
opt( :c, '-c=ForC', "Option c").
|
128
|
+
opt( :d, '-d=ForD', "Option d (implicit default)").
|
129
|
+
opt( :e, '-e', "Toggle e")
|
130
|
+
|
131
|
+
sub.sub( :deeper, "You want to have Sub-Sub-Commands?") do |sub2|
|
132
|
+
sub2.cmd( :help, "", aliases: [nil, '-h', '--help'], &lambda {|*commands| sub2.help( *commands, output: $stderr) })
|
133
|
+
sub2.cmd( :last, "The last example", &lambda { $stderr.puts "The last example" })
|
134
|
+
|
135
|
+
sub2.sub( :'sub-commands', "Endless Sub-Sub- ... with a special alias") do |sub3|
|
136
|
+
# h -> help
|
137
|
+
# he -> hehe
|
138
|
+
# hel -> help
|
139
|
+
# help -> help
|
140
|
+
# heh -> hehe
|
141
|
+
# hehe -> hehe
|
142
|
+
sub3.cmd( :help, "", min: 3, aliases: [nil, :h]) {|*args| $stderr.puts sub3.help( *args) }
|
143
|
+
sub3.cmd( :hehe, "The real last example", min: 2) { $stderr.puts "Trust me!" }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
cli.cmd( :cli, "Interactive shell", min: 3, &lambda {||
|
149
|
+
cli.interactive( File.basename($0, '.rb')).run
|
150
|
+
})
|
151
|
+
|
98
152
|
cli.sub :tests, "Some tests", noshortaliases: true do |tcli|
|
153
|
+
tcli.cmd( :help, "", min: 4) {|*args| $stderr.puts tcli.help( *args) }
|
99
154
|
OptionParser.accept IPAddr do |arg|
|
100
155
|
begin
|
101
156
|
IPAddr.new arg
|
@@ -202,50 +257,6 @@ cli.sub :tests, "Some tests", noshortaliases: true do |tcli|
|
|
202
257
|
end.opt( :verbose, '-v', 'Prints additional information per test', default: false)
|
203
258
|
end
|
204
259
|
|
205
|
-
cli.cmd( :args, "Expects and prints given arguments",
|
206
|
-
&lambda {|a, b, c:, d:, e:, f:, g:|
|
207
|
-
p a: a, b: b, c: c, d: d, e: e
|
208
|
-
}).
|
209
|
-
opt( :c, '-c=ForC', "Option c").
|
210
|
-
opt( :d, '-dForD', "Option d", default: "something").
|
211
|
-
opt( :e, '-e', "Toggle e", default: false).
|
212
|
-
opt( :f, '--[no-]f', "Toggle f", default: false).
|
213
|
-
opt( :g, '--long-option=sth', "Long option, no short option", default: "nothing").
|
214
|
-
opt( :h, '-hsth', "No long option, only short option", default: "nothing")
|
215
|
-
|
216
|
-
cli.cmd( :example, "I have an example command") { $stderr.puts "This is an example" }
|
217
|
-
cli.cmd( :help, "An example for help", aliases: [nil, '-h', '--help'], &lambda {|*commands, full:|
|
218
|
-
if full
|
219
|
-
cli.help_full *commands, output: $stderr
|
220
|
-
else
|
221
|
-
cli.help *commands, output: $stderr
|
222
|
-
end
|
223
|
-
}).
|
224
|
-
opt( :full, '-f', '--[no-]full', "Print all commands and sub-commands.", default: false)
|
225
|
-
|
226
|
-
cli.sub( :more, "Sub-Commands are also possible with a new cli") do |sub|
|
227
|
-
sub.cmd( :help, "", aliases: [nil, '-h', '--help']) {|*args| $stderr.puts sub.help(*args) }
|
228
|
-
sub.cmd( :example, "Here is an example, too") { $stderr.puts "This is an other example" }
|
229
|
-
sub.cmd( :foo, "BAR") { $stderr.puts "FOO bar"}
|
230
|
-
|
231
|
-
sub.cmd( :args, "Expects and prints given arguments", &lambda {|a, b=1, c:, d: 5, e:|
|
232
|
-
p a: a, b: b, c: c, d: d, e: e
|
233
|
-
}).
|
234
|
-
opt( :c, '-c=ForC', "Option c").
|
235
|
-
opt( :d, '-d=ForD', "Option d (implicit default)").
|
236
|
-
opt( :e, '-e', "Toggle e")
|
237
|
-
|
238
|
-
sub.sub( :deeper, "You want to have Sub-Sub-Commands?") do |sub2|
|
239
|
-
sub2.cmd( :help, "", aliases: [nil, '-h', '--help'], &lambda {|*commands| sub2.help( *commands, output: $stderr) })
|
240
|
-
sub2.cmd( :last, "The last example", &lambda { $stderr.puts "The last example" })
|
241
|
-
|
242
|
-
sub2.sub( :'sub-commands', "Endless Sub-Sub- ...") do |sub3|
|
243
|
-
sub3.cmd( :help, "") {|*args| $stderr.puts sub3.help( sub3, *args) }
|
244
|
-
sub3.cmd( :hehe, "The real last example", min: 2) { $stderr.puts "Trust me!" }
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
260
|
begin
|
250
261
|
cli.call *ARGV
|
251
262
|
rescue DenCli::UsageError
|
data/lib/dencli/cmd.rb
CHANGED
@@ -2,11 +2,11 @@ require_relative '../dencli'
|
|
2
2
|
|
3
3
|
|
4
4
|
class DenCli::CMD
|
5
|
-
attr_reader :parent, :name, :description, :exe, :completion, :options
|
5
|
+
attr_reader :parent, :name, :description, :exe, :completion, :options, :defined_in
|
6
6
|
|
7
|
-
def initialize parent, name, description, exe
|
7
|
+
def initialize parent, name, description, exe, defined_in
|
8
8
|
raise "Proc expected, instead of: #{exe.inspect}" unless Proc === exe
|
9
|
-
@parent, @name, @description, @exe = parent, name, description, lambda( &exe)
|
9
|
+
@parent, @name, @description, @exe, @defined_in = parent, name, description, lambda( &exe), defined_in
|
10
10
|
@parameters = @exe.parameters
|
11
11
|
@arguments_required = @exe.parameters.select {|e| :req == e[0] }.map {|e| e[1] }
|
12
12
|
@arguments_additional = @exe.parameters.select {|e| :opt == e[0] }.map {|e| e[1] }
|
@@ -167,15 +167,15 @@ class DenCli::CMD
|
|
167
167
|
|
168
168
|
def parse_opt_string opt
|
169
169
|
case opt
|
170
|
-
when /\A(--\[no-\][^=]+)\z/
|
170
|
+
when /\A(--\[no-\][^= ]+)\z/
|
171
171
|
@long, @val = $1, nil
|
172
|
-
when /\A(--[^=]+)=(.+)\z/
|
172
|
+
when /\A(--[^= ]+)[= ](.+)\z/
|
173
173
|
@long, @val = $1, $2 || @val
|
174
|
-
when /\A(--[^=]+)\z/
|
174
|
+
when /\A(--[^= ]+)\z/
|
175
175
|
@long, @val = $1, nil
|
176
|
-
when /\A(-[
|
176
|
+
when /\A(-[^= -])[= ]?(.+)\z/
|
177
177
|
@short, @val = $1, $2 || @val
|
178
|
-
when /\A(-[
|
178
|
+
when /\A(-[^= -])\z/
|
179
179
|
@short, @val = $1, nil
|
180
180
|
else
|
181
181
|
raise ArgumentError, "Unexpected format for option: #{opt.inspect}"
|
data/lib/dencli/interactive.rb
CHANGED
@@ -17,12 +17,15 @@ class DenCli::Interactive
|
|
17
17
|
end
|
18
18
|
read_history if @histfile
|
19
19
|
|
20
|
-
|
20
|
+
begin
|
21
|
+
Readline.vi_editing_mode
|
22
|
+
rescue NotImplementedError
|
23
|
+
end
|
21
24
|
Readline.completion_append_character = " "
|
22
25
|
Readline.completion_proc = method :complete
|
23
26
|
|
24
27
|
prepare_sub cl.subs
|
25
|
-
cl.cmd :exit, "exit", min: 2 do
|
28
|
+
cl.cmd :exit, "exit", min: cl.has?(:ex) ? cl.has?(:exi) ? 4 : 3 : 2 do
|
26
29
|
exit 0
|
27
30
|
end
|
28
31
|
cl.subs.aliases['?'] = cl.subs.subs['help']
|
@@ -90,14 +93,16 @@ class DenCli::Interactive
|
|
90
93
|
c.subs.values.each do |n|
|
91
94
|
case n
|
92
95
|
when DenCli::Sub
|
93
|
-
n.cmd :exit,
|
94
|
-
|
95
|
-
|
96
|
+
n.cmd :exit,
|
97
|
+
"<- #{n.parent.full_cmd.join ' '} - #{n.parent.description[3..-1]}",
|
98
|
+
min: n.has?(:ex) ? n.has?( :exi) ? 4 : 3 : 2,
|
99
|
+
&lambda {|| @cur = n.parent }
|
100
|
+
n.aliases.delete nil
|
101
|
+
n.subs.delete nil
|
96
102
|
n.cmd '', "", min: 2, aliases: [nil] do
|
97
103
|
@cur = n
|
98
104
|
end
|
99
|
-
n.
|
100
|
-
n.aliases['?'] = n.subs['help']
|
105
|
+
n.aliases['?'] = n[:help] if n.has? :help and not n.has? '?'
|
101
106
|
prepare_sub n
|
102
107
|
when DenCli::CMD
|
103
108
|
else raise "Unsupported sub-type: #{x}"
|
data/lib/dencli/sub.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
require_relative '../dencli'
|
2
2
|
|
3
3
|
class DenCli::Sub
|
4
|
-
attr_reader :parent, :name, :description, :subs, :aliases
|
4
|
+
attr_reader :parent, :name, :description, :subs, :aliases, :defined_in
|
5
5
|
|
6
|
-
def initialize parent, name, description, noshortaliases: nil
|
6
|
+
def initialize parent, name, description, noshortaliases: nil, defined_in: nil
|
7
7
|
#DenCli::assert_type self, __method__, :name, name, Symbol
|
8
8
|
#DenCli::assert_type self, __method__, :parent, parent, DenCli, DenCli::Sub
|
9
9
|
#DenCli::assert_type self, __method__, :description, description, String
|
10
10
|
@parent, @name, @description, @subs, @aliases = parent, name, "-> #{description}", {}, {}
|
11
|
-
@noshortaliases = ! ! noshortaliases
|
11
|
+
@noshortaliases, @defined_in = ! ! noshortaliases, defined_in || Kernel.caller
|
12
12
|
end
|
13
13
|
|
14
14
|
def _full_cmd( post) parent._full_cmd [@name]+post end
|
15
15
|
def full_cmd() _full_cmd [] end
|
16
|
-
def [](
|
16
|
+
def []( name) @aliases[name&.to_s] end
|
17
|
+
def has?( name) @aliases.has_key? name&.to_s end
|
18
|
+
|
17
19
|
|
18
20
|
def usage output: nil
|
19
21
|
output ||= ''
|
@@ -40,8 +42,8 @@ class DenCli::Sub
|
|
40
42
|
if n.nil?
|
41
43
|
output << "#{full_cmd.join ' '}: #{description}\n\n"
|
42
44
|
self.class._help_commands output, @subs
|
43
|
-
elsif
|
44
|
-
|
45
|
+
elsif has? n
|
46
|
+
self[n]._help output, *a
|
45
47
|
else
|
46
48
|
raise DenCli::UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
|
47
49
|
end
|
@@ -96,8 +98,8 @@ class DenCli::Sub
|
|
96
98
|
def goto *a
|
97
99
|
return self if a.empty?
|
98
100
|
n, *a = *a
|
99
|
-
if
|
100
|
-
|
101
|
+
if has? n
|
102
|
+
self[n].goto *a
|
101
103
|
else
|
102
104
|
raise DenCli::UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
|
103
105
|
end
|
@@ -105,32 +107,33 @@ class DenCli::Sub
|
|
105
107
|
|
106
108
|
def call *a
|
107
109
|
n, *a = *a
|
108
|
-
if
|
109
|
-
|
110
|
+
if has? n
|
111
|
+
self[n].call *a
|
110
112
|
else
|
111
113
|
raise DenCli::UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
|
112
114
|
end
|
113
115
|
end
|
114
116
|
|
115
117
|
def _add name, min, obj, aliases
|
116
|
-
#DenCli::assert_type self, __method__, :name, name, Symbol,
|
118
|
+
#DenCli::assert_type self, __method__, :name, name, Symbol, String
|
117
119
|
#DenCli::assert_type self, __method__, :min, min, Integer, NilClass
|
118
120
|
#DenCli::assert_type self, __method__, :obj, obj, DenCli::Sub, DenCli::CMD
|
119
121
|
#DenCli::assert_type self, __method__, :aliases, aliases, Array, NilClass
|
120
|
-
name = name.to_s
|
122
|
+
name = name.to_s
|
121
123
|
@subs[name] = obj
|
122
124
|
if @noshortaliases
|
123
|
-
warn "Command/Alias already exists: #{full_cmd.join ' '} #{name}" if @aliases.has_key? name
|
125
|
+
warn "Command/Alias for #{obj.full_cmd} defined in #{obj.defined_in} already exists: #{full_cmd.join ' '} #{name}. Used by #{@aliases[name].full_cmd} defined in #{@aliases[name].defined_in}" if @aliases.has_key? name
|
124
126
|
@aliases[name] = obj
|
125
127
|
else
|
126
128
|
DenCli.gen_aliases name, min do |a|
|
127
|
-
warn "Command/Alias already exists: #{full_cmd.join ' '} #{a}"
|
129
|
+
warn "Command/Alias for #{obj.full_cmd} defined in #{obj.defined_in} already exists: #{full_cmd.join ' '} #{a}. Used by #{@aliases[a].full_cmd} defined in #{@aliases[a].defined_in}" if @aliases.has_key? a
|
128
130
|
@aliases[a] ||= obj
|
129
131
|
end
|
130
132
|
end
|
131
133
|
if aliases
|
132
134
|
[*aliases].each do |a|
|
133
|
-
|
135
|
+
a = a&.to_s
|
136
|
+
raise ArgumentError, "Alias for #{obj.full_cmd} defined in #{obj.defined_in} already exists: #{full_cmd.join ' '} #{a}. Used by #{@aliases[a].full_cmd} defined in #{@aliases[a].defined_in}" if @aliases.has_key? a
|
134
137
|
@aliases[a] = obj
|
135
138
|
end
|
136
139
|
end
|
@@ -138,13 +141,51 @@ class DenCli::Sub
|
|
138
141
|
end
|
139
142
|
private :_add
|
140
143
|
|
141
|
-
|
142
|
-
|
144
|
+
# Define a new sub-menu:
|
145
|
+
#
|
146
|
+
# DenCli.new {|c|
|
147
|
+
# c.sub( 'sub-command') {|s|
|
148
|
+
# s.cmd( :hello, 'Greetings', &lambda {|| puts 'hello world' })
|
149
|
+
# }
|
150
|
+
# }
|
151
|
+
#
|
152
|
+
# # ./prog sub-command hello
|
153
|
+
#
|
154
|
+
# name should be a string/symbol. It will be converted to string.
|
155
|
+
# If provided, aliases must be a list of different aliases. It will be converted to string.
|
156
|
+
def sub name, description, min: nil, aliases: nil, noshortaliases: nil, defined_in: nil, &exe
|
157
|
+
r = _add name.to_s, min, DenCli::Sub.new( self, name, description, noshortaliases: noshortaliases, defined_in: defined_in || Kernel.caller.first), aliases
|
143
158
|
block_given? ? yield( r) : r
|
144
159
|
end
|
145
160
|
|
146
|
-
|
147
|
-
|
161
|
+
# Define a new command:
|
162
|
+
#
|
163
|
+
# DenCli.new {|c|
|
164
|
+
# c.cmd( :hello, 'Greetings', &lambda {|| puts 'hello world' })
|
165
|
+
# }
|
166
|
+
#
|
167
|
+
# # ./prog hello
|
168
|
+
# hello world
|
169
|
+
#
|
170
|
+
# name should be a string/symbol. It will be converted to string.
|
171
|
+
# If provided, aliases must be a list of different aliases. Except of nil, any alias will be converted to string.
|
172
|
+
# nil is an alias for a default command for sub-commands, but interactive shells.
|
173
|
+
#
|
174
|
+
# DenCli.new {|c|
|
175
|
+
# c.sub( :greetings, 'Hello, Welcome, ...') do |s|
|
176
|
+
# s.cmd( :hello, 'A simple Hello', aliases: %w[hello-world hello_world], &lambda {|| puts 'Hello World' })
|
177
|
+
# s.cmd( :welcome, 'More gracefull', aliases: [nil, 'welcome-world', :hello_world], &lambda {|| puts 'Welcome World' })
|
178
|
+
# }
|
179
|
+
# }
|
180
|
+
#
|
181
|
+
# # ./prog greetings
|
182
|
+
# Welcome World
|
183
|
+
# # ./prog greetings welcome
|
184
|
+
# Welcome World
|
185
|
+
# # ./prog greetings hello
|
186
|
+
# Hello World
|
187
|
+
def cmd name, description, min: nil, aliases: nil, defined_in: nil, &exe
|
188
|
+
_add name, min, DenCli::CMD.new( self, name, description, exe, defined_in || Kernel.caller.first), aliases
|
148
189
|
end
|
149
190
|
|
150
191
|
def complete *pre, str
|
data/lib/dencli/version.rb
CHANGED
data/lib/dencli.rb
CHANGED
@@ -80,6 +80,9 @@ class DenCli
|
|
80
80
|
post
|
81
81
|
end
|
82
82
|
|
83
|
+
def []( k) @subs[k] end
|
84
|
+
def has?( k) @subs.has? k end
|
85
|
+
|
83
86
|
def sub *a, **o, &exe
|
84
87
|
@subs.sub *a, **o, &exe
|
85
88
|
end
|
@@ -110,10 +113,6 @@ class DenCli
|
|
110
113
|
Sub._help_commands output, subs.to_enum( :commands)
|
111
114
|
end
|
112
115
|
|
113
|
-
def [] k
|
114
|
-
@subs[k]
|
115
|
-
end
|
116
|
-
|
117
116
|
def interactive *args, **opts
|
118
117
|
Interactive.new self, *args, **opts
|
119
118
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dencli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Knauf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-02-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|