kxi 1.0.1 → 1.0.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/lib/kxi.rb +44 -39
- data/lib/kxi/application/config.rb +177 -177
- data/lib/kxi/application/config_reader.rb +16 -16
- data/lib/kxi/application/event.rb +35 -35
- data/lib/kxi/application/logger.rb +155 -155
- data/lib/kxi/application/version.rb +106 -74
- data/lib/kxi/application/version_expression.rb +94 -69
- data/lib/kxi/application/workspace.rb +105 -0
- data/lib/kxi/cli/anonymous_argument.rb +50 -50
- data/lib/kxi/cli/argument.rb +56 -56
- data/lib/kxi/cli/argument_values.rb +83 -83
- data/lib/kxi/cli/explicit_argument.rb +38 -38
- data/lib/kxi/cli/flag_argument.rb +15 -15
- data/lib/kxi/cli/named_argument.rb +59 -59
- data/lib/kxi/cli/property_list.rb +57 -48
- data/lib/kxi/cli/table.rb +82 -62
- data/lib/kxi/cli/verb.rb +282 -280
- data/lib/kxi/collections/array_collection.rb +106 -106
- data/lib/kxi/collections/enumerable.rb +527 -527
- data/lib/kxi/collections/enumerator.rb +31 -31
- data/lib/kxi/collections/hash_collection.rb +100 -100
- data/lib/kxi/collections/protected_collection.rb +20 -19
- data/lib/kxi/exceptions/abstract_exception.rb +34 -34
- data/lib/kxi/exceptions/argument_exception.rb +21 -21
- data/lib/kxi/exceptions/collection_exception.rb +13 -13
- data/lib/kxi/exceptions/configuration_exception.rb +36 -25
- data/lib/kxi/exceptions/dimension_mismatch_exception.rb +29 -0
- data/lib/kxi/exceptions/invalid_type_exception.rb +32 -32
- data/lib/kxi/exceptions/no_argument_exception.rb +20 -20
- data/lib/kxi/exceptions/not_implemented_exception.rb +12 -12
- data/lib/kxi/exceptions/out_of_range_exception.rb +43 -43
- data/lib/kxi/exceptions/parse_exception.rb +28 -20
- data/lib/kxi/exceptions/verb_expected_exception.rb +20 -20
- data/lib/kxi/exceptions/workspace_collision_exception.rb +21 -0
- data/lib/kxi/math/math.rb +45 -0
- data/lib/kxi/math/matrix.rb +303 -0
- data/lib/kxi/math/polynomial.rb +141 -101
- data/lib/kxi/math/vector.rb +181 -0
- data/lib/kxi/platform.rb +103 -57
- data/lib/kxi/reflection/stack_frame.rb +80 -80
- data/lib/kxi/version.rb +4 -4
- metadata +8 -3
- data/lib/kxi/exceptions/invalid_operation_exception.rb +0 -11
@@ -1,70 +1,95 @@
|
|
1
|
-
# Created by Matyáš Pokorný on 2018-01-27.
|
2
|
-
|
3
|
-
module KXI
|
4
|
-
module Application
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
1
|
+
# Created by Matyáš Pokorný on 2018-01-27.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module Application
|
5
|
+
# Represents a comparison of two semantic versions
|
6
|
+
class VersionExpression
|
7
|
+
# Equivalence comparison
|
8
|
+
COMP_EQ = '='
|
9
|
+
# Less than or equivalent to comparison
|
10
|
+
COMP_LEQ = '<='
|
11
|
+
# Less than comparison
|
12
|
+
COMP_LT = '<'
|
13
|
+
# Grater than or equivalent to comparison
|
14
|
+
COMP_GEQ = '>='
|
15
|
+
# Grater than comparison
|
16
|
+
COMP_GT = '>'
|
17
|
+
# Minimal requirement comparison
|
18
|
+
COMP_AT = '~>'
|
19
|
+
|
20
|
+
# Get the comparison of versions
|
21
|
+
# @return [string] Comparison of versions
|
22
|
+
def comparison
|
23
|
+
@comp
|
24
|
+
end
|
25
|
+
|
26
|
+
# Gets the major number of left-side version
|
27
|
+
# @return [int] Major number version
|
28
|
+
def major
|
29
|
+
@major
|
30
|
+
end
|
31
|
+
|
32
|
+
# Gets the minor number of left-side version
|
33
|
+
# @return [int,nil] Minor number version
|
34
|
+
def minor
|
35
|
+
@minor
|
36
|
+
end
|
37
|
+
|
38
|
+
# Gets the patch number of left-side version
|
39
|
+
# @return [int,nil] Patch number version
|
40
|
+
def patch
|
41
|
+
@patch
|
42
|
+
end
|
43
|
+
|
44
|
+
# Instantiates the {KXI::Application::VersionExpression} class
|
45
|
+
# @param [string] comp Comparison rule of expression
|
46
|
+
# @param [int] major Major number of left-side version
|
47
|
+
# @param [int,nil] minor Minor number of left-side version
|
48
|
+
# @param [int,nil] patch Patch number of left-side version
|
49
|
+
def initialize(comp, major, minor = nil, patch = nil)
|
50
|
+
@comp = comp
|
51
|
+
@major = major
|
52
|
+
@minor = minor
|
53
|
+
@patch = patch
|
54
|
+
@target = KXI::Application::Version.new(major, minor == nil ? 0 : minor, patch == nil ? 0 : patch)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Checks whether expression is true for given version
|
58
|
+
# @param ver [KXI::Application::Version] Right-side version of expression
|
59
|
+
# @return [bool] True if expression is valid; otherwise false
|
60
|
+
def matches?(ver)
|
61
|
+
case @comp
|
62
|
+
when COMP_EQ
|
63
|
+
return (
|
64
|
+
ver.major == @major and
|
65
|
+
ver.minor == (@minor == nil ? 0 : @minor) and
|
66
|
+
ver.patch == (@patch == nil ? 0 : @patch)
|
67
|
+
)
|
68
|
+
when COMP_AT
|
69
|
+
return (
|
70
|
+
ver.major == @major and
|
71
|
+
(@minor == nil or ver.minor == @minor) and
|
72
|
+
(@patch == nil or ver.patch == @patch)
|
73
|
+
)
|
74
|
+
when COMP_GEQ
|
75
|
+
return ver >= @target
|
76
|
+
when COMP_LEQ
|
77
|
+
return ver <= @target
|
78
|
+
when COMP_GT
|
79
|
+
return ver > @target
|
80
|
+
when COMP_LT
|
81
|
+
return ver < @target
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Parses a version expression from its string form
|
86
|
+
# @param [string] str String representation of version expression
|
87
|
+
# @return [KXI::Application::VersionExpression] Version expression equivalent to given string
|
88
|
+
def self.parse(str)
|
89
|
+
m = /^\s*(?'cm'>|<|>=|<=|=|~>)\s*(?'mj'\d+)\s*(\.\s*(?'mi'\d+))?\s*(\.\s*(?'pt'\d+))?\s*?$/m.match(str)
|
90
|
+
raise(KXI::Exceptions::ParseException.new('version expression', str)) if m == nil
|
91
|
+
return VersionExpression.new(m['cm'], m['mj'].to_i, m['mi']&.to_i, m['pt']&.to_i)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
70
95
|
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# Created by Matyáš Pokorný on 2018-03-23.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module Application
|
5
|
+
# Represents a workspace (directory)
|
6
|
+
class Workspace
|
7
|
+
# Instantiates the {KXI::Application::Workspace} class
|
8
|
+
# @param path [String] Path to workspace
|
9
|
+
# @param mk [Bool] True if workspace should be created; otherwise false
|
10
|
+
def initialize(path, mk = false)
|
11
|
+
@path = File.expand_path(path)
|
12
|
+
validate
|
13
|
+
make if mk
|
14
|
+
end
|
15
|
+
|
16
|
+
# Gets path relative to this workspace
|
17
|
+
# @param path [String] Parts of path
|
18
|
+
# @return [String] The combined path
|
19
|
+
def path(*path)
|
20
|
+
return @path if path.length == 0
|
21
|
+
return File.expand_path(File.join(@path, *path))
|
22
|
+
end
|
23
|
+
|
24
|
+
# Obtains the parent of this workspace, if it exists
|
25
|
+
# @return [KXI::Application::Workspace, nil] Parent workspace if any; nil otherwise
|
26
|
+
def parent
|
27
|
+
dir = File.dirname(@path)
|
28
|
+
return nil if KXI::Platform.this.path_case_sensitive? ? dir == @path : dir.downcase == @path.downcase
|
29
|
+
return KXI::Application::Workspace.new(dir)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Checks if workspace physically exists in the file system
|
33
|
+
# @return [Bool] True if workspace exists; false otherwise
|
34
|
+
def made?
|
35
|
+
validate
|
36
|
+
return Dir.exists?(@path)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Creates the workspace, if it doesn't exist
|
40
|
+
def make
|
41
|
+
validate
|
42
|
+
return if made?
|
43
|
+
p = parent
|
44
|
+
p.make unless parent == nil
|
45
|
+
Dir.mkdir(@path)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Gets a child workspace
|
49
|
+
# @param [String] path Path to child workspace
|
50
|
+
# @return [KXI::Application::Workspace] Child workspace
|
51
|
+
def inner(*path)
|
52
|
+
return KXI::Application::Workspace.new(path(*path))
|
53
|
+
end
|
54
|
+
|
55
|
+
# Opens a file withing the workspace
|
56
|
+
# @overload open(mode, *path)
|
57
|
+
# @param mode [String] IO mode to open the file with
|
58
|
+
# @param path [String] Path to desired file
|
59
|
+
# @return [IO] File handle
|
60
|
+
# @overload open(mode, *path)
|
61
|
+
# @param mode [String] IO mode to open the file with
|
62
|
+
# @param path [String] Path to desired file
|
63
|
+
# @yield [handle] Block where file is used
|
64
|
+
# @yieldparam handle [IO] Handle of block
|
65
|
+
def open(mode, *path)
|
66
|
+
h = File.open(path(*path), mode)
|
67
|
+
return h unless block_given?
|
68
|
+
begin
|
69
|
+
yield(h)
|
70
|
+
ensure
|
71
|
+
h.flush
|
72
|
+
h.close
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Preforms lookup of files (glob)
|
77
|
+
# @param ptt [String, nil] Pattern for searching, returns all files if nil
|
78
|
+
# @param rec [Bool] Determines weather search is recursive
|
79
|
+
# @return [Array<String>] Found files
|
80
|
+
def files(ptt = nil, rec = true)
|
81
|
+
ptt = '*' if ptt == nil
|
82
|
+
ptt = File.join('**', ptt) if rec
|
83
|
+
return Dir.glob(path(ptt), File::FNM_DOTMATCH).select { |i| File.exists?(i) and not File.directory?(i) }.collect { |i| File.expand_path(i) }
|
84
|
+
end
|
85
|
+
|
86
|
+
# Preforms lookup of directories (glob)
|
87
|
+
# @param ptt [String, nil] Pattern for searching, returns all directories if nil
|
88
|
+
# @param rec [Bool] Determines weather search is recursive
|
89
|
+
# @return [Array<String>] Found directories
|
90
|
+
def dirs(ptt = nil, rec = true)
|
91
|
+
ptt = '*' if ptt == nil
|
92
|
+
ptt = File.join('**', ptt) if rec
|
93
|
+
return Dir.glob(path(ptt), File::FNM_DOTMATCH).select { |i| File.exists?(i) and File.directory?(i) }.collect { |i| File.expand_path(i) }
|
94
|
+
end
|
95
|
+
|
96
|
+
# Validates path of workspace
|
97
|
+
# @raise [KXI::Exceptions::WorkspaceCollisionException] If workspace path is used by file
|
98
|
+
def validate
|
99
|
+
raise(KXI::Exceptions::WorkspaceCollisionException.new(@path)) if File.exists?(@path) and not File.directory?(@path)
|
100
|
+
end
|
101
|
+
|
102
|
+
private :validate
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -1,51 +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
|
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
51
|
end
|
data/lib/kxi/cli/argument.rb
CHANGED
@@ -1,57 +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
|
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
57
|
end
|