conditions 0.0.2.alpha

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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ nbproject/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in conditions.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2011, André Gawron
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ - Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ - Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ - The names of its contributors may be used to endorse or promote products
13
+ derived from this software without specific prior written permission.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
+ IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
19
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
24
+ OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.rdoc ADDED
@@ -0,0 +1,37 @@
1
+ = Conditions
2
+
3
+ Conditions is some kind of low-level condition-based
4
+ event-handler suitable for different kind of uses.
5
+ Typical use is error handling. it's ported from LISP's Condition System:
6
+
7
+ http://gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html
8
+
9
+ THIS IS HIGHLY ALPHA! DO NOT USE IN PRODUCTION!
10
+ (but syntax is most likely not going to change)
11
+
12
+ For more information, read covering blog posts on:
13
+
14
+ http://www.andre-gawron.de/123/the-diversity-of-error-handling
15
+
16
+ http://www.andre-gawron.de/187/road-to-condition
17
+
18
+ == Patching
19
+
20
+ It's currently extending the Object class. Why? Kinda easy.
21
+ I don't want to write Conditions::handle (etc).
22
+
23
+ The Object class is patched as soon as Conditions are required.
24
+ I'm lookin into actually check before patching if there are other
25
+ methods already in the Object class and probably not allow
26
+ patching then. But that's for the future, it's alpha, right?
27
+
28
+ == I'd like to patch and / or help maintain Conditions. How can I?
29
+
30
+ Are you sure? Ok, feel free to ...
31
+
32
+ * Fork the project: http://github.com/melkon/conditions
33
+ * Make your feature addition or bug fix.
34
+
35
+ == Copyright
36
+
37
+ Copyright (c) 2011 André Gawron. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,19 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "conditions/version"
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "conditions"
6
+ s.version = Conditions::VERSION
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["André Gawron"]
9
+ s.email = ["andre@ziemek.de"]
10
+ s.homepage = "https://github.com/melkon/conditions"
11
+ s.summary = %q{Implements the Lisp's condition system in Ruby}
12
+ s.description = %q{Implements the Lisp's condition system in Ruby}
13
+ s.license = 'BSD'
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,6 @@
1
+ yes
2
+ no
3
+ no
4
+ no
5
+ no
6
+ yes
@@ -0,0 +1,72 @@
1
+ require "conditions"
2
+
3
+ class MalformedLogEntryError < Condition ; end
4
+
5
+ bind :NoticeSignaled => lambda { invoke :Suppress}
6
+
7
+ p (bind :NoticeSignaled => lambda { invoke :Suppress } do
8
+ "block value is returning!"
9
+ end)
10
+
11
+ def parse_log_entry text
12
+
13
+ if !well_formed? text then
14
+
15
+ restart :UseValue => proc { |value| text = value },
16
+ :ReparseEntry => proc { |fixed| text = parse_log_entry fixed } do
17
+
18
+ error MalformedLogEntryError
19
+
20
+ end
21
+
22
+ end
23
+
24
+ text
25
+
26
+ end
27
+
28
+ def parse_log_file file
29
+
30
+ File.open(file).each do |line|
31
+
32
+ entry = (restart :SkipLogEntry => lambda { nil } do
33
+ parse_log_entry line
34
+ end)
35
+
36
+ yield entry if entry
37
+
38
+ end
39
+
40
+ end
41
+
42
+ def log_analyzer
43
+
44
+ bind :ConditionNotDefined => lambda { invoke :Define },
45
+ :MalformedLogEntryError => lambda { invoke :UseValue, "failed\n" } do
46
+ find_logs do |log|
47
+ analyze_log log
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ def analyze_log log
54
+ parse_log_file log do |entry|
55
+ analyze_entry entry
56
+ end
57
+ end
58
+
59
+ def well_formed? text
60
+ "yes\n" == text ? true : false
61
+ end
62
+
63
+ def analyze_entry entry
64
+ p entry
65
+ end
66
+
67
+ def find_logs
68
+ yield "./log"
69
+ yield "./another-log"
70
+ end
71
+
72
+ log_analyzer
data/example/log ADDED
@@ -0,0 +1,5 @@
1
+ yes
2
+ yes
3
+ no
4
+ no
5
+ yes
data/example/newfile ADDED
File without changes
data/lib/conditions.rb ADDED
@@ -0,0 +1,16 @@
1
+ # main api
2
+ require "conditions/signals"
3
+ require "conditions/handles"
4
+ require "conditions/restarts"
5
+
6
+ # base condition classes
7
+ require "conditions/definitions/defaults"
8
+
9
+ # helper functions and exception definitions
10
+ require "conditions/lib/helpers"
11
+ require "conditions/lib/exceptions"
12
+
13
+ # remove this and the puppy will cry
14
+ class Object
15
+ include Conditions
16
+ end
@@ -0,0 +1,38 @@
1
+ class Condition
2
+
3
+ attr_reader :dynamic, :trace, :message, :restarts
4
+
5
+ def initialize message = nil
6
+
7
+ @message = message
8
+
9
+ @trace = Kernel.caller
10
+ @dynamic = false
11
+ @restarts = Utils::Handler::get_restarts
12
+
13
+ end
14
+
15
+ end
16
+
17
+ class ConditionDynamic < Condition
18
+
19
+ def initialize *params
20
+
21
+ super params
22
+
23
+ @params = params
24
+ @dynamic = true
25
+
26
+ end
27
+
28
+ def get key
29
+ @params[key]
30
+ end
31
+
32
+ end
33
+
34
+ class DynamicConditionCreation < Condition ; end
35
+ class ConditionNotDefined < Condition ; end
36
+ class NoDynamicConditionAllowed < Condition ; end
37
+
38
+ class NoticeSignaled < Condition ; end
@@ -0,0 +1,143 @@
1
+ module Conditions
2
+
3
+ #
4
+ # handles a signaled condition
5
+ #
6
+ # handles a condition signaled by #signal or any other signaling method
7
+ # by registering handlers for given conditions.
8
+ #
9
+ # if a handler matches a condition, it will be executed and after that,
10
+ # the stack will be unwound to the point where the latest #handle registered
11
+ # a handler for given condition returning the value of the executed handler.
12
+ #
13
+ # @param *conditions conditions which shall be catched by #handle,
14
+ # @param &block block which will be executed normally if no condition will be signaled
15
+ #
16
+ # @return return value of &block
17
+ # @return if a condition is catched, the return value of the registered handler
18
+ #
19
+ # @raises ConditionHandled if the catched condition doesnt belong to current block
20
+ #
21
+ # @see #parse_handlers for syntax information on *conditions
22
+ #
23
+ def handle *conditions, &block
24
+
25
+ conditions = Utils::parse_handlers conditions
26
+
27
+ conditions.each do |condition|
28
+ Utils::Handler::set(:condition, condition.merge!(:raise => true))
29
+ end
30
+
31
+ value = begin
32
+ block.call
33
+ rescue Exception::ConditionHandled => ex
34
+
35
+ # if condition doesnt belong to this block,
36
+ # continue unwinding the stack
37
+ if !Utils::find_handler(ex.condition[:name], conditions) then
38
+ raise Exception::ConditionHandled, :value => ex.value, :condition => ex.condition
39
+ end
40
+
41
+ ex.value
42
+
43
+ end
44
+
45
+ conditions.each do |condition|
46
+ Utils::Handler::unset(:condition, condition)
47
+ end
48
+
49
+ value
50
+
51
+ end
52
+
53
+ #
54
+ # binds a handler to a condition
55
+ #
56
+ # #bind works similiar to #handle but instead of unwinding the stack,
57
+ # #bind returns the value of the last called handler.
58
+ #
59
+ # caveat:
60
+ #
61
+ # *if* there's a condition bound by #handle in the upper callstack
62
+ # *and* the same condition is bound by #bind inside of this #handle,
63
+ # the system will unwind the stack to #handle - but the condition's handler
64
+ # bound by #bind will be executed and properly unregistered.
65
+ #
66
+ # @param *conditions conditions which shall be bound by #bind,
67
+ # @param &block block which will be executed normally if no condition will be signaled
68
+ #
69
+ # @return return value of &block
70
+ # @return if a condition is signaled and bound by #bind, it returns value of the last registered handler
71
+ #
72
+ # @see #parse_handlers for syntax information on *conditions
73
+ #
74
+ def bind *conditions, &block
75
+
76
+ conditions = Utils::parse_handlers conditions
77
+
78
+ conditions.each do |condition|
79
+ Utils::Handler::set(:condition, condition.merge!(:raise => false))
80
+ end
81
+
82
+ value = true
83
+ if block_given? then
84
+
85
+ value = begin
86
+
87
+ # tmp save the value of the callback
88
+ # and return it after the conditions were unset
89
+ value = block.call
90
+
91
+ conditions.each do |condition|
92
+ Utils::Handler::unset(:condition, condition)
93
+ end
94
+
95
+ value
96
+
97
+ # it is possible that a Condition has a handler registered by #handle
98
+ # and therefore will unwind the stack. but if a handler bound by #bind
99
+ # and #bind is used with a block, the bound handler will not be unregistered.
100
+ # therefore, catch the exception intended for #handle
101
+ # unregister the handler registered by #bind
102
+ # and rethrow the exception again to reach the proper #handle
103
+ rescue Exception::ConditionHandled => ex
104
+
105
+ conditions.each do |condition|
106
+ Utils::Handler::unset(:condition, condition)
107
+ end
108
+
109
+ raise Exception::ConditionHandled, :value => ex.value, :condition => ex.condition
110
+
111
+ end
112
+
113
+ end
114
+
115
+ value
116
+
117
+ end
118
+
119
+ #
120
+ # unregisters a bound condition
121
+ #
122
+ # if bind is used without a block,
123
+ # #unbind is used to unregister the condition's handler
124
+ #
125
+ # @param *conditions conditions which shall be unregistered by #unbind,
126
+ #
127
+ # @return [Boolean] true
128
+ #
129
+ # @see #parse_handlers for syntax information on *conditions
130
+ #
131
+ def unbind *conditions
132
+
133
+ conditions = Utils::parse_handlers conditions
134
+
135
+ conditions.each do |condition|
136
+ Exception::Handler::unset(:condition, condition)
137
+ end
138
+
139
+ true
140
+
141
+ end
142
+
143
+ end
@@ -0,0 +1,35 @@
1
+ module Conditions::Exception
2
+
3
+ class ConditionNotHandledError < StandardError ; end
4
+ class ConditionHandled < StandardError
5
+
6
+ attr_reader :value, :condition
7
+
8
+ def initialize info
9
+
10
+ super info[:value]
11
+
12
+ @value = info[:value]
13
+ @condition = info[:condition]
14
+
15
+ end
16
+
17
+ end
18
+
19
+ class RestartNotFoundError < StandardError ; end
20
+ class RestartHandled < StandardError
21
+
22
+ attr_reader :value, :restart
23
+
24
+ def initialize info
25
+
26
+ super info[:value]
27
+
28
+ @value = info[:value]
29
+ @restart = info[:restart]
30
+
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,226 @@
1
+ module Conditions::Utils
2
+
3
+ class Handler
4
+
5
+ @@types = {:condition => {},
6
+ :restart => {}}
7
+
8
+ #
9
+ # yields every registered condition for given type
10
+ #
11
+ # opts:
12
+ # :reverse => true|false [default: true] LIFO or FIFO of yielded handlers
13
+ #
14
+ # @param [String, Symbol] supported types: :condition, :restart
15
+ # @param [String, Symbol] name of the condition
16
+ # @param [Hash] opts current available: :reverse => true
17
+ #
18
+ def self.get(type, condition_name, opts = {})
19
+
20
+ condition_name = Utils::normalize(condition_name)
21
+
22
+ if (!@@types[type].has_key?(condition_name)) or (@@types[type][condition_name].empty?)
23
+ return nil
24
+ end
25
+
26
+ opts[:reserve] = true unless opts[:reserve] === false
27
+
28
+ if opts[:reserve] === true
29
+ direction = :reverse_each
30
+ else
31
+ direction = :each
32
+ end
33
+
34
+ @@types[type][condition_name].send(direction) do |condition|
35
+
36
+ condition[:name] = condition_name
37
+
38
+ yield condition
39
+
40
+ end
41
+
42
+ end
43
+
44
+ def self.get_restarts()
45
+ return @@types[:restarts];
46
+ end
47
+
48
+ def self.get_handlers()
49
+ return @@types[:condition];
50
+ end
51
+
52
+ def self.set(type, condition)
53
+
54
+ condition[:name] = Utils::normalize(condition[:name])
55
+
56
+ @@types[type][condition[:name]] = [] unless @@types[type][condition[:name]]
57
+ @@types[type][condition[:name]].push({:block => condition[:block],
58
+ :raise => condition[:raise]})
59
+
60
+ end
61
+
62
+ def self.unset(type, condition)
63
+
64
+ condition[:name] = Utils::normalize(condition[:name])
65
+
66
+ @@types[type][condition[:name]].each_with_index do |saved_condition, index|
67
+
68
+ if saved_condition[:block] == condition[:block]
69
+
70
+ # completely delete the restart-entry if no block is given anymore
71
+ if 2 >@@types[type][condition[:name]].size then
72
+ @@types[type].delete(condition[:name])
73
+ else
74
+ @@types[type][condition[:name]].delete_at(index)
75
+ end
76
+
77
+ # unset only one condition
78
+ return true
79
+
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+ #
89
+ # parses magically the correct handlers / restarts
90
+ #
91
+ # #parse_handlers takes a hash as an argument and tries to identify
92
+ # the handlers / restarts and their callbacks. the syntax is the same for both.
93
+ #
94
+ # the simpliest is:
95
+ #
96
+ # :HandlerName => callback[, ...]
97
+ #
98
+ # class names are also supported:
99
+ #
100
+ # HandlerNAme => callback[, ...]
101
+ #
102
+ # class names as well as symbol will be casted to strings internally.
103
+ #
104
+ # currently, the callback has to be a lambda or
105
+ # a proc function to work within the condition system.
106
+ #
107
+ # it's also possible to define multiple handlers / restarts with the same callback:
108
+ #
109
+ # :HandlerName1, :HandlerName2, {:HandlerName3 => callback}[, ...]
110
+ #
111
+ # now let's mix everything together:
112
+ #
113
+ # :HandlerName => callback, HandlerName1, {:HandlerName2 => callback}, :HandlerName3 => callback
114
+ #
115
+ # why does this work?
116
+ #
117
+ # it's a lot of magic with hashes, since the #handle and #restart functions are using the * operator.
118
+ # this way, the parameters are wrapped in a Hash and can be magically transformed.
119
+ #
120
+ # @param [Hash] handlers a multidimensional Hash
121
+ #
122
+ # @return [Hash] a structured hash {{:name => :HandlerName, :block => callback}[, ...}}
123
+ #
124
+ def self.parse_handlers(handlers)
125
+
126
+ without_proc = []
127
+ parsed = []
128
+
129
+ handlers.each do |handler|
130
+
131
+ if handler.is_a? Hash
132
+
133
+ handler.each do |handler_name, handler_proc|
134
+
135
+ without_proc.each do |handler_name|
136
+ parsed.push(:name => handler_name, :block => handler_proc)
137
+ end
138
+
139
+ parsed.push(:name => handler_name, :block => handler_proc)
140
+
141
+ end
142
+
143
+ without_proc.clear
144
+
145
+ else
146
+
147
+ without_proc.push(handler)
148
+
149
+ end
150
+
151
+ end
152
+
153
+ parsed
154
+
155
+ end
156
+
157
+ #
158
+ # creates a condition object
159
+ #
160
+ # creates a condition object of given conditon_name symbol or string-class
161
+ # if the requested condition_name is not a existing class,
162
+ # #generate_condition registers a restart offering to dynamically create class.
163
+ # currently, the new class will be created in the module Conditions.
164
+ #
165
+ # this condition class inherits the class ConditionDynamic.
166
+ #
167
+ # @param [String, Symbol] condition_name the condition class' name to instance. it must start with an upper case letter!
168
+ # @param *params parameters forwarded to the condition class' constructor
169
+ #
170
+ # @return [Condition] object of the demanded condition class
171
+ #
172
+ # @error :ConditionNotDefined if requested condition class does not exist
173
+ #
174
+ # @restart :Define creates a dynamic condition named like condition_name
175
+ #
176
+ def self.generate_condition(condition_name, *params)
177
+
178
+ if not condition_name.kind_of?(Class)
179
+
180
+ if !Conditions.const_defined? condition_name then
181
+ restart :WriteToFile => lambda { p "will be implemented anytime soon" },
182
+ :Define => lambda { Conditions::const_set(condition_name, Class.new(ConditionDynamic))
183
+ notice :DynamicConditionCreation, "#{condition_name} dynamically created" } do
184
+
185
+ error :ConditionNotDefined, condition_name
186
+ end
187
+ end
188
+
189
+ condition_name = Conditions::const_get(condition_name)
190
+
191
+ end
192
+
193
+ condition_name.new(*params)
194
+
195
+ end
196
+
197
+ #
198
+ # finds a handler in the given hash
199
+ #
200
+ # @param [String, Symbol] the handler / restart to find
201
+ # @param [Hash] a hash of handlers / restarts: {{:name => :Handlername}[, ...]}
202
+ #
203
+ # @return [Boolean] true if found
204
+ # @return [Boolean] false if not
205
+ #
206
+ def self.find_handler(name, handlers)
207
+
208
+ name = Utils::normalize(name)
209
+
210
+ handlers.each do |handler|
211
+
212
+ if name == handler[:name]
213
+ return true
214
+ end
215
+
216
+ end
217
+
218
+ false
219
+
220
+ end
221
+
222
+ def self.normalize(name)
223
+ return name.to_s
224
+ end
225
+
226
+ end
@@ -0,0 +1,76 @@
1
+ module Conditions
2
+
3
+ #
4
+ # register a possible restart-option
5
+ #
6
+ # register a possible restart-option
7
+ # which can be invoked by an condition handler using #invoke
8
+ #
9
+ # since its possible to access the method's scope
10
+ # you can actually modify the method's behaviour from a handler
11
+ # which can be pretty dangerous but also very rewarding.
12
+ #
13
+ # if no restart was invoked, it returns the value of the block
14
+ # otherwise, it returns the value of invoked restart
15
+ #
16
+ # @param *restarts register restarts
17
+ # @param &block the code to execute normally
18
+ #
19
+ # @return value of the &block
20
+ # @return value of the invoked restart
21
+ #
22
+ # @raises RestartHandled if the catched restart doesnt belong to this block
23
+ #
24
+ # @see #parse_handlers for syntax information on *conditions
25
+ #
26
+ def restart *restarts, &block
27
+
28
+ restarts = Utils::parse_handlers restarts
29
+
30
+ restarts.each { |restart| Utils::Handler::set(:restart, restart)}
31
+
32
+ value = begin
33
+ block.call
34
+ rescue Exception::RestartHandled => ex
35
+
36
+ # if restart doesnt belong to this block,
37
+ # continue unwinding the stack
38
+ if !Utils::find_handler(ex.restart, restarts) then
39
+ raise Exception::RestartHandled, :value => ex.value, :restart => ex.restart
40
+ end
41
+
42
+ ex.value
43
+
44
+ end
45
+
46
+ restarts.each { |restart| Utils::Handler::unset(:restart, restart)}
47
+
48
+ value
49
+
50
+ end
51
+
52
+ #
53
+ # invokes a registered restart
54
+ #
55
+ # #invoke checks if a restart with restart_name was registered
56
+ # and calls it if found.
57
+ #
58
+ # @param [String] restart_name the restart which shall be invoked
59
+ # @param *params parameters which are needed by the restart
60
+ #
61
+ # @raises RestartHandled if a invoked restart is called
62
+ # @raises RestartNotFoundError if a demanded restart was not found
63
+ #
64
+ # @see #parse_handlers for syntax information on *conditions
65
+ #
66
+ def invoke restart_name, *params
67
+
68
+ Utils::Handler::get(:restart, restart_name) do |restart|
69
+ raise Exception::RestartHandled, :value => restart[:block].call(*params), :restart => restart_name
70
+ end
71
+
72
+ raise Exception::RestartNotFoundError, restart_name
73
+
74
+ end
75
+
76
+ end
@@ -0,0 +1,95 @@
1
+ module Conditions
2
+
3
+ #
4
+ # calls the registered handler for given condition
5
+ #
6
+ # if the registered handler is established using #handle,
7
+ # the call to #signal will not return and raise an exception instead.
8
+ #
9
+ # if it's established using bind, #signal will return normally with
10
+ # the handler's returned value.
11
+ #
12
+ # @param [Symbol] conditon_name the condition to signal
13
+ # @param *params additional information wich will be directly passed
14
+ # to the condition's constructor
15
+ #
16
+ # @return value the return value of the called handler.
17
+ #
18
+ # @raises ConditionHandled if a handler is established with #handle
19
+ #
20
+ def signal condition_name, *params
21
+
22
+ value = nil
23
+
24
+ condition = Utils::generate_condition condition_name, *params
25
+
26
+ Utils::Handler::get :condition, condition_name do |handler|
27
+
28
+ value = case handler[:block].arity
29
+ when 0 then handler[:block].call
30
+ when 1 then handler[:block].call condition
31
+ when 2 then handler[:block].call condition, value
32
+ end
33
+
34
+ raise(Exception::ConditionHandled, :value => value, :condition => handler) if handler[:raise]
35
+
36
+ end
37
+
38
+ value
39
+
40
+ end
41
+
42
+ #
43
+ # errors a condition
44
+ #
45
+ # it's build on top of #signal but will raise an ConditionNotHandledError
46
+ # if #signal returns normally. This ensures that a condition errored using
47
+ # #error has to be handled by a condition handler with an non-local exit
48
+ # as it's done by using #handle.
49
+ #
50
+ # @param [Symbol] condition condition's name
51
+ # @param *params additional information wich will be directly passed
52
+ # to the condition's constructor
53
+ #
54
+ # @raises ConditionNotHandledError if the condition was not handled
55
+ #
56
+ def error condition, *params
57
+
58
+ signal condition, *params
59
+
60
+ raise Exception::ConditionNotHandledError, "condition #{condition} was not handled"
61
+
62
+ end
63
+
64
+ #
65
+ # notices a condition
66
+ #
67
+ # it's build on top of #signal and will print the given message
68
+ # it can be suppressed by invoking the restart :Suppress.
69
+ #
70
+ # since notice is calling #signal,
71
+ # the given condition can also be handled
72
+ #
73
+ # if no handler is bound to given condition, #notice returns normally.
74
+ #
75
+ # @param [Symbol] condition condition's name
76
+ # @param [String] message
77
+ #
78
+ # @return nil or bound handler's returned value
79
+ #
80
+ # @signal :NoticeSignaled if #notice got called.
81
+ #
82
+ # @restart :Suppress message will not be printed
83
+ #
84
+ def notice condition, message
85
+
86
+ restart :Suppress => lambda { nil } do
87
+ signal :NoticeSignaled, condition
88
+ print "Notice: #{message}"
89
+ end
90
+
91
+ signal condition
92
+
93
+ end
94
+
95
+ end
@@ -0,0 +1,3 @@
1
+ module Conditions
2
+ VERSION = "0.0.2.alpha"
3
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: conditions
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: 6
5
+ version: 0.0.2.alpha
6
+ platform: ruby
7
+ authors:
8
+ - "Andr\xC3\xA9 Gawron"
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-08-31 00:00:00 Z
14
+ dependencies: []
15
+
16
+ description: Implements the Lisp's condition system in Ruby
17
+ email:
18
+ - andre@ziemek.de
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files: []
24
+
25
+ files:
26
+ - .gitignore
27
+ - Gemfile
28
+ - LICENSE
29
+ - README.rdoc
30
+ - Rakefile
31
+ - conditions.gemspec
32
+ - example/another-log
33
+ - example/example.rb
34
+ - example/log
35
+ - example/newfile
36
+ - lib/conditions.rb
37
+ - lib/conditions/definitions/defaults.rb
38
+ - lib/conditions/handles.rb
39
+ - lib/conditions/lib/exceptions.rb
40
+ - lib/conditions/lib/helpers.rb
41
+ - lib/conditions/restarts.rb
42
+ - lib/conditions/signals.rb
43
+ - lib/conditions/version.rb
44
+ homepage: https://github.com/melkon/conditions
45
+ licenses:
46
+ - BSD
47
+ post_install_message:
48
+ rdoc_options: []
49
+
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ">"
62
+ - !ruby/object:Gem::Version
63
+ version: 1.3.1
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.8.5
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Implements the Lisp's condition system in Ruby
71
+ test_files: []
72
+