kxi 1.0.0 → 1.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a376bd573bfb44dbeae16f773f883a1f55daedd7
4
- data.tar.gz: 4cbb2897d3c73fe15b882a26d79f8d3bdc387244
3
+ metadata.gz: 78e859a6e89e40dbab305b79851a257dfd2ddf68
4
+ data.tar.gz: aedb9bc1385418141e79d90d64fe688c00e529d4
5
5
  SHA512:
6
- metadata.gz: 7d040d8a1a051f68268ba981ea84e69fcf5bd547f801c3411511bcb3b3edd2da4e23befcb9171fe6b43655bdd2adca2ef6b8de387fa5874f8d8b76b79cbabac7
7
- data.tar.gz: c35695494016d0625076379ffcc9370e5c4299cc47cc19f4979d10ee0cd4f9ac01c3d4f3e27051f1c2859c18a4099aa830324545fb1ef0d0ab45ec671c405ed8
6
+ metadata.gz: 856340dde06a8e744284dfb3060eb69a053f90868338ce3b7034163750c566f8c0f60cbc67c59b73ee0c9666b18cbe1e808afcb22d84cba58a0f49593c5517ce
7
+ data.tar.gz: 10ee0e919f19ea968f65220714bc2a5be7a42cc4f2d59999c40b5c02ab0300da8974c54b814b977b9e7ff7cd86c2df0a7137e9110066169c499f618cf64b3702
@@ -0,0 +1,178 @@
1
+ # Created by Matyáš Pokorný on 2018-01-24.
2
+
3
+ module KXI
4
+ module Application
5
+ # Represents configuration file
6
+ class Config
7
+ # Gets configuration file
8
+ # @return [String] Path to configuration file
9
+ def file
10
+ @file
11
+ end
12
+
13
+ # Instantiates the {KXI::Application::Config} file
14
+ # @param file [String] Configuration file to read
15
+ # @param reader [KXI::Application::ConfigReader] Readers used to parse configuration
16
+ def initialize(file, reader)
17
+ @file = file
18
+ @obj = reader.parse(File.read(file))
19
+ @pth = ''
20
+ @def = false
21
+ end
22
+
23
+ # Gets current context
24
+ # @return [Object] Current context
25
+ def context
26
+ @obj
27
+ end
28
+
29
+ # Gets path of current context
30
+ # @return [String] Path of current context
31
+ def path
32
+ @pth
33
+ end
34
+
35
+ # Gets value or default from current context
36
+ # @param key [String] Name of value
37
+ # @param default [Object, nil] Default value
38
+ # @yield [val] Validator function
39
+ # @yieldparam val [Object, nil] Value to validate
40
+ # @return [Object, nil] Value or default
41
+ def get(key, default = nil, &validator)
42
+ if not @def and @obj.key?(key)
43
+ ctx = @obj[key]
44
+ return ctx if validator == nil
45
+ return validate(key, ctx, &validator)
46
+ else
47
+ return default
48
+ end
49
+ end
50
+
51
+ # Gets value from current context
52
+ # @param key [String] Name of value
53
+ # @yield [val] Validator function
54
+ # @yieldparam val [Object, nil] Value to validate
55
+ # @return [Object, nil] Value
56
+ # @raise [KXI::Exceptions::ConfigurationException] Raised when field is not found
57
+ def get!(key, &validator)
58
+ if not @def and @obj.key?(key)
59
+ ctx = @obj[key]
60
+ return ctx if validator == nil
61
+ return validate(key, ctx, &validator)
62
+ else
63
+ raise(KXI::Exceptions::ConfigurationException.new(@file, "#{@pth}/#{key}", 'Field is mandatory!'))
64
+ end
65
+ end
66
+
67
+ # Enters named section of configuration file
68
+ # @param key [String] Name of section
69
+ # @param man [Bool] Determines whether this section is mandatory
70
+ # @yield [] Block of actions for entered context
71
+ def inside(key, man = false, &block)
72
+ if not @def and @obj.key?(key)
73
+ ctx = @obj[key]
74
+ raise(KXI::Exceptions::ConfigurationException.new(@file, "#{@pth}/#{key}", 'Field must be object!')) unless ctx.is_a?(Hash)
75
+ enter(key, ctx) do
76
+ block.call
77
+ end
78
+ elsif man
79
+ raise(KXI::Exceptions::ConfigurationException.new(@file, "#{@pth}/#{key}", 'Object is mandatory!'))
80
+ else
81
+ enter(key, nil) do
82
+ if @def
83
+ block.call
84
+ else
85
+ @def = true
86
+ block.call
87
+ @def = false
88
+ end
89
+ end
90
+ end
91
+ end
92
+
93
+ # Enters mandatory named section of configuration file
94
+ # @param key [String] Name of section
95
+ # @yield [] Block of actions for entered context
96
+ def inside!(key, &block)
97
+ inside(key, true) { block.call }
98
+ end
99
+
100
+ # Iterates through collection
101
+ # @param key [String] Name of collection
102
+ # @param man [Bool] Determines whether this section is mandatory
103
+ # @yield [] Block of actions for entered context
104
+ def each_index(key, man = false, &block)
105
+ if not @def and @obj.key?(key)
106
+ ctx = @obj[key]
107
+ raise(KXI::Exceptions::ConfigurationException.new(@file, "#{@pth}/#{key}", 'Field must be array!')) unless ctx.is_a?(Array)
108
+ ctx.each_with_index do |itm, idx|
109
+ enter("#{key}[#{idx}]", itm) do
110
+ block.call
111
+ end
112
+ end
113
+ elsif man
114
+ raise(KXI::Exceptions::ConfigurationException.new(@file, "#{@pth}/#{key}", 'Array is mandatory!'))
115
+ end
116
+ end
117
+
118
+ # Iterates through mandatory collection
119
+ # @param key [String] Name of collection
120
+ # @yield [] Block of actions for entered context
121
+ def each_index!(key, &block)
122
+ each_index(key, true) { block.call }
123
+ end
124
+
125
+ # Iterates through fields of object
126
+ # @param key [String] Name of object
127
+ # @param man [Bool] Determines whether this section is mandatory
128
+ # @yield [idx] Block of actions for entered context
129
+ # @yieldparam idx [String] Name of field
130
+ def each_field(key, man = false, &block)
131
+ if not @def and @obj.key?(key)
132
+ ctx = @obj[key]
133
+ raise(KXI::Exceptions::ConfigurationException.new(@file, "#{@pth}/#{key}", 'Field must be object!')) unless ctx.is_a?(Hash)
134
+ ctx.each_pair do |idx, itm|
135
+ enter("#{key}/#{idx}", itm) do
136
+ block.call(idx)
137
+ end
138
+ end
139
+ elsif man
140
+ raise(KXI::Exceptions::ConfigurationException.new(@file, "#{@pth}/#{key}", 'Object is mandatory!'))
141
+ end
142
+ end
143
+
144
+ # Iterates through fields of mandatory object
145
+ # @param key [String] Name of object
146
+ # @yield [idx] Block of actions for entered context
147
+ # @yieldparam idx [String] Name of field
148
+ def each_field!(key, &block)
149
+ each_field(key, true) { |itm| block.call(itm) }
150
+ end
151
+
152
+ def enter(key, ctx, &block)
153
+ obj = @obj
154
+ pth = @pth
155
+ @obj = ctx
156
+ @pth = "#{@pth}/#{key}"
157
+ block.call
158
+ ensure
159
+ @pth = pth
160
+ @obj = obj
161
+ end
162
+
163
+ def validate(key, ctx, &validator)
164
+ begin
165
+ enter(key, ctx) do
166
+ validator.call(ctx)
167
+ end
168
+ return ctx
169
+ rescue Exception => ex
170
+ raise(KXI::Exceptions::ConfigurationException.new(@file, "#{@pth}/#{key}", ex.message))
171
+ end
172
+ end
173
+
174
+ protected :context, :path, :get, :get!, :inside, :inside!, :each_index, :each_index!, :each_field, :each_field!
175
+ private :enter, :validate
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,17 @@
1
+ # Created by Matyáš Pokorný on 2018-01-24.
2
+
3
+ module KXI
4
+ module Application
5
+ # Parses configuration
6
+ # @abstract
7
+ class ConfigReader
8
+ # Parses configuration from file
9
+ # @param str [String] Data to parse
10
+ # @return [Hash] Parsed configuration
11
+ # @abstract
12
+ def parse(str)
13
+ raise(KXI::Exceptions::AbstractException.new(KXI::Application::ConfigReader))
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ # Created by Matyáš Pokorný on 2018-01-26.
2
+
3
+ module KXI
4
+ module Application
5
+ # Event handler
6
+ class Event
7
+ # Adds hook to handler
8
+ # @return [Number] Id of hook
9
+ # @yield [sender, *args] Action block of hook
10
+ # @yieldparam sender [Object] Invoker of event
11
+ # @yieldparam args [Array<Object, nil>] Arguments of invocation
12
+ def add(&block)
13
+ @hooks.push(block)
14
+ return @hooks.length - 1
15
+ end
16
+
17
+ # Removes hook from handler
18
+ # @param id [Number] Id of hook to remove
19
+ def remove(id)
20
+ @hooks.delete_at(id)
21
+ end
22
+
23
+ # Instantiates the {KXI::Application::Event} class
24
+ def initialize
25
+ @hooks = []
26
+ end
27
+
28
+ # Invokes all hooks
29
+ # @param sender [Object] Invoker of event
30
+ # @param args [Array<Object, nil>] Arguments of invocation
31
+ def fire(sender, *args)
32
+ @hooks.each { |h| h.call(sender, *args) }
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,156 @@
1
+ # Created by Matyáš Pokorný on 2018-01-26.
2
+
3
+ module KXI
4
+ module Application
5
+ # Allows simple unstructured (time-independent) logging
6
+ class Logger
7
+ # Gets the message event
8
+ # @return [KXI::Application::Event] Message event
9
+ def on_message
10
+ @event
11
+ end
12
+
13
+ # Attaches action to message event
14
+ # @param min [KXI::Application::Logger::Message::Severity] Minimal severity of message
15
+ # @yield [msg] Event action
16
+ # @yieldparam msg [KXI::Application::Logger::Message] Logger message
17
+ # @return [Number] Id of event hook
18
+ def attach(min = Message::Severity::COMMAND, &block)
19
+ return @event.add { |s, msg| block.call(msg) if msg.severity.level >= min.level }
20
+ end
21
+
22
+ # Instantiates the {KXI::Application::Logger} class
23
+ def initialize
24
+ @event = KXI::Application::Event.new
25
+ @start = DateTime.now
26
+ end
27
+
28
+ # Logs message with the {KXI::Application::Logger::Message::Severity::COMMAND} severity
29
+ # @param cmd [String] Executed command
30
+ def command(cmd)
31
+ log(Message::Severity::COMMAND, cmd)
32
+ end
33
+
34
+ # Logs message with the {KXI::Application::Logger::Message::Severity::TRACE} severity
35
+ # @param msg [String] Text of message
36
+ def trace(msg)
37
+ log(Message::Severity::TRACE, msg)
38
+ end
39
+
40
+ # Logs message with the {KXI::Application::Logger::Message::Severity::DEBUG} severity
41
+ # @param msg [String] Text of message
42
+ def debug(msg)
43
+ log(Message::Severity::DEBUG, msg)
44
+ end
45
+
46
+ # Logs message with the {KXI::Application::Logger::Message::Severity::INFO} severity
47
+ # @param msg [String] Text of message
48
+ def info(msg)
49
+ log(Message::Severity::INFO, msg)
50
+ end
51
+
52
+ # Logs message with the {KXI::Application::Logger::Message::Severity::WARNING} severity
53
+ # @param msg [String] Text of message
54
+ def warning(msg)
55
+ log(Message::Severity::WARNING, msg)
56
+ end
57
+
58
+ # Logs message with the {KXI::Application::Logger::Message::Severity::ERROR} severity
59
+ # @param msg [String] Text of message
60
+ def error(msg)
61
+ log(Message::Severity::ERROR, msg)
62
+ end
63
+
64
+ # Logs message with the {KXI::Application::Logger::Message::Severity::FATAL} severity
65
+ # @param msg [String] Text of message
66
+ def fatal(msg)
67
+ log(Message::Severity::FATAL, msg)
68
+ end
69
+
70
+ def log(severity, msg)
71
+ now = DateTime.now
72
+ @event.fire(self, Message.new(severity, now - @start, now, msg))
73
+ end
74
+
75
+ private :log
76
+
77
+ # Represents a log message
78
+ class Message
79
+ # Represents severity of message
80
+ class Severity
81
+ # Gets the name of severity
82
+ # @return [String] Name of severity
83
+ def name
84
+ @name
85
+ end
86
+
87
+ # Gets the level of severity
88
+ # @return [Number] Level of severity
89
+ def level
90
+ @lvl
91
+ end
92
+
93
+ # Instantiates the [KXI::Application::Logger::Message::Severity] class
94
+ # @param nm [String] Name of severity
95
+ # @param lvl [Number] Level of severity
96
+ def initialize(nm, lvl)
97
+ @name = nm
98
+ @lvl = lvl
99
+ end
100
+
101
+
102
+ # Severity of messages that log execution of external commands
103
+ COMMAND = Severity.new('command', 0)
104
+ # Severity of messages that allow tracing of execution paths
105
+ TRACE = Severity.new('trace', 1)
106
+ # Severity of messages used for debugging
107
+ DEBUG = Severity.new('debug', 2)
108
+ # Severity of messages that user should know about
109
+ INFO = Severity.new('info', 3)
110
+ # Severity of messages that notify about something that might lead in future to problems
111
+ WARNING = Severity.new('warning', 4)
112
+ # Severity of messages that notify about problems that application can recover from
113
+ ERROR = Severity.new('error', 5)
114
+ # Severity of messages that notify about problems that application cannot recover from
115
+ FATAL = Severity.new('fatal', 6)
116
+ end
117
+
118
+ # Gets the severity of message
119
+ # @return [KXI::Application::Logger::Message:Severity] Severity of message
120
+ def severity
121
+ @sev
122
+ end
123
+
124
+ # Gets time at which the message was created
125
+ # @return [DateTime] Time of creation
126
+ def absolute_time
127
+ @ttime
128
+ end
129
+
130
+ # Gets time, relative to creation of logger, at which the message was created
131
+ # @return [DateTime] Relative time of creation
132
+ def relative_time
133
+ @rtime
134
+ end
135
+
136
+ # Gets the text message
137
+ # @return [String] Message
138
+ def message
139
+ @msg
140
+ end
141
+
142
+ # Instantiates the {KXI::Application::Logger::Message} class
143
+ # @param severity [KXI::Application::Logger::Message::Severity] Severity of message
144
+ # @param rtime [DateTime] Relative time of message
145
+ # @param ttime [DateTime] Absolute time of message
146
+ # @param message [String] Text of message
147
+ def initialize(severity, rtime, ttime, message)
148
+ @sev = severity
149
+ @rtime = rtime
150
+ @ttime = ttime
151
+ @msg = message
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,75 @@
1
+ # Created by Matyáš Pokorný on 2018-01-27.
2
+
3
+ module KXI
4
+ module Application
5
+ class Version
6
+ def major
7
+ @major
8
+ end
9
+
10
+ def minor
11
+ @minor
12
+ end
13
+
14
+ def patch
15
+ @patch
16
+ end
17
+
18
+ def identifier
19
+ @id
20
+ end
21
+
22
+ def metadata
23
+ @meta
24
+ end
25
+
26
+ def initialize(major, minor = 0, patch = 0, id = nil, meta = nil)
27
+ @major = major
28
+ @minor = minor
29
+ @patch = patch
30
+ @id = id
31
+ @meta = meta
32
+ end
33
+
34
+ def to_s
35
+ "#{@major}.#{@minor}.#{@patch}#{@id == nil ? '' : "-#{@id}"}#{@meta == nil ? '' : "+#{@meta}"}"
36
+ end
37
+
38
+ def ==(other)
39
+ return false unless other.is_a?(KXI::Application::Version)
40
+ return (@major == other.major and @minor == other.minor and @patch == other.patch and @id == other.identifier)
41
+ end
42
+
43
+ def <(other)
44
+ raise(KXI::Exceptions::InvalidOperationException.new("Can't compare version to #{other.class.name}!")) unless other.is_a?(KXI::Application::Version)
45
+ return true if @major < other.major or @minor < other.minor or @patch < other.patch
46
+ return true if @id != nil and other.identifier == nil
47
+ return true if @id != nil and other.identifier != nil and @id < other.identifier
48
+ return false
49
+ end
50
+
51
+ def <=(other)
52
+ raise(KXI::Exceptions::InvalidOperationException.new("Can't compare version to #{other.class.name}!")) unless other.is_a?(KXI::Application::Version)
53
+ return true if self == other
54
+ return true if @major < other.major or @minor < other.minor or @patch < other.patch
55
+ return true if @id != nil and other.identifier == nil
56
+ return true if @id != nil and other.identifier != nil and @id < other.identifier
57
+ return false
58
+ end
59
+
60
+ def >(other)
61
+ return (not self <= other)
62
+ end
63
+
64
+ def >=(other)
65
+ return (not self < other)
66
+ end
67
+
68
+ def self.parse(str)
69
+ m = /^\s*(?'ma'\d+)\s*(\.\s*(?'mi'\d+))?\s*(\.\s*(?'pt'\d+))?\s*(-\s*(?'id'[0-9A-Z\-.]+))?\s*(\+\s*(?'mt'[0-9A-Z\-.]+))?\s*$/mi.match(str)
70
+ raise(KXI::Exceptions::ParseException.new('version', str)) if m == nil
71
+ return Version.new(m['ma'].to_i, m['mi'] != nil ? m['mi'].to_i : 0, m['pt'] != nil ? m['pt'].to_i : 0, m['id'], m['mt'])
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,70 @@
1
+ # Created by Matyáš Pokorný on 2018-01-27.
2
+
3
+ module KXI
4
+ module Application
5
+ class VersionExpression
6
+ COMP_EQ = '='
7
+ COMP_LEQ = '<='
8
+ COMP_LT = '<'
9
+ COMP_GEQ = '>='
10
+ COMP_GT = '>'
11
+ COMP_AT = '~>'
12
+
13
+ def comparison
14
+ @comp
15
+ end
16
+
17
+ def major
18
+ @major
19
+ end
20
+
21
+ def minor
22
+ @minor
23
+ end
24
+
25
+ def patch
26
+ @patch
27
+ end
28
+
29
+ def initialize(comp, major, minor = nil, patch = nil)
30
+ @comp = comp
31
+ @major = major
32
+ @minor = minor
33
+ @patch = patch
34
+ @target = KXI::Application::Version.new(major, minor == nil ? 0 : minor, patch == nil ? 0 : patch)
35
+ end
36
+
37
+ # @param ver [KXI::Application::Version]
38
+ def matches?(ver)
39
+ case @comp
40
+ when COMP_EQ
41
+ return (
42
+ ver.major == @major and
43
+ ver.minor == (@minor == nil ? 0 : @minor) and
44
+ ver.patch == (@patch == nil ? 0 : @patch)
45
+ )
46
+ when COMP_AT
47
+ return (
48
+ ver.major == @major and
49
+ (@minor == nil or ver.minor == @minor) and
50
+ (@patch == nil or ver.patch == @patch)
51
+ )
52
+ when COMP_GEQ
53
+ return ver >= @target
54
+ when COMP_LEQ
55
+ return ver <= @target
56
+ when COMP_GT
57
+ return ver > @target
58
+ when COMP_LT
59
+ return ver < @target
60
+ end
61
+ end
62
+
63
+ def self.parse(str)
64
+ m = /^\s*(?'cm'>|<|>=|<=|=|~>)\s*(?'mj'\d+)\s*(\.\s*(?'mi'\d+))?\s*(\.\s*(?'pt'\d+))?\s*?$/m.match(str)
65
+ raise(KXI::Exceptions::ParseException.new('version expression', str)) if m == nil
66
+ return VersionExpression.new(m['cm'], m['mj'].to_i, m['mi']&.to_i, m['pt']&.to_i)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -42,13 +42,13 @@ module KXI
42
42
  # Gets value of argument
