aliases are strings only or nil. more examples.
This commit is contained in:
parent
09b467f7bd
commit
c946a093f7
|
@ -95,7 +95,62 @@ class Capture
|
|||
end
|
||||
end
|
||||
|
||||
cli.cmd( :args, "Expects and prints given arguments",
|
||||
&lambda {|a, b, c:, d:, e:, f:, g:|
|
||||
p a: a, b: b, c: c, d: d, e: e
|
||||
}).
|
||||
opt( :c, '-c=ForC', "Option c").
|
||||
opt( :d, '-dForD', "Option d", default: "something").
|
||||
opt( :e, '-e', "Toggle e", default: false).
|
||||
opt( :f, '--[no-]f', "Toggle f", default: false).
|
||||
opt( :g, '--long-option=sth', "Long option, no short option", default: "nothing").
|
||||
opt( :h, '-hsth', "No long option, only short option", default: "nothing")
|
||||
|
||||
cli.cmd( :example, "I have an example command") { $stderr.puts "This is an example" }
|
||||
cli.cmd( :help, "An example for help", aliases: [nil, '-h', '--help'], &lambda {|*commands, full:|
|
||||
if full
|
||||
cli.help_full *commands, output: $stderr
|
||||
else
|
||||
cli.help *commands, output: $stderr
|
||||
end
|
||||
}).
|
||||
opt( :full, '-f', '--[no-]full', "Print all commands and sub-commands.", default: false)
|
||||
|
||||
cli.sub( :more, "Sub-Commands are also possible with a new cli") do |sub|
|
||||
sub.cmd( :help, "", aliases: [nil, '-h', '--help']) {|*args| $stderr.puts sub.help(*args) }
|
||||
sub.cmd( :example, "Here is an example, too") { $stderr.puts "This is an other example" }
|
||||
sub.cmd( :foo, "BAR") { $stderr.puts "FOO bar"}
|
||||
|
||||
sub.cmd( :args, "Expects and prints given arguments", &lambda {|a, b=1, c:, d: 5, e:|
|
||||
p a: a, b: b, c: c, d: d, e: e
|
||||
}).
|
||||
opt( :c, '-c=ForC', "Option c").
|
||||
opt( :d, '-d=ForD', "Option d (implicit default)").
|
||||
opt( :e, '-e', "Toggle e")
|
||||
|
||||
sub.sub( :deeper, "You want to have Sub-Sub-Commands?") do |sub2|
|
||||
sub2.cmd( :help, "", aliases: [nil, '-h', '--help'], &lambda {|*commands| sub2.help( *commands, output: $stderr) })
|
||||
sub2.cmd( :last, "The last example", &lambda { $stderr.puts "The last example" })
|
||||
|
||||
sub2.sub( :'sub-commands', "Endless Sub-Sub- ... with a special alias") do |sub3|
|
||||
# h -> help
|
||||
# he -> hehe
|
||||
# hel -> help
|
||||
# help -> help
|
||||
# heh -> hehe
|
||||
# hehe -> hehe
|
||||
sub3.cmd( :help, "", min: 3, aliases: [nil, :h]) {|*args| $stderr.puts sub3.help( *args) }
|
||||
sub3.cmd( :hehe, "The real last example", min: 2) { $stderr.puts "Trust me!" }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cli.cmd( :cli, "Interactive shell", min: 3, &lambda {||
|
||||
cli.interactive( File.basename($0, '.rb')).run
|
||||
})
|
||||
|
||||
cli.sub :tests, "Some tests", noshortaliases: true do |tcli|
|
||||
tcli.cmd( :help, "", min: 4) {|*args| $stderr.puts tcli.help( *args) }
|
||||
OptionParser.accept IPAddr do |arg|
|
||||
begin
|
||||
IPAddr.new arg
|
||||
|
@ -202,50 +257,6 @@ cli.sub :tests, "Some tests", noshortaliases: true do |tcli|
|
|||
end.opt( :verbose, '-v', 'Prints additional information per test', default: false)
|
||||
end
|
||||
|
||||
cli.cmd( :args, "Expects and prints given arguments",
|
||||
&lambda {|a, b, c:, d:, e:, f:, g:|
|
||||
p a: a, b: b, c: c, d: d, e: e
|
||||
}).
|
||||
opt( :c, '-c=ForC', "Option c").
|
||||
opt( :d, '-dForD', "Option d", default: "something").
|
||||
opt( :e, '-e', "Toggle e", default: false).
|
||||
opt( :f, '--[no-]f', "Toggle f", default: false).
|
||||
opt( :g, '--long-option=sth', "Long option, no short option", default: "nothing").
|
||||
opt( :h, '-hsth', "No long option, only short option", default: "nothing")
|
||||
|
||||
cli.cmd( :example, "I have an example command") { $stderr.puts "This is an example" }
|
||||
cli.cmd( :help, "An example for help", aliases: [nil, '-h', '--help'], &lambda {|*commands, full:|
|
||||
if full
|
||||
cli.help_full *commands, output: $stderr
|
||||
else
|
||||
cli.help *commands, output: $stderr
|
||||
end
|
||||
}).
|
||||
opt( :full, '-f', '--[no-]full', "Print all commands and sub-commands.", default: false)
|
||||
|
||||
cli.sub( :more, "Sub-Commands are also possible with a new cli") do |sub|
|
||||
sub.cmd( :help, "", aliases: [nil, '-h', '--help']) {|*args| $stderr.puts sub.help(*args) }
|
||||
sub.cmd( :example, "Here is an example, too") { $stderr.puts "This is an other example" }
|
||||
sub.cmd( :foo, "BAR") { $stderr.puts "FOO bar"}
|
||||
|
||||
sub.cmd( :args, "Expects and prints given arguments", &lambda {|a, b=1, c:, d: 5, e:|
|
||||
p a: a, b: b, c: c, d: d, e: e
|
||||
}).
|
||||
opt( :c, '-c=ForC', "Option c").
|
||||
opt( :d, '-d=ForD', "Option d (implicit default)").
|
||||
opt( :e, '-e', "Toggle e")
|
||||
|
||||
sub.sub( :deeper, "You want to have Sub-Sub-Commands?") do |sub2|
|
||||
sub2.cmd( :help, "", aliases: [nil, '-h', '--help'], &lambda {|*commands| sub2.help( *commands, output: $stderr) })
|
||||
sub2.cmd( :last, "The last example", &lambda { $stderr.puts "The last example" })
|
||||
|
||||
sub2.sub( :'sub-commands', "Endless Sub-Sub- ...") do |sub3|
|
||||
sub3.cmd( :help, "") {|*args| $stderr.puts sub3.help( sub3, *args) }
|
||||
sub3.cmd( :hehe, "The real last example", min: 2) { $stderr.puts "Trust me!" }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
cli.call *ARGV
|
||||
rescue DenCli::UsageError
|
||||
|
|
|
@ -80,6 +80,9 @@ class DenCli
|
|||
post
|
||||
end
|
||||
|
||||
def []( k) @subs[k] end
|
||||
def has?( k) @subs.has? k end
|
||||
|
||||
def sub *a, **o, &exe
|
||||
@subs.sub *a, **o, &exe
|
||||
end
|
||||
|
@ -110,10 +113,6 @@ class DenCli
|
|||
Sub._help_commands output, subs.to_enum( :commands)
|
||||
end
|
||||
|
||||
def [] k
|
||||
@subs[k]
|
||||
end
|
||||
|
||||
def interactive *args, **opts
|
||||
Interactive.new self, *args, **opts
|
||||
end
|
||||
|
|
|
@ -17,12 +17,15 @@ class DenCli::Interactive
|
|||
end
|
||||
read_history if @histfile
|
||||
|
||||
Readline.vi_editing_mode rescue NotImplementedError
|
||||
begin
|
||||
Readline.vi_editing_mode
|
||||
rescue NotImplementedError
|
||||
end
|
||||
Readline.completion_append_character = " "
|
||||
Readline.completion_proc = method :complete
|
||||
|
||||
prepare_sub cl.subs
|
||||
cl.cmd :exit, "exit", min: 2 do
|
||||
cl.cmd :exit, "exit", min: cl.has?(:ex) ? cl.has?(:exi) ? 4 : 3 : 2 do
|
||||
exit 0
|
||||
end
|
||||
cl.subs.aliases['?'] = cl.subs.subs['help']
|
||||
|
@ -90,14 +93,16 @@ class DenCli::Interactive
|
|||
c.subs.values.each do |n|
|
||||
case n
|
||||
when DenCli::Sub
|
||||
n.cmd :exit, "<- #{n.parent.full_cmd.join ' '} - #{n.parent.description[3..-1]}", min: 2 do
|
||||
@cur = n.parent
|
||||
end
|
||||
n.cmd :exit,
|
||||
"<- #{n.parent.full_cmd.join ' '} - #{n.parent.description[3..-1]}",
|
||||
min: n.has?(:ex) ? n.has?( :exi) ? 4 : 3 : 2,
|
||||
&lambda {|| @cur = n.parent }
|
||||
n.aliases.delete nil
|
||||
n.subs.delete nil
|
||||
n.cmd '', "", min: 2, aliases: [nil] do
|
||||
@cur = n
|
||||
end
|
||||
n.subs.delete ''
|
||||
n.aliases['?'] = n.subs['help']
|
||||
n.aliases['?'] = n[:help] if n.has? :help and not n.has? '?'
|
||||
prepare_sub n
|
||||
when DenCli::CMD
|
||||
else raise "Unsupported sub-type: #{x}"
|
||||
|
|
|
@ -13,7 +13,9 @@ class DenCli::Sub
|
|||
|
||||
def _full_cmd( post) parent._full_cmd [@name]+post end
|
||||
def full_cmd() _full_cmd [] end
|
||||
def []( k) @aliases[k] end
|
||||
def []( name) @aliases[name&.to_s] end
|
||||
def has?( name) @aliases.has_key? name&.to_s end
|
||||
|
||||
|
||||
def usage output: nil
|
||||
output ||= ''
|
||||
|
@ -40,8 +42,8 @@ class DenCli::Sub
|
|||
if n.nil?
|
||||
output << "#{full_cmd.join ' '}: #{description}\n\n"
|
||||
self.class._help_commands output, @subs
|
||||
elsif @aliases.has_key? n
|
||||
@aliases[n]._help output, *a
|
||||
elsif has? n
|
||||
self[n]._help output, *a
|
||||
else
|
||||
raise DenCli::UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
|
||||
end
|
||||
|
@ -96,8 +98,8 @@ class DenCli::Sub
|
|||
def goto *a
|
||||
return self if a.empty?
|
||||
n, *a = *a
|
||||
if @aliases.has_key? n
|
||||
@aliases[n].goto *a
|
||||
if has? n
|
||||
self[n].goto *a
|
||||
else
|
||||
raise DenCli::UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
|
||||
end
|
||||
|
@ -105,19 +107,19 @@ class DenCli::Sub
|
|||
|
||||
def call *a
|
||||
n, *a = *a
|
||||
if @aliases.has_key? n
|
||||
@aliases[n].call *a
|
||||
if has? n
|
||||
self[n].call *a
|
||||
else
|
||||
raise DenCli::UnknownCommand, "unknown command: #{_full_cmd( [n])[1..-1].join ' '}, available for #{full_cmd[1..-1].join' '}: #{@subs.keys.join ' '}"
|
||||
end
|
||||
end
|
||||
|
||||
def _add name, min, obj, aliases
|
||||
#DenCli::assert_type self, __method__, :name, name, Symbol, NilClass
|
||||
#DenCli::assert_type self, __method__, :name, name, Symbol, String
|
||||
#DenCli::assert_type self, __method__, :min, min, Integer, NilClass
|
||||
#DenCli::assert_type self, __method__, :obj, obj, DenCli::Sub, DenCli::CMD
|
||||
#DenCli::assert_type self, __method__, :aliases, aliases, Array, NilClass
|
||||
name = name.to_s unless name.nil?
|
||||
name = name.to_s
|
||||
@subs[name] = obj
|
||||
if @noshortaliases
|
||||
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
|
||||
|
@ -130,6 +132,7 @@ class DenCli::Sub
|
|||
end
|
||||
if aliases
|
||||
[*aliases].each do |a|
|
||||
a = a&.to_s
|
||||
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
|
||||
@aliases[a] = obj
|
||||
end
|
||||
|
@ -138,11 +141,49 @@ class DenCli::Sub
|
|||
end
|
||||
private :_add
|
||||
|
||||
# Define a new sub-menu:
|
||||
#
|
||||
# DenCli.new {|c|
|
||||
# c.sub( 'sub-command') {|s|
|
||||
# s.cmd( :hello, 'Greetings', &lambda {|| puts 'hello world' })
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# # ./prog sub-command hello
|
||||
#
|
||||
# name should be a string/symbol. It will be converted to string.
|
||||
# If provided, aliases must be a list of different aliases. It will be converted to string.
|
||||
def sub name, description, min: nil, aliases: nil, noshortaliases: nil, defined_in: nil, &exe
|
||||
r = _add name, min, DenCli::Sub.new( self, name, description, noshortaliases: noshortaliases, defined_in: defined_in || Kernel.caller.first), aliases
|
||||
r = _add name.to_s, min, DenCli::Sub.new( self, name, description, noshortaliases: noshortaliases, defined_in: defined_in || Kernel.caller.first), aliases
|
||||
block_given? ? yield( r) : r
|
||||
end
|
||||
|
||||
# Define a new command:
|
||||
#
|
||||
# DenCli.new {|c|
|
||||
# c.cmd( :hello, 'Greetings', &lambda {|| puts 'hello world' })
|
||||
# }
|
||||
#
|
||||
# # ./prog hello
|
||||
# hello world
|
||||
#
|
||||
# name should be a string/symbol. It will be converted to string.
|
||||
# If provided, aliases must be a list of different aliases. Except of nil, any alias will be converted to string.
|
||||
# nil is an alias for a default command for sub-commands, but interactive shells.
|
||||
#
|
||||
# DenCli.new {|c|
|
||||
# c.sub( :greetings, 'Hello, Welcome, ...') do |s|
|
||||
# s.cmd( :hello, 'A simple Hello', aliases: %w[hello-world hello_world], &lambda {|| puts 'Hello World' })
|
||||
# s.cmd( :welcome, 'More gracefull', aliases: [nil, 'welcome-world', :hello_world], &lambda {|| puts 'Welcome World' })
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# # ./prog greetings
|
||||
# Welcome World
|
||||
# # ./prog greetings welcome
|
||||
# Welcome World
|
||||
# # ./prog greetings hello
|
||||
# Hello World
|
||||
def cmd name, description, min: nil, aliases: nil, defined_in: nil, &exe
|
||||
_add name, min, DenCli::CMD.new( self, name, description, exe, defined_in || Kernel.caller.first), aliases
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue