Class: Parsely

Inherits:
Object
  • Object
show all
Defined in:
lib/parsely.rb

Defined Under Namespace

Classes: Expression

Constant Summary collapse

VERSION =
"0.1.5"
RGX =
/"(.*?)"|\[(.*?)\]|([^\s]+)/
Ops =
{
  :timediff => cmd do
   def initialize value
     require 'date'
     @running_value = nil
   end 
   def process(value)
     new_value = DateTime.parse(value).to_time
     if @running_value.nil?
       @result = new_value.to_s
     else
      @result = ">\t+" + (new_value -  @running_value).to_s
     end
     @running_value = new_value
     @result
   end
  end,
  :count => cmd do
    def initialize value
      super
      @running_value = 0
      @result = proc { @running_value }
      @result.single = true
    end
    def process(value)
      @running_value += 1
      @result
    end
  end,
  :top => cmd do
    def initialize values
      super
      @running_values = []
      @result = proc { @running_values.sort {|a,b| b <=> a}.first(@k).join("\n") }
      @result.single = true
    end
    def process(k, value)
      @k ||= k
      @running_values << value
      @result
    end
  end,
  :min => cmd do
    def initialize value
      super
      @running_value = Float::MAX #-Inf would be better
      @result = proc { @running_value }
      @result.single = true
    end
    def process(value)
      if value.to_f < @running_value  
        @running_value = value.to_f
      end
      @result
    end
  end,
  :max => cmd do
    def initialize index
      super
      @running_value = Float::MIN #-Inf would be better
      @result = proc { @running_value }
      @result.single = true
    end
    def process(value)
      if value.to_f > @running_value
        @running_value = value.to_f
      end
      @result
    end
  end,
  :sum => cmd do
    def initialize index
      super
      @running_value = 0
      @result = proc { @running_value }
      @result.single = true
    end
    def process(value)
      @running_value += value.to_i
      @result
    end
  end,
  :avg => cmd do
    def initialize index
      super
      @running_value = 0
      @running_count = 0
      @result = proc { @running_value/@running_count.to_f }
      @result.single = true
    end
    def process(value)
      @running_value += value.to_i
      @running_count += 1
      @result
    end
  end,
  :freq => cmd do
    def initialize index
      super
    	@running_freqs = Hash.new(0)
      @running_count = 0
     as_ary=nil
      @result = proc do
        if as_ary.nil?
          as_ary=@running_freqs.sort_by do |k,v| [-v,k] end.each
        end
        k,v = as_ary.next 
        [v, k]
      end
    end
    def process(value)
      @running_freqs[value.to_s]+=1
      @running_count += 1
      @result
    end
  end,
  :stats => cmd do
    def initialize index
      require 'rubygems'
      require 'ministat'
      super
      @running_values = []
      cached = nil
      @result = proc do  
        unless cached
          data = MiniStat::Data.new(@running_values)
          cached = { 
            "Mean"=>data.mean,
            "Geometric Mean"=>data.geometric_mean,
            "Harmonic Mean"=>data.harmonic_mean,
            "Median"=>data.median ,
            "Min"=>data.data.min ,
            "Q1"=>data.q1,
            "Q3"=>data.q3,
            "Max"=>data.data.max,
            "IQR"=>data.iqr,
            "Outliers"=>data.outliers.inspect,
            "Variance"=>data.variance ,
            "Std Dev"=>data.std_dev,
          }.sort.each
        end
        cached.next
      end
    end
    def process(value)
      @running_values << value.to_i
      @result
    end
  end,
}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.cmd(&block) ⇒ Object



90
91
92
# File 'lib/parsely.rb', line 90

def self.cmd(&block)
  Struct.new :value, &block
end

Instance Method Details

#load_rcObject



287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/parsely.rb', line 287

def load_rc
  rcfile = if  ENV["PARSELYRC"]
    ENV["PARSELYRC"]
  else
    home = ENV["HOME"] || Dir.pwd
    home+"/.parselyrc"
    #_parsely, $parsely etc
  end
  if File.exists?(rcfile)
    load rcfile
  end
end

#mainObject



300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/parsely.rb', line 300

def main
  if ARGV.empty?
    abort("usage #$0 [-l |<expr> <file file file| stdin >]")
  elsif ARGV[0] == '-l'
    puts " Available aggregate functions:"
    puts Ops.keys.map {|k| "\t#{k}"}
    exit
  end
  load_rc
  expr = ARGV.shift
  main_loop(expr,ARGF)
end

#main_loop(expr, lines) ⇒ Object



313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
# File 'lib/parsely.rb', line 313

def main_loop(expr,lines)
  expression, cond =parse(expr)
  result = []
  result = lines.map.with_index do |line, lineno|
    line.chomp!
    items = [line]+line.scan(RGX).map do |a| 
      # XXX horrible
      a.find do |e| 
        !e.nil? 
      end 
    end
    #XXX ugly
    next unless items
    b = PseudoBinding.new(lineno, items)
    expression.process(b) if cond[b]
  end
  last = []
  result.each do |cols|
    next if cols.nil? #when test fails
    result_line = cols.map do |col|
      next if col.nil?
      col.value
    end.join.strip 
    same_results = cols.zip(last).map do |a,b| 
      a.respond_to?(:single) && a.single && a.object_id == b.object_id && !a.is_a?(Numeric) 
    end.all?
    break if same_results
    next if result_line.empty?
    puts result_line
    last = cols
  end
rescue StopIteration
  # end
end

#parse(expr) ⇒ Object



264
265
266
267
268
269
270
271
272
273
274
# File 'lib/parsely.rb', line 264

def parse(expr)
  val, cond = expr.split(/ if /)
                            # p [ val, cond]

  val = '['+val+']'
  if val =~ /([\(\)\w])( ([\(\)\w]))+/
    val = val.split(" ").join(",")
  end
  r = Expression.new(val)
  [r, parse_cond(cond)]
end

#parse_cond(str) ⇒ Object



276
277
278
279
280
281
282
283
284
285
# File 'lib/parsely.rb', line 276

def parse_cond str
  case str
  when %r[/.*/]
    proc { |bnd| bnd.instance_eval(str) === bnd._0 }
  when nil, ''
    proc { |bnd| true }
  else
    proc { |bnd| bnd.instance_eval(str) }
  end
end