43
43
  # @param index [String, Symbol, KXI::CLI::Argument] Name of argument
44
44
  # @return [String] Value of argument
45
- def []=(index)
45
+ def [](index)
46
46
  if index.is_a?(Symbol)
47
47
  index = index.to_s
48
48
  elsif index.is_a?(KXI::CLI::Argument)
49
49
  index = index.name
50
50
  end
51
- raise(Exception.new("Undefined argument #{index}!")) if @vals[index] == nil
51
+ raise(Exception.new("Undefined argument '#{index}'!")) unless @vals.include?(index)
52
52
  return @vals[index][:value]
53
53
  end
54
54
 
@@ -65,7 +65,7 @@ module KXI
65
65
  # Validates variadic arguments and checks for minimal argument requirements
66
66
  def finish
67
67
  @args.each do |arg|
68
- if @vals[arg.name] != nil
68
+ if @vals.include?(arg.name)
69
69
  unless arg.is_a?(KXI::CLI::FlagArgument)
70
70
  begin
71
71
  arg.validate(@vals[arg.name][:value])
@@ -75,7 +75,7 @@ module KXI
75
75
  end
76
76
  else
77
77
  raise(KXI::Exceptions::ArgumentException.new(arg.name, 'Argument is mandatory!')) if arg.required?
