kxi 1.0.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 +7 -0
- data/lib/kxi/cli/anonymous_argument.rb +51 -0
- data/lib/kxi/cli/argument.rb +57 -0
- data/lib/kxi/cli/argument_values.rb +84 -0
- data/lib/kxi/cli/explicit_argument.rb +39 -0
- data/lib/kxi/cli/flag_argument.rb +16 -0
- data/lib/kxi/cli/named_argument.rb +60 -0
- data/lib/kxi/cli/verb.rb +281 -0
- data/lib/kxi/collections/array_collection.rb +107 -0
- data/lib/kxi/collections/enumerable.rb +528 -0
- data/lib/kxi/collections/enumerator.rb +32 -0
- data/lib/kxi/collections/hash_collection.rb +101 -0
- data/lib/kxi/collections/protected_collection.rb +20 -0
- data/lib/kxi/exceptions/abstract_exception.rb +35 -0
- data/lib/kxi/exceptions/argument_exception.rb +22 -0
- data/lib/kxi/exceptions/collection_exception.rb +14 -0
- data/lib/kxi/exceptions/invalid_type_exception.rb +33 -0
- data/lib/kxi/exceptions/no_argument_exception.rb +21 -0
- data/lib/kxi/exceptions/not_implemented_exception.rb +13 -0
- data/lib/kxi/exceptions/out_of_range_exception.rb +44 -0
- data/lib/kxi/exceptions/verb_expected_exception.rb +21 -0
- data/lib/kxi/reflection/stack_frame.rb +81 -0
- data/lib/kxi/version.rb +4 -0
- data/lib/kxi.rb +22 -0
- metadata +165 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a376bd573bfb44dbeae16f773f883a1f55daedd7
|
4
|
+
data.tar.gz: 4cbb2897d3c73fe15b882a26d79f8d3bdc387244
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7d040d8a1a051f68268ba981ea84e69fcf5bd547f801c3411511bcb3b3edd2da4e23befcb9171fe6b43655bdd2adca2ef6b8de387fa5874f8d8b76b79cbabac7
|
7
|
+
data.tar.gz: c35695494016d0625076379ffcc9370e5c4299cc47cc19f4979d10ee0cd4f9ac01c3d4f3e27051f1c2859c18a4099aa830324545fb1ef0d0ab45ec671c405ed8
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Created by Matyáš Pokorný on 2018-01-20.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module CLI
|
5
|
+
# Represents anonymous argument (eg.: verb VALUE)
|
6
|
+
class AnonymousArgument < KXI::CLI::Argument
|
7
|
+
# Gets default value of argument
|
8
|
+
# @return [Object] Default value of argument
|
9
|
+
def default
|
10
|
+
@def
|
11
|
+
end
|
12
|
+
|
13
|
+
# Gets whether argument is variadic
|
14
|
+
# @return [Bool] True if argument is variadic; false otherwise
|
15
|
+
def variadic?
|
16
|
+
@var
|
17
|
+
end
|
18
|
+
|
19
|
+
# Gets syntax of argument
|
20
|
+
# @return [String] Syntax of argument
|
21
|
+
def syntax
|
22
|
+
"#{required? ? '<' : '['}#{name}#{required? ? '>' : ']'}"
|
23
|
+
end
|
24
|
+
|
25
|
+
# Gets full descriptive name of argument
|
26
|
+
# @return [String] Full name of argument
|
27
|
+
def headline
|
28
|
+
super.upcase
|
29
|
+
end
|
30
|
+
|
31
|
+
# Instantiates the {KXI::CLI::AnonymousArgument} class
|
32
|
+
# @param nm [String] Name of argument
|
33
|
+
# @param desc [String] Description of argument
|
34
|
+
# @param rq [Bool] Indicates whether argument is required
|
35
|
+
# @param df Default value of argument
|
36
|
+
# @param var [Bool] Indicates whether argument is variadic
|
37
|
+
def initialize(nm, desc, rq = true, df = nil, var = false, &validator)
|
38
|
+
super(nm, desc, rq, 5 - (var ? 1 : 0) - (rq ? 0 : 1))
|
39
|
+
@def = df
|
40
|
+
@var = var
|
41
|
+
@val = validator
|
42
|
+
end
|
43
|
+
|
44
|
+
# Validates value of argument
|
45
|
+
# @param val [String, Array<String>] Value of argument
|
46
|
+
def validate(val)
|
47
|
+
@val.call(val) if @val != nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Created by Matyáš Pokorný on 2018-01-20.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module CLI
|
5
|
+
# Represents argument of command-line interface
|
6
|
+
class Argument
|
7
|
+
# Gets the name of argument
|
8
|
+
# @return [String] Name of argument
|
9
|
+
def name
|
10
|
+
@name
|
11
|
+
end
|
12
|
+
|
13
|
+
# Gets syntax of argument
|
14
|
+
# @return [String] Syntax of argument
|
15
|
+
def syntax
|
16
|
+
name
|
17
|
+
end
|
18
|
+
|
19
|
+
# Gets full descriptive name of argument
|
20
|
+
# @return [String] Full name of argument
|
21
|
+
def headline
|
22
|
+
name
|
23
|
+
end
|
24
|
+
|
25
|
+
# Gets the description of argument
|
26
|
+
# @return [String] Description of argument
|
27
|
+
def description
|
28
|
+
@desc
|
29
|
+
end
|
30
|
+
|
31
|
+
# Indicates whether argument is mandatory
|
32
|
+
# @return [Bool] True if argument is mandatory; otherwise false
|
33
|
+
def required?
|
34
|
+
@req
|
35
|
+
end
|
36
|
+
|
37
|
+
# Gets the order of argument (in descending order)
|
38
|
+
# @return [Number] Order of argument
|
39
|
+
def order
|
40
|
+
@order
|
41
|
+
end
|
42
|
+
|
43
|
+
# Instantiates the {KXI::CLI::Argument} class
|
44
|
+
# @param nm [String] Name of argument
|
45
|
+
# @param desc [String] Description of argument
|
46
|
+
# @param req [Bool] Determines whether argument is mandatory
|
47
|
+
# @param order [Number] Order of argument
|
48
|
+
def initialize(nm, desc, req, order)
|
49
|
+
raise(Exception.new('Invalid argument name!')) unless /^[A-Za-z0-9\-]+$/m =~ nm
|
50
|
+
@name = nm.downcase
|
51
|
+
@desc = desc
|
52
|
+
@req = req
|
53
|
+
@order = order
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Created by Matyáš Pokorný on 2018-01-21.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module CLI
|
5
|
+
# Manages values of arguments
|
6
|
+
class ArgumentValues
|
7
|
+
# Instantiates the {KXI::CLI::ArgumentValues} class
|
8
|
+
# @param args [Array<KXI::CLI::Argument>] Expected arguments
|
9
|
+
def initialize(args)
|
10
|
+
@args = args
|
11
|
+
@vals = {}
|
12
|
+
args.each do |a|
|
13
|
+
if a.is_a?(KXI::CLI::FlagArgument)
|
14
|
+
@vals[a.name] = { :argument => a, :value => false }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Assigns (or adds) a value to argument
|
20
|
+
# @param arg [KXI::CLI::Argument] Argument to set
|
21
|
+
# @param val [String] Value to assign
|
22
|
+
def set(arg, val)
|
23
|
+
if arg.is_a?(KXI::CLI::FlagArgument)
|
24
|
+
raise(KXI::Exceptions::ArgumentException.new(arg.name, 'Flag set multiple times!')) if @vals[arg.name][:value]
|
25
|
+
@vals[arg.name][:value] = val
|
26
|
+
else
|
27
|
+
if arg.variadic?
|
28
|
+
@vals[arg.name] = { :argument => arg, :value => [] } if @vals[arg.name] == nil
|
29
|
+
@vals[arg.name][:value].push(val)
|
30
|
+
else
|
31
|
+
raise(KXI::Exceptions::ArgumentException.new(arg.name, 'Argument set multiple times!')) if @vals[arg.name] != nil
|
32
|
+
begin
|
33
|
+
arg.validate(val)
|
34
|
+
rescue Exception => ex
|
35
|
+
raise(KXI::Exceptions::ArgumentException.new(arg.name, ex.message))
|
36
|
+
end
|
37
|
+
@vals[arg.name] = { :argument => arg, :value => val }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Gets value of argument
|
43
|
+
# @param index [String, Symbol, KXI::CLI::Argument] Name of argument
|
44
|
+
# @return [String] Value of argument
|
45
|
+
def []=(index)
|
46
|
+
if index.is_a?(Symbol)
|
47
|
+
index = index.to_s
|
48
|
+
elsif index.is_a?(KXI::CLI::Argument)
|
49
|
+
index = index.name
|
50
|
+
end
|
51
|
+
raise(Exception.new("Undefined argument #{index}!")) if @vals[index] == nil
|
52
|
+
return @vals[index][:value]
|
53
|
+
end
|
54
|
+
|
55
|
+
# Converts class to {Hash}
|
56
|
+
# @return [Hash] Equivalent hash
|
57
|
+
def to_h
|
58
|
+
ret = {}
|
59
|
+
@vals.each_pair do |k, v|
|
60
|
+
ret[k] = v[:value]
|
61
|
+
end
|
62
|
+
return ret
|
63
|
+
end
|
64
|
+
|
65
|
+
# Validates variadic arguments and checks for minimal argument requirements
|
66
|
+
def finish
|
67
|
+
@args.each do |arg|
|
68
|
+
if @vals[arg.name] != nil
|
69
|
+
unless arg.is_a?(KXI::CLI::FlagArgument)
|
70
|
+
begin
|
71
|
+
arg.validate(@vals[arg.name][:value])
|
72
|
+
rescue Exception => ex
|
73
|
+
raise(KXI::Exceptions::ArgumentException.new(arg.name, ex.message))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
else
|
77
|
+
raise(KXI::Exceptions::ArgumentException.new(arg.name, 'Argument is mandatory!')) if arg.required?
|
78
|
+
@vals[arg.name] = arg.default
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Created by Matyáš Pokorný on 2018-01-20.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module CLI
|
5
|
+
# Represents argument specified explicitly with name
|
6
|
+
class ExplicitArgument < KXI::CLI::Argument
|
7
|
+
# Gets full descriptive name of argument
|
8
|
+
# @return [String] Full name of argument
|
9
|
+
def headline
|
10
|
+
ret = ''
|
11
|
+
ret = "-#{@sh}, " if @sh != nil
|
12
|
+
ret += "--#{name}"
|
13
|
+
return ret
|
14
|
+
end
|
15
|
+
|
16
|
+
# Gets syntax of argument
|
17
|
+
# @return [String] Syntax of argument
|
18
|
+
def syntax
|
19
|
+
headline
|
20
|
+
end
|
21
|
+
|
22
|
+
# Gets the shortcut symbol of argument
|
23
|
+
# @return [String] Shortcut symbol of argument
|
24
|
+
def shortcut
|
25
|
+
@sh
|
26
|
+
end
|
27
|
+
|
28
|
+
# Instantiates the {KXI::CLI::ExplicitArgument} class
|
29
|
+
# @param nm [String] Name of argument
|
30
|
+
# @param desc [String] Description of argument
|
31
|
+
# @param sh [String, nil] Shortcut of argument
|
32
|
+
# @param req [Bool] Specifies whether argument is mandatory
|
33
|
+
def initialize(nm, desc, sh = nil, req = false)
|
34
|
+
super(nm, desc, req, req ? 2 : 1)
|
35
|
+
@sh = sh
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Created by Matyáš Pokorný on 2018-01-20.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module CLI
|
5
|
+
# Represents the flag argument (eg.: -f, --flag)
|
6
|
+
class FlagArgument < KXI::CLI::ExplicitArgument
|
7
|
+
# Instantiates the {KXI::CLI::FlagArgument} class
|
8
|
+
# @param nm [String] Name of argument
|
9
|
+
# @param desc [String] Description of argument
|
10
|
+
# @param sh [String] Shortcut of argument
|
11
|
+
def initialize(nm, desc, sh = nil)
|
12
|
+
super(nm, desc, sh)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# Created by Matyáš Pokorný on 2018-01-20.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module CLI
|
5
|
+
# Represents named argument (eg.: -a VALUE, --argument VALUE)
|
6
|
+
class NamedArgument < KXI::CLI::ExplicitArgument
|
7
|
+
# Gets default value of argument
|
8
|
+
# @return [Object] Default value of argument
|
9
|
+
def default
|
10
|
+
@def
|
11
|
+
end
|
12
|
+
|
13
|
+
# Gets whether argument is variadic
|
14
|
+
# @return [Bool] True if argument is variadic; false otherwise
|
15
|
+
def variadic?
|
16
|
+
@var
|
17
|
+
end
|
18
|
+
|
19
|
+
# Gets name of argument value
|
20
|
+
# @return [String] Name of argument value
|
21
|
+
def value_name
|
22
|
+
@vnm
|
23
|
+
end
|
24
|
+
|
25
|
+
# Gets full descriptive name of argument
|
26
|
+
# @return [String] Full name of argument
|
27
|
+
def headline
|
28
|
+
"#{super} #{@var ? '...' : ''}#{@vnm.upcase}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# Gets syntax of argument
|
32
|
+
# @return [String] Syntax of argument
|
33
|
+
def syntax
|
34
|
+
"-#{(shortcut != nil ? shortcut : "-#{name}")} #{required? ? '<' : '['}#{@var ? '...' : ''}#{@vnm}#{required? ? '>' : ']'}"
|
35
|
+
end
|
36
|
+
|
37
|
+
# Instantiates the {KXI::CLI::NamedArgument} class
|
38
|
+
# @param nm [String] Name of argument
|
39
|
+
# @param vn [String] Name of value
|
40
|
+
# @param desc [String] Description of argument
|
41
|
+
# @param sh [String] Shortcut of argument
|
42
|
+
# @param rq [Bool] Indicates whether argument is required
|
43
|
+
# @param df Default value of argument
|
44
|
+
# @param var [Bool] Indicates whether argument is variadic
|
45
|
+
def initialize(nm, vn, desc, sh = nil, rq = true, df = nil, var = false, &validator)
|
46
|
+
super(nm, desc, sh, rq)
|
47
|
+
@def = df
|
48
|
+
@vnm = vn
|
49
|
+
@var = var
|
50
|
+
@val = validator
|
51
|
+
end
|
52
|
+
|
53
|
+
# Validates value of argument
|
54
|
+
# @param val [String, Array<String>] Value of argument
|
55
|
+
def validate(val)
|
56
|
+
@val.call(val) if @val != nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/kxi/cli/verb.rb
ADDED
@@ -0,0 +1,281 @@
|
|
1
|
+
# Created by Matyáš Pokorný on 2018-01-20.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module CLI
|
5
|
+
# Represents a verb of console interface
|
6
|
+
class Verb
|
7
|
+
# Gets the name of verb
|
8
|
+
# @return [String] Name of verb
|
9
|
+
def name
|
10
|
+
@name
|
11
|
+
end
|
12
|
+
|
13
|
+
# Gets the description of verb
|
14
|
+
# @return [String] Description of verb
|
15
|
+
def description
|
16
|
+
@desc
|
17
|
+
end
|
18
|
+
|
19
|
+
# Assigns action to this verb
|
20
|
+
# @yield [args] Action of verb
|
21
|
+
# @yieldparam args [KXI::CLI::ArgumentValues] Parsed values of arguments
|
22
|
+
def action(&block)
|
23
|
+
@action = block
|
24
|
+
end
|
25
|
+
|
26
|
+
# Gets the arguments assigned to this verb
|
27
|
+
# @return [KXI::Collections::ProtectedCollection] Arguments of verb
|
28
|
+
def arguments
|
29
|
+
KXI::Collections::ProtectedCollection.new(@args)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Enables help for this verb and it's children
|
33
|
+
def enable_help
|
34
|
+
unless @help
|
35
|
+
@help = true
|
36
|
+
@verbs.foreach { |i| i.enable_help }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Instantiates the {KXI::CLI::Verb} class
|
41
|
+
# @param nm [String] Name of verb
|
42
|
+
# @param desc [String] Description of verb
|
43
|
+
# @param ctx [String] Context of verb
|
44
|
+
# @yield [verb] Initialization body of verb
|
45
|
+
# @yieldparam verb [KXI::CLI::Verb] Initialized verb
|
46
|
+
# @raise [Exception] When name of verb is invalid
|
47
|
+
def initialize(nm, desc, ctx = nil)
|
48
|
+
raise(Exception.new('Invalid name of verb!')) unless /^[A-Za-z0-9][A-Za-z0-9\-]*$/m =~ nm
|
49
|
+
@name = nm.downcase
|
50
|
+
@desc = desc
|
51
|
+
@verbs = KXI::Collections::ArrayCollection.new
|
52
|
+
@args = KXI::Collections::ArrayCollection.new
|
53
|
+
@action = nil
|
54
|
+
@ctx = ctx
|
55
|
+
@help = false
|
56
|
+
yield(self) if block_given?
|
57
|
+
end
|
58
|
+
|
59
|
+
# Creates a new child verb
|
60
|
+
# @param name [String] Name of verb
|
61
|
+
# @param desc [String] Description of verb
|
62
|
+
# @return [KXI::CLI::Verb] Child verb
|
63
|
+
def verb(name, desc)
|
64
|
+
check_name(name)
|
65
|
+
add_verb(Verb.new(name, desc, @ctx == nil ? @name : "#{@ctx} #{@name}") { |v| yield(v) if block_given? })
|
66
|
+
end
|
67
|
+
|
68
|
+
# Creates new optional anonymous argument
|
69
|
+
# @param name [String] Name of argument
|
70
|
+
# @param desc [String] Description of argument
|
71
|
+
# @param df [Object, nil] Default value of argument
|
72
|
+
# @param var [Bool] Determines whether argument is variadic
|
73
|
+
# @yield [val] Validator function for value of argument
|
74
|
+
# @yieldparam val [String, Array<String>] Value of argument
|
75
|
+
# @return [KXI::CLI::AnonymousArgument] Anonymous argument
|
76
|
+
def anonymous(name, desc, df = nil, var = false, &validator)
|
77
|
+
add_argument(KXI::CLI::AnonymousArgument.new(name, desc, false, df, var, &validator))
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# Creates new mandatory anonymous argument
|
82
|
+
# @param name [String] Name of argument
|
83
|
+
# @param desc [String] Description of argument
|
84
|
+
# @param var [Bool] Determines whether argument is variadic
|
85
|
+
# @yield [val] Validator function for value of argument
|
86
|
+
# @yieldparam val [String, Array<String>] Value of argument
|
87
|
+
# @return [KXI::CLI::AnonymousArgument] Anonymous argument
|
88
|
+
def anonymous!(name, desc, var = false, &validator)
|
89
|
+
add_argument(KXI::CLI::AnonymousArgument.new(name, desc, true, nil, var, &validator))
|
90
|
+
end
|
91
|
+
|
92
|
+
# Creates new optional named argument
|
93
|
+
# @param name [String] Name of argument
|
94
|
+
# @param val [String] Name of value
|
95
|
+
# @param desc [String] Description of argument
|
96
|
+
# @param sh [String, nil] Shortcut symbol
|
97
|
+
# @param df [Object, nil] Default value of argument
|
98
|
+
# @param var [Bool] Determines whether argument is variadic
|
99
|
+
# @yield [val] Validator function for value of argument
|
100
|
+
# @yieldparam val [String, Array<String>] Value of argument
|
101
|
+
# @return [KXI::CLI::NamedArgument] Named argument
|
102
|
+
def named(name, val, desc, sh = nil, df = nil, var = false, &validator)
|
103
|
+
add_argument(KXI::CLI::NamedArgument.new(name, val, desc, sh, false, df, var, &validator))
|
104
|
+
end
|
105
|
+
|
106
|
+
|
107
|
+
# Creates new mandatory named argument
|
108
|
+
# @param name [String] Name of argument
|
109
|
+
# @param val [String] Name of value
|
110
|
+
# @param desc [String] Description of argument
|
111
|
+
# @param sh [String, nil] Shortcut symbol
|
112
|
+
# @param var [Bool] Determines whether argument is variadic
|
113
|
+
# @yield [val] Validator function for value of argument
|
114
|
+
# @yieldparam val [String, Array<String>] Value of argument
|
115
|
+
# @return [KXI::CLI::NamedArgument] Named argument
|
116
|
+
def named!(name, val, desc, sh = nil, var = false, &validator)
|
117
|
+
add_argument(KXI::CLI::NamedArgument.new(name, val, desc, sh, true, nil, var, &validator))
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
# Creates new flag argument
|
122
|
+
# @param name [String] Name of flag
|
123
|
+
# @param desc [String] Description of flag
|
124
|
+
# @param sh [String, nil] Shortcut symbol
|
125
|
+
# @return [KXI::CLI::FlagArgument] Flag argument
|
126
|
+
def flag(name, desc, sh = nil)
|
127
|
+
add_argument(KXI::CLI::FlagArgument.new(name, desc, sh))
|
128
|
+
end
|
129
|
+
|
130
|
+
# Parses and executes action of verb
|
131
|
+
# @param args [Array<String>] Given arguments
|
132
|
+
def act(*args)
|
133
|
+
args = ARGV if args.length == 0
|
134
|
+
hf = args.include?('-h') or args.include?('--help') or args.include?('-?')
|
135
|
+
if @verbs.count > 0
|
136
|
+
v = args.shift
|
137
|
+
if @help and (v == 'help' or hf)
|
138
|
+
if v == 'help' or v == nil
|
139
|
+
help
|
140
|
+
else
|
141
|
+
verb = @verbs.first { |i| i.name == v.downcase }
|
142
|
+
if verb == nil
|
143
|
+
help
|
144
|
+
else
|
145
|
+
verb.act(*args)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
else
|
149
|
+
raise(KXI::Exceptions::VerbExpectedException.new(@verbs.select { |i| i.name }.to_array)) if v == nil
|
150
|
+
verb = @verbs.first { |i| i.name == v.downcase }
|
151
|
+
raise(KXI::Exceptions::VerbExpectedException.new(@verbs.select { |i| i.name }.to_array)) if verb == nil
|
152
|
+
verb.act(*args)
|
153
|
+
end
|
154
|
+
else
|
155
|
+
if @help and hf
|
156
|
+
help
|
157
|
+
else
|
158
|
+
vals = KXI::CLI::ArgumentValues.new(@args.to_array)
|
159
|
+
anon = @args.of_type(KXI::CLI::AnonymousArgument).order_by_descending { |a, b| a.order <=> b.order }
|
160
|
+
|
161
|
+
ar = nil
|
162
|
+
args.each do |val|
|
163
|
+
if val.start_with?('-')
|
164
|
+
raise(KXI::Exceptions::ArgumentException.new(ar.name, 'Expected value!')) if ar != nil
|
165
|
+
raise(KXI::Exceptions::ArgumentException.new(val, 'Invalid syntax!')) if val.start_with?('---')
|
166
|
+
if val.start_with?('--')
|
167
|
+
raise(KXI::Exceptions::ArgumentException.new(val, 'Expected argument name!')) if val.length == 2
|
168
|
+
nm = val[2..val.length - 1].downcase
|
169
|
+
arg = @args.first { |i| i.name == nm }
|
170
|
+
raise(KXI::Exceptions::ArgumentException.new(nm, 'No such argument exists!')) if arg == nil
|
171
|
+
if arg.is_a?(KXI::CLI::FlagArgument)
|
172
|
+
vals.set(arg, true)
|
173
|
+
elsif arg.is_a?(KXI::CLI::NamedArgument)
|
174
|
+
ar = arg
|
175
|
+
else
|
176
|
+
raise(KXI::Exceptions::ArgumentException.new(nm, 'Argument cannot be assigned explicitly!'))
|
177
|
+
end
|
178
|
+
else
|
179
|
+
raise(KXI::Exceptions::ArgumentException.new(val, 'Expected short argument name!')) if val.length == 1
|
180
|
+
nm = val[1]
|
181
|
+
arg = @args.first { |i| i.shortcut == nm }
|
182
|
+
raise(KXI::Exceptions::ArgumentException.new(nm, 'No such argument exists!')) if arg == nil
|
183
|
+
if arg.is_a?(KXI::CLI::FlagArgument)
|
184
|
+
vals.set(arg, true)
|
185
|
+
elsif arg.is_a?(KXI::CLI::NamedArgument)
|
186
|
+
if val.length == 2
|
187
|
+
ar = arg
|
188
|
+
else
|
189
|
+
vals.set(arg, val[2..val.length - 1])
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
else
|
194
|
+
if ar != nil
|
195
|
+
vals.set(ar, val)
|
196
|
+
ar = nil
|
197
|
+
else
|
198
|
+
an = anon.first
|
199
|
+
raise(KXI::Exceptions::NoArgumentException.new(val)) if an == nil
|
200
|
+
vals.set(an, val)
|
201
|
+
anon.remove_at(0)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
if @action == nil
|
206
|
+
raise(KXI::Exceptions::NotImplementedException.new)
|
207
|
+
else
|
208
|
+
vals.finish
|
209
|
+
@action.call(vals)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# Prints help message of verb
|
216
|
+
def help
|
217
|
+
puts(@name)
|
218
|
+
puts("\t#{@desc}")
|
219
|
+
puts
|
220
|
+
puts('Usage:')
|
221
|
+
if @verbs.count == 0
|
222
|
+
print("\t")
|
223
|
+
print("#{@ctx} ") if @ctx != nil
|
224
|
+
print(@name)
|
225
|
+
args = @args.order_by_descending { |a, b| a.order <=> b.order }
|
226
|
+
args.where { |i| i.required? or i.is_a?(KXI::CLI::AnonymousArgument) }.foreach do |i|
|
227
|
+
print(" #{i.syntax}")
|
228
|
+
end
|
229
|
+
puts
|
230
|
+
if args.count > 0
|
231
|
+
puts
|
232
|
+
max = args.max { |a, b| a.headline.length <=> b.headline.length }.headline.length
|
233
|
+
args.foreach do |a|
|
234
|
+
puts("\t#{a.headline.ljust(max)} #{a.description}")
|
235
|
+
end
|
236
|
+
end
|
237
|
+
else
|
238
|
+
max = @verbs.max { |a, b| a.name.length <=> b.name.length }.name.length
|
239
|
+
@verbs.foreach do |v|
|
240
|
+
print("\t")
|
241
|
+
print("#{@ctx} ") if @ctx != nil
|
242
|
+
puts("#{@name} #{v.name.ljust(max)} #{v.description}")
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# Adds argument
|
248
|
+
# @param arg [KXI::CLI::Argument] Argument to add
|
249
|
+
def add_argument(arg)
|
250
|
+
check_name(arg.name)
|
251
|
+
if arg.is_a?(KXI::CLI::ExplicitArgument) and arg.shortcut != nil
|
252
|
+
raise(Exception.new("Short name '#{arg.shortcut}' is already in use!")) if @args.of_type(KXI::CLI::ExplicitArgument).any { |i| i.shortcut == arg.shortcut }
|
253
|
+
end
|
254
|
+
if arg.is_a?(KXI::CLI::AnonymousArgument) and arg.variadic?
|
255
|
+
raise(Exception.new("Verb can have only one variadic anonymous argument! (argument '#{arg.name}')")) if @args.of_type(KXI::CLI::AnonymousArgument).any { |i| i.variadic? }
|
256
|
+
raise(Exception.new("Verb cannot contain both optional and variadic anonymous arguments! (argument '#{arg.name}')")) if @args.of_type(KXI::CLI::AnonymousArgument).any { |i| not i.required? }
|
257
|
+
end
|
258
|
+
@args.add(arg)
|
259
|
+
@verbs.foreach { |i| i.add_argument(arg) }
|
260
|
+
return arg
|
261
|
+
end
|
262
|
+
|
263
|
+
# Adds child verb
|
264
|
+
# @param v [KXI::CLI::Verb] Verb to add
|
265
|
+
def add_verb(v)
|
266
|
+
@args.foreach { |a| v.add_argument(a) }
|
267
|
+
@verbs.add(v)
|
268
|
+
v.enable_help if @help
|
269
|
+
return v
|
270
|
+
end
|
271
|
+
|
272
|
+
def check_name(nm)
|
273
|
+
raise(Exception.new('Name must contain at least two characters!')) if nm == nil or nm.length < 2
|
274
|
+
nm = nm.downcase
|
275
|
+
raise(Exception.new("Name '#{nm}' is already in use!")) unless @verbs.all { |i| i.name != nm } && @args.all { |i| i.name != nm }
|
276
|
+
end
|
277
|
+
|
278
|
+
private :check_name
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|