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.
@@ -0,0 +1,101 @@
1
+ # Created by Matyáš Pokorný on 2017-12-29.
2
+
3
+ module KXI
4
+ module Collections
5
+ # Makes hash enumerable.
6
+ # Every key-value pair of hash is represented by {KXI::Collections::HashCollection::HashEnumerator::KeyValuePair} class
7
+ class HashCollection < KXI::Collections::Enumerable
8
+ # Instantiates the {KXI::Collections::HashCollection} class
9
+ # @param hash [Hash] Hash for enumeration
10
+ def initialize(hash)
11
+ super()
12
+ @hash = hash
13
+ end
14
+
15
+ # Creates a new {KXI::Collections::Enumerator} bound to this instance
16
+ # @return [KXI::Collections::Enumerator] Enumerator bound to this instance
17
+ def create_enumerator
18
+ HashEnumerator.new(@hash)
19
+ end
20
+
21
+ # Gets value from hash at given key
22
+ # @param key [Object] Key of value to obtain
23
+ # @return [Object] Obtained value
24
+ def [](key)
25
+ lock do
26
+ return @hash[key]
27
+ end
28
+ end
29
+
30
+ # Sets value to hash at given key
31
+ # @param key [Object] Key of pair to set
32
+ # @param value [Object] Value to set the pair to
33
+ # @return [Object] Given value
34
+ def []=(key, value)
35
+ lock(true) do
36
+ @hash[key] = value
37
+ end
38
+ return value
39
+ end
40
+
41
+ # Enumerates hash as key-value pairs represented by the {KXI::Collections::HashCollection::HashEnumerator::KeyValuePair} class
42
+ class HashEnumerator < KXI::Collections::Enumerator
43
+ # Instantiates the {KXI::Collections::HashCollection::HashEnumerator} class
44
+ # @param hash [Hash] Hash for enumeration
45
+ def initialize(hash)
46
+ @hash = hash
47
+ @keys = hash.keys
48
+ @current = 0
49
+ end
50
+
51
+ # Selects first item in collection
52
+ # @return [Bool] True if collection contains elements; otherwise false
53
+ def rewind
54
+ @current = 0
55
+ return @keys.length > 0
56
+ end
57
+
58
+ # Advances enumerator to next item
59
+ # @return [Bool] True if item is available; false otherwise
60
+ # @raise [KXI::Exceptions::AbstractException] When method is not implemented in superclass
61
+ def next
62
+ @current += 1
63
+ return @keys.length > @current
64
+ end
65
+
66
+ # Returns current item
67
+ # @return [Object] Current item
68
+ # @raise [KXI::Exceptions::AbstractException] When method is not implemented in superclass
69
+ def current
70
+ k = @keys[@current]
71
+ KeyValuePair.new(k, @hash[k])
72
+ end
73
+
74
+ # Represents a key-value pair
75
+ class KeyValuePair
76
+ # Returns the key of pair
77
+ # @return [Object] Key of pair
78
+ def key
79
+ @key
80
+ end
81
+
82
+ # Returns the value of pair
83
+ # @return [Object] Value of pair
84
+ def value
85
+ @val
86
+ end
87
+
88
+ # Instantiates the {KXI::Collections::HashCollection::HashEnumerator::KeyValuePair} class
89
+ # @param k [Object] Key of pair
90
+ # @param v [Object] Value of pair
91
+ def initialize(k, v)
92
+ @key = k
93
+ @val = v
94
+ end
95
+ end
96
+ end
97
+
98
+ protected :create_enumerator
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,20 @@
1
+ # Created by Matyáš Pokorný on 2018-01-20.
2
+
3
+ module KXI
4
+ module Collections
5
+ class ProtectedCollection < KXI::Collections::Enumerable
6
+ # Instantiates the {KXI::Collections::ArrayCollection} class
7
+ # @param enum [KXI::Collections::Enumerable] Protected enumerable
8
+ def initialize(enum = [])
9
+ super()
10
+ @enum = enum
11
+ end
12
+
13
+ # Creates a new {KXI::Collections::Enumerator} bound to this instance
14
+ # @return [KXI::Collections::Enumerator] Enumerator bound to this instance
15
+ def create_enumerator
16
+ @enum.create_enumerator
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ # Created by Matyáš Pokorný on 2017-12-28.
2
+ module KXI
3
+ module Exceptions
4
+ # Raised when method that was supposed to be implemented by super class wasn't
5
+ class AbstractException < Exception
6
+ # Returns the abstract class
7
+ # @return [Class] Abstract class
8
+ def class
9
+ @class
10
+ end
11
+
12
+ # Returns the file that contains the abstract class
13
+ # @return [String] Path of file that contains the abstract class
14
+ def file
15
+ @file
16
+ end
17
+
18
+ # Returns name of the abstract method
19
+ # @return [String] Name of the abstract method
20
+ def method
21
+ @mtd
22
+ end
23
+
24
+ # Instantiates the {KXI::Exceptions::AbstractException} class
25
+ # @param cl [Class] Abstract class
26
+ def initialize(cl)
27
+ frame = Reflection::StackFrame.callstack(3).first
28
+ @file = frame.file
29
+ @mtd = frame.method
30
+ super("Abstract method #{cl.name}##{@mtd} wasn't implemented!")
31
+ @class = cl
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,22 @@
1
+ # Created by Matyáš Pokorný on 2018-01-20.
2
+
3
+ module KXI
4
+ module Exceptions
5
+ # Raised when command-line parser encounters an error
6
+ class ArgumentException < Exception
7
+ # Get the name of argument
8
+ # @return [String] Name of argument
9
+ def argument
10
+ @arg
11
+ end
12
+
13
+ # Instantiates the {KXI::Exceptions::ArgumentException} class
14
+ # @param arg [String] Name of argument
15
+ # @param msg [String] Error message
16
+ def initialize(arg, msg)
17
+ super("<#{arg}> #{msg}")
18
+ @arg = arg
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ # Created by Matyáš Pokorný on 2017-12-28.
2
+
3
+ module KXI
4
+ module Exceptions
5
+ # Raised when collection encounters an error
6
+ class CollectionException < Exception
7
+ # Instantiates the {KXI::Exceptions::CollectionException} class
8
+ # @param msg [String] Exception message
9
+ def initialize(msg)
10
+ super(msg)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,33 @@
1
+ # Created by Matyáš Pokorný on 2017-12-30.
2
+
3
+ module KXI
4
+ module Exceptions
5
+ # Raised when some value is of unexpected type
6
+ class InvalidTypeException < Exception
7
+ # Returns expected types
8
+ # @return [Array<Class>] Expected types
9
+ def expected
10
+ @exp
11
+ end
12
+
13
+ # Returns actual type
14
+ # @return [Class] Actual type
15
+ def actual
16
+ @act
17
+ end
18
+
19
+ # Instantiates the [KXI::Exceptions::InvalidTypeException] class
20
+ # @param exp [Array<Class>] Expected types
21
+ # @param act [Class] Actual type
22
+ def initialize(act, *exp)
23
+ if exp.length == 1
24
+ super("Value is of unexpected type! Expected <#{exp[0].name}> got <#{act.name}>")
25
+ else
26
+ super("Value is of unexpected type! Expected { #{exp.collect {|i| "<#{i}>"}.join(', ')} } got <#{act.name}>")
27
+ end
28
+ @exp = exp
29
+ @act = act
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ # Created by Matyáš Pokorný on 2018-01-21.
2
+
3
+ module KXI
4
+ module Exceptions
5
+ # Raised when argument value has no binding argument
6
+ class NoArgumentException < Exception
7
+ # Gets the erroneous value
8
+ # @return [String] Erroneous value
9
+ def value
10
+ @val
11
+ end
12
+
13
+ # Instantiates the {KXI::Exceptions::NoArgumentException} class
14
+ # @param val [String] Erroneous value
15
+ def initialize(val)
16
+ super("Value '#{val}' has no argument to bind to!")
17
+ @val = val
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ # Created by Matyáš Pokorný on 2017-12-29.
2
+
3
+ module KXI
4
+ module Exceptions
5
+ # Raised when given part of code isn't yet implemented
6
+ class NotImplementedException < Exception
7
+ # Instantiates the {KXI::Exceptions::NotImplementedException} class
8
+ def initialize
9
+ super('Code not implemented yet!')
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,44 @@
1
+ # Created by Matyáš Pokorný on 2017-12-29.
2
+
3
+ module KXI
4
+ module Exceptions
5
+ # Raised when certain value is out of range
6
+ class OutOfRangeException < Exception
7
+ # Returns erroneous value
8
+ # @return [Object] Erroneous value
9
+ def value
10
+ @val
11
+ end
12
+
13
+ # Returns minimal expected value
14
+ # @return [Object, nil] Minimal expected value; nil if there is no minimum
15
+ def minimum
16
+ @min
17
+ end
18
+
19
+ # Returns maximal expected value
20
+ # @return [Object, nil] Maximal expected value; nil if there is no maximum
21
+ def maximum
22
+ @max
23
+ end
24
+
25
+ # Instantiates the {KXI::Exceptions::OutOfRangeException} class
26
+ # @param val [Object] Erroneous value
27
+ # @param min [Object, nil] Minimal expected value; nil if there is no minimum
28
+ # @param max [Object, nil] Maximal expected value; nil if there is no maximum
29
+ # @note If both min and max are nil, then range is empty set
30
+ def initialize(val, min = nil, max = nil)
31
+ if min == nil and max == nil
32
+ super("Value '#{val}' is out of range {}!")
33
+ elsif min == max
34
+ super("Value '#{val}' is out of range {#{min}}!")
35
+ else
36
+ super("Value '#{val}' is out of range #{(min == nil ? '(-∞' : "<#{min}")};#{(max == nil ? '∞)' : "#{max}>")}!")
37
+ end
38
+ @val = val
39
+ @min = min
40
+ @max = max
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ # Created by Matyáš Pokorný on 2018-01-21.
2
+
3
+ module KXI
4
+ module Exceptions
5
+ # Raised when specific verb was expected
6
+ class VerbExpectedException < Exception
7
+ # Gets array of verbs that were expected
8
+ # @return [Array<String>] Expected verbs
9
+ def verbs
10
+ @verbs
11
+ end
12
+
13
+ # Instantiates the {KXI::CLI::VerbExpectedException} class
14
+ # @param verbs [Array<String>] Expected verbs
15
+ def initialize(verbs)
16
+ super("Expected verb! (#{verbs.join(', ')})")
17
+ @verbs = verbs
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,81 @@
1
+ # Created by Matyáš Pokorný on 2017-12-28.
2
+ module KXI
3
+ module Reflection
4
+ # Represents frame of call stack
5
+ class StackFrame
6
+ # Returns the file of frame
7
+ # @return [String] File of frame
8
+ def file
9
+ @file
10
+ end
11
+
12
+ # Returns the line number of frame
13
+ # @return [Number] Line number of frame
14
+ def line
15
+ @line
16
+ end
17
+
18
+ # Returns the context of frame
19
+ # @return [String] Context of frame
20
+ def context
21
+ @context
22
+ end
23
+
24
+ # Indicates whether frame is block
25
+ # @return [Bool] True if stack frame represents call to block; false otherwise
26
+ def block?
27
+ @block != nil
28
+ end
29
+
30
+ # Returns containing method of frame; nil if none
31
+ # @return [String, nil] Name of method that the stack frame represents
32
+ def method
33
+ return nil if @block != nil and @block[0] == '<' and @block[@block.length - 1] == '>'
34
+ return @block unless @block == nil
35
+ return nil if @context[0] == '<' and @context[@context.length - 1] == '>'
36
+ @context
37
+ end
38
+
39
+ # Instantiates the {KXI::Reflection::StackFrame} class
40
+ # @param file [String] File of frame
41
+ # @param line [Number] Line number of frame
42
+ # @param context [String, nil] Context of frame
43
+ def initialize(file, line, context = nil)
44
+ @file = file
45
+ @line = line
46
+ @context = context
47
+ if context == nil
48
+ @block = nil
49
+ else
50
+ mt = /^block (\((?'levels'\d+) levels\) )?in (?'method'.+)$/mi.match(context)
51
+ @block = mt == nil ? nil : mt['method']
52
+ end
53
+ end
54
+
55
+ # Converts class to string
56
+ # @return [String] Equivalent string
57
+ def to_s
58
+ "#{@file}:#{@line}#{(@context != nil ? ": in `#{@context}'" : '')}"
59
+ end
60
+
61
+ # Parses callstack into array of {KXI::Reflection::StackFrame}
62
+ # @param skip [Number] Number of callstack records to ignore
63
+ # @return [Array<KXI::Reflection::StackFrame>] Equivalent array of stack frames
64
+ def self.callstack(skip = 1)
65
+ ret = []
66
+ caller(skip).each do |bt|
67
+ ret.push(from_backtrace(bt))
68
+ end
69
+ return ret
70
+ end
71
+
72
+ # Parses backtrace line into {KXI::Reflection::StackFrame}
73
+ # @param bt [String] Backtrace line
74
+ # @return [KXI::Reflection::StackFrame] Equivalent stack frame
75
+ def self.from_backtrace(bt)
76
+ mt = /(?'file'.+?):(?'line'\d+)(:\s*in\s*`(?'context'.+?)')?/.match(bt)
77
+ StackFrame.new(mt['file'], mt['line'].to_i, mt['context'])
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,4 @@
1
+ module KXI
2
+ # Version of KXI
3
+ VERSION = '1.0.0'
4
+ end
data/lib/kxi.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'kxi/version'
2
+ require 'kxi/exceptions/abstract_exception'
3
+ require 'kxi/exceptions/collection_exception'
4
+ require 'kxi/exceptions/out_of_range_exception'
5
+ require 'kxi/exceptions/not_implemented_exception'
6
+ require 'kxi/exceptions/argument_exception'
7
+ require 'kxi/exceptions/no_argument_exception'
8
+ require 'kxi/exceptions/verb_expected_exception'
9
+ require 'kxi/exceptions/invalid_type_exception'
10
+ require 'kxi/reflection/stack_frame'
11
+ require 'kxi/collections/enumerator'
12
+ require 'kxi/collections/enumerable'
13
+ require 'kxi/collections/array_collection'
14
+ require 'kxi/collections/hash_collection'
15
+ require 'kxi/collections/protected_collection'
16
+ require 'kxi/cli/argument'
17
+ require 'kxi/cli/explicit_argument'
18
+ require 'kxi/cli/anonymous_argument'
19
+ require 'kxi/cli/flag_argument'
20
+ require 'kxi/cli/named_argument'
21
+ require 'kxi/cli/argument_values'
22
+ require 'kxi/cli/verb'
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kxi
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Matyáš Pokorný
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-01-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest-reporters
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.7'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.7'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.15'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.15'
97
+ - !ruby/object:Gem::Dependency
98
+ name: yard
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.9'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.9'
111
+ description: A collection of classes to help with development of Ruby applications
112
+ email:
113
+ - matyaspoko@live.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - lib/kxi.rb
119
+ - lib/kxi/cli/anonymous_argument.rb
120
+ - lib/kxi/cli/argument.rb
121
+ - lib/kxi/cli/argument_values.rb
122
+ - lib/kxi/cli/explicit_argument.rb
123
+ - lib/kxi/cli/flag_argument.rb
124
+ - lib/kxi/cli/named_argument.rb
125
+ - lib/kxi/cli/verb.rb
126
+ - lib/kxi/collections/array_collection.rb
127
+ - lib/kxi/collections/enumerable.rb
128
+ - lib/kxi/collections/enumerator.rb
129
+ - lib/kxi/collections/hash_collection.rb
130
+ - lib/kxi/collections/protected_collection.rb
131
+ - lib/kxi/exceptions/abstract_exception.rb
132
+ - lib/kxi/exceptions/argument_exception.rb
133
+ - lib/kxi/exceptions/collection_exception.rb
134
+ - lib/kxi/exceptions/invalid_type_exception.rb
135
+ - lib/kxi/exceptions/no_argument_exception.rb
136
+ - lib/kxi/exceptions/not_implemented_exception.rb
137
+ - lib/kxi/exceptions/out_of_range_exception.rb
138
+ - lib/kxi/exceptions/verb_expected_exception.rb
139
+ - lib/kxi/reflection/stack_frame.rb
140
+ - lib/kxi/version.rb
141
+ homepage: https://github.com/cryocz/kxi
142
+ licenses:
143
+ - MIT
144
+ metadata: {}
145
+ post_install_message:
146
+ rdoc_options: []
147
+ require_paths:
148
+ - lib
149
+ required_ruby_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ required_rubygems_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ requirements: []
160
+ rubyforge_project:
161
+ rubygems_version: 2.6.13
162
+ signing_key:
163
+ specification_version: 4
164
+ summary: Classes for Ruby survival
165
+ test_files: []