78
- @vals[arg.name] = arg.default
78
+ @vals[arg.name] = { :argument => arg, :value => arg.default }
79
79
  end
80
80
  end
81
81
  end
@@ -0,0 +1,49 @@
1
+ # Created by Matyáš Pokorný on 2018-01-24.
2
+
3
+ module KXI
4
+ module CLI
5
+ class PropertyList
6
+ def initialize
7
+ @align = 0
8
+ @data = {}
9
+ end
10
+
11
+ def field(name, value)
12
+ @data[name] = value
13
+ @align = name.length if name.length > @align
14
+ end
15
+
16
+ def render(cols = 4)
17
+ @data.each_pair do |k, v|
18
+ if v.kind_of?(Array)
19
+ print("#{pad(k)}: ")
20
+ v.each_index do |idx|
21
+ if idx > 0 and idx % cols == 0
22
+ puts('')
23
+ print(' ' * (@align + 2))
24
+ elsif idx > 0
25
+ print(', ')
26
+ end
27
+ print(v[idx])
28
+ end
29
+ puts('')
30
+ else
31
+ puts("#{pad(k)}: #{v}")
32
+ end
33
+ end
34
+ end
35
+
36
+ def pad(key)
37
+ d = false
38
+ p = ''
39
+ (@align - key.length).times do |i|
40
+ p = (d ? '.' : ' ') + p
41
+ d = (not d)
42
+ end
43
+ return key + p
44
+ end
45
+
46
+ private :pad
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,63 @@
1
+ # Created by Matyáš Pokorný on 2018-01-24.
2
+
3
+ module KXI
4
+ module CLI
5
+ class Table
6
+ def initialize
7
+ @cols = KXI::Collections::ArrayCollection.new
8
+ @rows = 0
9
+ yield(self) if block_given?
10
+ end
11
+
12
+ def column(name)
13
+ col = Column.new(name)
14
+ @cols.add(col)
15
+ return col
16
+ end
17
+
18
+ def row(e)
19
+ e.each_key { |c| @cols.first { |i| i.name == c }&.row(e[c].to_s.strip.chomp) }
20
+ @rows += 1
21
+ end
22
+
23
+ def render
24
+ @rows.times do |row|
25
+ f = true
26
+ @cols.foreach do |col|
27
+ print(' ') unless f
28
+ f = false
29
+ col.write(row)
30
+ end
31
+ puts
32
+ end
33
+ end
34
+
35
+ class Column
36
+ def align
37
+ @align
38
+ end
39
+
40
+ def name
41
+ @name
42
+ end
43
+
44
+ def initialize(name)
45
+ @name = name
46
+ @align = 0
47
+ @data = []
48
+ end
49
+
50
+ def row(str)
51
+ @align = str.length if @align < str.length
52
+ @data.push(str)
53
+ end
54
+
55
+ def write(row)
56
+ str = @data[row]
57
+ str = '' if str == nil
58
+ print(str.ljust(@align))
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
data/lib/kxi/cli/verb.rb CHANGED
@@ -129,9 +129,9 @@ module KXI
129
129
 
