Class: Parsely
- Inherits:
-
Object
- Object
- Parsely
- 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
- #load_rc ⇒ Object
- #main ⇒ Object
- #main_loop(expr, lines) ⇒ Object
- #parse(expr) ⇒ Object
- #parse_cond(str) ⇒ Object
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_rc ⇒ Object
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 |
#main ⇒ Object
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 |