lib/sup/util.rb in sup-0.2 vs lib/sup/util.rb in sup-0.3

- old
+ new

@@ -134,20 +134,47 @@ ## "k combinator" def returning x; yield x; x; end ## clone of java-style whole-method synchronization ## assumes a @mutex variable + ## TODO: clean up, try harder to avoid namespace collisions def synchronized *meth meth.each do class_eval <<-EOF alias unsynchronized_#{meth} #{meth} def #{meth}(*a, &b) @mutex.synchronize { unsynchronized_#{meth}(*a, &b) } end EOF end end + + def ignore_concurrent_calls *meth + meth.each do + mutex = "@__concurrent_protector_#{meth}" + flag = "@__concurrent_flag_#{meth}" + oldmeth = "__unprotected_#{meth}" + class_eval <<-EOF + alias #{oldmeth} #{meth} + def #{meth}(*a, &b) + #{mutex} = Mutex.new unless defined? #{mutex} + #{flag} = true unless defined? #{flag} + run = #{mutex}.synchronize do + if #{flag} + #{flag} = false + true + end + end + if run + ret = #{oldmeth}(*a, &b) + #{mutex}.synchronize { #{flag} = true } + ret + end + end + EOF + end + end end class String def camel_to_hyphy self.gsub(/([a-z])([A-Z0-9])/, '\1-\2').downcase @@ -163,20 +190,79 @@ start = pos + 1 end ret end + ## one of the few things i miss from perl def ucfirst self[0 .. 0].upcase + self[1 .. -1] end ## a very complicated regex found on teh internets to split on ## commas, unless they occurr within double quotes. def split_on_commas split(/,\s*(?=(?:[^"]*"[^"]*")*(?![^"]*"))/) end + ## ok, here we do it the hard way. got to have a remainder for purposes of + ## tab-completing full email addresses + def split_on_commas_with_remainder + ret = [] + state = :outstring + pos = 0 + region_start = 0 + while pos <= length + newpos = case state + when :escaped_instring, :escaped_outstring: pos + else index(/[,"\\]/, pos) + end + + if newpos + char = self[newpos] + else + char = nil + newpos = length + end + + case char + when ?" + state = case state + when :outstring: :instring + when :instring: :outstring + when :escaped_instring: :instring + when :escaped_outstring: :outstring + end + when ?,, nil + state = case state + when :outstring, :escaped_outstring: + ret << self[region_start ... newpos].gsub(/^\s+|\s+$/, "") + region_start = newpos + 1 + :outstring + when :instring: :instring + when :escaped_instring: :instring + end + when ?\\ + state = case state + when :instring: :escaped_instring + when :outstring: :escaped_outstring + when :escaped_instring: :instring + when :escaped_outstring: :outstring + end + end + pos = newpos + 1 + end + + remainder = case state + when :instring + self[region_start .. -1].gsub(/^\s+/, "") + else + nil + end + + [ret, remainder] + end + def wrap len ret = [] s = self while s.length > len cut = s[0 ... len].rindex(/\s/) @@ -221,10 +307,24 @@ chr else "<#{self}>" end end + + ## hacking the english language + def pluralize s + to_s + " " + + if self == 1 + s + else + if s =~ /(.*)y$/ + $1 + "ies" + else + s + "s" + end + end + end end class Hash def - o Hash[*self.map { |k, v| [k, v] unless o.include? k }.compact.flatten_one_level] @@ -297,10 +397,11 @@ def rest; self[1..-1]; end def to_boolean_h; Hash[*map { |x| [x, true] }.flatten]; end def last= e; self[-1] = e end + def nonempty?; !empty? end end class Time def to_indexable_s sprintf "%012d", self @@ -403,23 +504,24 @@ def self.included klass klass.extend ClassMethods end end -## wraps an object. if it throws an exception, keeps a copy, and -## rethrows it for any further method calls. +## wraps an object. if it throws an exception, keeps a copy. class Recoverable def initialize o @o = o - @e = nil + @error = nil + @mutex = Mutex.new end - def clear_error!; @e = nil; end - def has_errors?; !@e.nil?; end - def error; @e; end + attr_accessor :error - def method_missing m, *a, &b; __pass m, *a, &b; end + def clear_error!; @error = nil; end + def has_errors?; !@error.nil?; end + + def method_missing m, *a, &b; __pass m, *a, &b end def id; __pass :id; end def to_s; __pass :to_s; end def to_yaml x; __pass :to_yaml, x; end def is_a? c; @o.is_a? c; end @@ -428,11 +530,11 @@ def __pass m, *a, &b begin @o.send(m, *a, &b) rescue Exception => e - @e = e - raise e + @error ||= e + raise end end end ## acts like a hash with an initialization block, but saves any