130
130
  # Parses and executes action of verb
131
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?('-?')
132
+ def act(args = nil)
133
+ args = ARGV if args == nil
134
+ hf = (args.include?('-h') or args.include?('--help') or args.include?('-?'))
135
135
  if @verbs.count > 0
136
136
  v = args.shift
137
137
  if @help and (v == 'help' or hf)
@@ -142,14 +142,14 @@ module KXI
142
142
  if verb == nil
143
143
  help
144
144
  else
145
- verb.act(*args)
145
+ verb.act(args)
146
146
  end
147
147
  end
148
148
  else
149
149
  raise(KXI::Exceptions::VerbExpectedException.new(@verbs.select { |i| i.name }.to_array)) if v == nil
150
150
  verb = @verbs.first { |i| i.name == v.downcase }
151
151
  raise(KXI::Exceptions::VerbExpectedException.new(@verbs.select { |i| i.name }.to_array)) if verb == nil
152
- verb.act(*args)
152
+ verb.act(args)
153
153
  end
154
154
  else
155
155
  if @help and hf
@@ -178,7 +178,7 @@ module KXI
178
178
  else
179
179
  raise(KXI::Exceptions::ArgumentException.new(val, 'Expected short argument name!')) if val.length == 1
180
180
  nm = val[1]
