ayaniimi213
2/8/2013 - 4:44 AM

LTSV viewer in Ruby

LTSV viewer in Ruby

#! /usr/local/bin/ruby
require 'ltsv'
require 'yaml'
require 'optparse'

options = nil
ARGV.options do |opt|
  opt.banner << " [file...]"
  options = LTSV.def_options(opt)
  opt.parse!
end
LTSV.parse(ARGF, **options) do |row|
  puts row.to_yaml
end
# -*- coding: us-ascii -*-

require 'csv'
require 'yaml'

class LTSV < CSV
  attr_accessor :ordered
  alias ordered? ordered

  def self.def_options(opt, options = {})
    opt.on("-k", "--keys", "--select-keys keys", Array, "comma separated list of keys to select") do |ary|
      (options[:select] ||= []).concat(ary)
    end
    opt.on("-i", "--ignore-keys keys", Array, "comma separated list of keys to ignore") do |ary|
      (options[:ignore] ||= []).concat(ary)
    end
    opt.on("--no-ordered", "sort keys in alphabetical order") do |ordered|
      options[:ordered] = ordered
    end
    opt.on("-m", "--match key:regexp", /\A([^:]+):(.*)/, "filter output by keys against regexp") do |_, key, re|
      ((options[:match] ||= {})[key] ||= []) << Regexp.new(re)
    end
    options
  end

  def initialize(data, match: nil, select: nil, ignore: nil, ordered: true, **options)
    super(data, col_sep: "\t", **options)
    if match
      matches = {}
      match.each {|key, re| matches[key] = Regexp.union(re)}
    end
    @matches = matches
    @select_keys = (select if select and !select.empty?)
    @ignore_keys = (ignore if ignore and !ignore.empty?)
    @ordered = ordered
  end

  def shift
    while row = super
      row = row.map {|col| col.split(':', 2)}
      if @matches
        row = Hash[row]
        next unless @matches.any? {|key, re| re =~ row[key]}
      end
      if ordered?
        row = row.to_a
        row.sort!
      end
      row = row.select do |key, val|
        (!@select_keys or @select_keys.include?(key)) and
          (!@ignore_keys or !@ignore_keys.include?(key))
      end
      return Hash[row]
    end
  end
end