kxi 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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