Website/slides/talks/2018-1-Tour-Mimir/data/PushdownVis/csvx.rb

65 lines
1.5 KiB
Ruby
Executable file

class String
def from_csv(sep = /,/)
ret = [[]]
c = chars
quote = "\""
comma = ","
i = 0
expecting_quote = false
while i < c.length
if c[i] == quote
if ret[-1].empty? then expecting_quote = true
elsif c[i+1] == quote then i += 1; ret[-1].push(quote)
elsif expecting_quote and (c[i+1] == comma) then
ret.push([])
expecting_quote = false
i += 1
elsif expecting_quote and (c[i+1] == nil) then
expecting_quote = false
else
raise "Invalid CSV Line (misplaced quote at #{i}; #{c[i+1]}): #{self}"
end
elsif c[i] == comma
if expecting_quote
ret[-1].push(comma)
else
ret.push([])
expecting_quote = false
end
else
ret[-1].push(c[i])
end
i += 1
end
ret.map { |col| col.join}
end
end
class Array
def from_csv
self.map { |l| l.to_s.chomp.from_csv }
end
def to_csv(f)
File.open(f, "w+") { |f| each { |row| f.puts(row.join(',')) }}
end
end
class IO
def from_csv(args = {})
header = args.fetch(:header, false)
separator = args.fetch(:separator, /,/)
keys = readline.chomp.
sub(/ *$/, "").sub(/^ */,"").
from_csv(separator) if header;
map { |l| l.to_s.chomp.from_csv(separator) }.
map { |a| if header then keys.zip(a).to_h else a end }
end
end
class File
def File.csv(f, args = {})
File.open(f) {|io| io.from_csv(args) }
end
end