181
- arg = @args.first { |i| i.shortcut == nm }
181
+ arg = @args.of_type(KXI::CLI::ExplicitArgument).first { |i| i.shortcut == nm }
182
182
  raise(KXI::Exceptions::ArgumentException.new(nm, 'No such argument exists!')) if arg == nil
183
183
  if arg.is_a?(KXI::CLI::FlagArgument)
184
184
  vals.set(arg, true)
@@ -198,14 +198,14 @@ module KXI
198
198
  an = anon.first
199
199
  raise(KXI::Exceptions::NoArgumentException.new(val)) if an == nil
200
200
  vals.set(an, val)
201
- anon.remove_at(0)
201
+ anon.remove_at(0) unless an.variadic?
202
202
  end
203
203
  end
204
204
  end
205
+ vals.finish
205
206
  if @action == nil
206
207
  raise(KXI::Exceptions::NotImplementedException.new)
207
208
  else
208
- vals.finish
209
209
  @action.call(vals)
210
210
  end
211
211
  end
@@ -0,0 +1,26 @@
1
+ # Created by Matyáš Pokorný on 2018-01-24.
2
+
3
+ module KXI
4
+ module Exceptions
5
+ class ConfigurationException < Exception
6
+ def file
7
+ @file
8
+ end
9
+
10
+ def path
11
+ @path
12
+ end
13
+
14
+ def error_message
15
+ @msg
16
+ end
17
+
18
+ def initialize(file, path, msg = nil)
19
+ super("Invalid configuration <#{path}> in file '#{file}'!#{msg != nil ? ": #{msg}" : ''}")
20
+ @file = file
21
+ @path = path
22
+ @msg = msg
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,11 @@
1
+ # Created by Matyáš Pokorný on 2018-01-27.
2
+
3
+ module KXI
4
+ module Exceptions
5
+ class InvalidOperationException < Exception
6
+ def initialize(msg)
7
+ super(msg)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ # Created by Matyáš Pokorný on 2018-01-27.
2
+
3
+ module KXI
4
+ module Exceptions
5
+ class ParseException < Exception
6
+ def value
7
+ @val
8
+ end
9
+
10
+ def parser
11
+ @par
12
+ end
13
+
14
+ def initialize(parser, val)
15
+ super("Failed to parse value '#{val.to_s}' as #{parser}!")
16
+ @par = parser
17
+ @val = val
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,102 @@
1
+ # Created by Matyáš Pokorný on 2018-01-26.
2
+
3
+ module KXI
4
+ module Math
5
+ class Polynomial
6
+ def degree
7
+ @cfs.length - 1
8
+ end
9
+
10
+ def coefficients
11
+ @cfs
12
+ end
13
+
14
+ def initialize(*cfs)
15
+ cfs.shift while cfs[0] == 0
16
+ @cfs = cfs.collect { |i| i.to_f }
17
+ end
18
+
19
+ def to_s
20
+ ret = nil
21
+ foreach do |k, d|
22
+ if d > 0
23
+ if k != 0
24
+ if ret == nil
25
+ ret = k >= 0 ? '' : '-'
26
+ else
27
+ ret += k >= 0 ? ' + ' : ' - '
28
+ end
29
+ ret += (k >= 0 ? k : -k).to_s if k != 1 and k != -1
30
+ ret += "x#{d > 1 ? "^#{d.to_s}" : ''}"
31
+ end
32
+ else
33
+ if ret == nil
34
+ ret = k >= 0 ? '' : '-'
35
+ else
36
+ ret += k >= 0 ? ' + ' : ' - '
37
+ end
38
+ ret += (k >= 0 ? k : -k).to_s
39
+ end
40
+ end
41
+ return ret
42
+ end
43
+
44
+ def derivative
45
+ cfs = []
46
+ foreach do |k, d|
47
+ if d > 0
48
+ cfs.push(k * d)
49
+ end
50
+ end
51
+ return Polynomial.new(*cfs)
52
+ end
53
+
54
+ def integral
55
+ cfs = []
56
+ foreach do |k, d|
57
+ cfs.push(k / (d + 1))
58
+ end
59
+ cfs.push(0)
60
+ return Polynomial.new(*cfs)
61
+ end
62
+
63
+ def integrate(x1, x2)
64
+ min = x1 > x2 ? x2 : x1
65
+ max = x1 > x2 ? x1 : x2
66
+ i = integral
67
+ return i.at(max) - i.at(min)
68
+ end
69
+
70
+ def at(x)
71
+ sum = 0
72
+ foreach do |k, d|
73
+ sum += k * (x ** d)
74
+ end
75
+ return sum
76
+ end
77
+
78
+ def foreach
79
+ d = degree
80
+ @cfs.each do |k|
81
+ yield(k, d)
82
+ d -= 1
83
+ end
84
+ end
85
+
86
+ def *(other)
87
+ if other.is_a?(Polynomial)
88
+ cfs = [0] * (degree + other.degree)
89
+ foreach do |k1, d1|
90
+ other.foreach do |k2, d2|
91
+ cfs[d1 + d2] += k1 * k2
92
+ end
93
+ end
94
+ return Polynomial.new(*cfs)
95
+ elsif other.is_a?(Numeric)
96
+ return @cfs.collect { |k| k * other }
97
+ end
98
+ raise(Exception.new('Polynomial multiplication error!'))
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,58 @@
1
+ # Created by Matyáš Pokorný on 2018-01-28.
2
+
3
+ module KXI
4
+ class Platform
5
+ def name
6
+ @name
7
+ end
8
+
9
+ def version
10
+ @version
11
+ end
12
+
13
+ def library_extensions
14
+ @libs
15
+ end
16
+
17
+ def path_separator
18
+ @ps
19
+ end
20
+
21
+ def initialize(nm, ver, ps, *libs)
22
+ @name = nm
23
+ @version = KXI::Application::Version.parse(ver)
24
+ @ps = ps
25
+ @libs = libs
26
+ end
27
+
28
+ def self.this
29
+ if /cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM
30
+ return Platform.new('windows', `wmic os get Version /value`.split('=').last.strip.chomp, ';', 'dll')
31
+ elsif /darwin/ =~ RUBY_PLATFORM
32
+ return Platform.new('osx', `defaults read loginwindow SystemVersionStampAsString`, ':', 'dylib')
33
+ else
34
+ return Platform.new('linux', `uname -r`.split('-')[0], ':', 'so')
35
+ end
36
+ end
37
+
38
+ def exec(name, *dir)
39
+ dir = Platform.env('path').split(@ps) if dir.length == 0
40
+ ext = Platform.env('pathext')
41
+ (ext != nil ? ext.split(@ps) + [''] : ['']).each do |e|
42
+ dir.each do |d|
43
+ f = File.join(d, "#{name}#{e}")
44
+ return f if File.exists?(f)
45
+ end
46
+ end
47
+ return nil
48
+ end
49
+
50
+ def self.env(key)
51
+ key = key.downcase
52
+ ENV.each_pair do |k, v|
53
+ return v if k.downcase == key
54
+ end
55
+ return nil
56
+ end
57
+ end
58
+ end
@@ -32,7 +32,7 @@ module KXI
32
32
  def method
33
33
  return nil if @block != nil and @block[0] == '<' and @block[@block.length - 1] == '>'
34
34
  return @block unless @block == nil
35
- return nil if @context[0] == '<' and @context[@context.length - 1] == '>'
35
+ return nil if @context != nil and @context[0] == '<' and @context[@context.length - 1] == '>'
36
36
  @context
37
37
  end
38
38
 
data/lib/kxi/version.rb CHANGED
@@ -1,4 +1,4 @@
1
- module KXI
2
- # Version of KXI
3
- VERSION = '1.0.0'
4
- end
1
+ module KXI
2
+ # Version of KXI
3
+ VERSION = '1.0.1'
4
+ end
data/lib/kxi.rb CHANGED
@@ -1,3 +1,7 @@
1
+ # Ruby
2
+ require 'date'
3
+
4
+ # KXI
1
5
  require 'kxi/version'
2
6
  require 'kxi/exceptions/abstract_exception'
3
7
  require 'kxi/exceptions/collection_exception'
@@ -7,6 +11,9 @@ require 'kxi/exceptions/argument_exception'
7
11
  require 'kxi/exceptions/no_argument_exception'
8
12
  require 'kxi/exceptions/verb_expected_exception'
9
13
  require 'kxi/exceptions/invalid_type_exception'
14
+ require 'kxi/exceptions/configuration_exception'
15
+ require 'kxi/exceptions/parse_exception'
16
+ require 'kxi/exceptions/invalid_operation_exception'
10
17
  require 'kxi/reflection/stack_frame'
11
18
  require 'kxi/collections/enumerator'
12
19
  require 'kxi/collections/enumerable'
@@ -20,3 +27,13 @@ require 'kxi/cli/flag_argument'
20
27
  require 'kxi/cli/named_argument'
21
28
  require 'kxi/cli/argument_values'
22
29
  require 'kxi/cli/verb'
30
+ require 'kxi/cli/table'
31
+ require 'kxi/cli/property_list'
32
+ require 'kxi/application/config_reader'
33
+ require 'kxi/application/config'
34
+ require 'kxi/application/event'
35
+ require 'kxi/application/logger'
36
+ require 'kxi/application/version'
37
+ require 'kxi/application/version_expression'
38
+ require 'kxi/math/polynomial'
39
+ require 'kxi/platform'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kxi
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matyáš Pokorný
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-23 00:00:00.000000000 Z
11
+ date: 2018-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -116,12 +116,20 @@ extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
118
  - lib/kxi.rb
119
+ - lib/kxi/application/config.rb
120
+ - lib/kxi/application/config_reader.rb
121
+ - lib/kxi/application/event.rb
122
+ - lib/kxi/application/logger.rb
123
+ - lib/kxi/application/version.rb
124
+ - lib/kxi/application/version_expression.rb
119
125
  - lib/kxi/cli/anonymous_argument.rb
120
126
  - lib/kxi/cli/argument.rb
121
127
  - lib/kxi/cli/argument_values.rb
122
128
  - lib/kxi/cli/explicit_argument.rb
123
129
  - lib/kxi/cli/flag_argument.rb
124
130
  - lib/kxi/cli/named_argument.rb
131
+ - lib/kxi/cli/property_list.rb
132
+ - lib/kxi/cli/table.rb
125
133
  - lib/kxi/cli/verb.rb
126
134
  - lib/kxi/collections/array_collection.rb
127
135
  - lib/kxi/collections/enumerable.rb
@@ -131,11 +139,16 @@ files:
131
139
  - lib/kxi/exceptions/abstract_exception.rb
132
140
  - lib/kxi/exceptions/argument_exception.rb
133
141
  - lib/kxi/exceptions/collection_exception.rb
142
+ - lib/kxi/exceptions/configuration_exception.rb
143
+ - lib/kxi/exceptions/invalid_operation_exception.rb
134
144
  - lib/kxi/exceptions/invalid_type_exception.rb
135
145
  - lib/kxi/exceptions/no_argument_exception.rb
136
146
  - lib/kxi/exceptions/not_implemented_exception.rb
137
147
  - lib/kxi/exceptions/out_of_range_exception.rb
148
+ - lib/kxi/exceptions/parse_exception.rb
138
149
  - lib/kxi/exceptions/verb_expected_exception.rb
150
+ - lib/kxi/math/polynomial.rb
151
+ - lib/kxi/platform.rb
139
152
  - lib/kxi/reflection/stack_frame.rb
140
153
  - lib/kxi/version.rb
141
154
  homepage: https://github.com/cryocz/kxi