ksherlock-iigs/aaae.rb

228 lines
3.7 KiB
Ruby
Raw Normal View History

#!/usr/bin/env ruby -w
#
# apple ascii art encoder.
#
require 'optparse'
#
# read stdin
# --trim -> trim trailing whitespace
# --dle -> compress > 2 spaces into a dle
# --indent=# -> indent it by # spaces
# --width=# -> console width (default = 80)
# --center -> center block assuming width
# --target=x -> target language (c, orca, mpw, etc)
#
# todo -- expand tabs? (--ts=8)
# todo -- left/right/center slign block?
#
#
# output char name[] = { 0x01, 0x02, ... };
#
def output_bytes(name, data)
tmp = data.join('')
index = 0
if name
puts "char #{name}[] = {"
else
puts "{"
end
tmp.each_byte {|b|
print " " if index == 0
2015-08-05 13:24:11 +00:00
printf("0x%02x, ", b)
index = index + 1
2015-08-05 13:24:11 +00:00
if index == 8
print "\n"
index = 0
end
}
2015-08-05 13:24:11 +00:00
puts "0x00\n"
#print "\n" if index > 0
puts "};"
end
#
# output char name[] = { "bleh\r","bleh\r" };
#
def output_strings(name, data)
map = {
0x0d => "\\r",
0x0a => "\\n",
}
if name
puts "char #{name}[] = "
end
data.each {|x|
# escape \
2015-08-05 13:24:11 +00:00
x = x.gsub(/([\\"])/) {|m| '\\' + m }
# escape "
2015-08-05 13:24:11 +00:00
#x = x.gsub(/"/, '\"')
# escape chars...
# unfortunately, \x doesn't have a length limit so
# it can't be used. octal sucks but it's limited
# to 3 characters.
x = x.gsub(/([\x00-\x1f\x7f])/) {|m|
c = m.getbyte(0)
next map[c] if map[c]
sprintf("\\%03o", c)
}
printf(" \"%s\"\n", x)
}
puts ";"
end
data = []
options = {
:trim => true,
:dle => false,
:indent => 0,
:width => 80,
:center => false,
:dry_run => false,
:name => nil,
:format => :string
}
OptionParser.new do |opts|
opts.banner = "Usage: aaae.rb [options] [input file]"
opts.on("--[no-]trim", "Trim trailing white space from input.") do |x|
options[:trim] = x
end
opts.on("--[no-]dle", "Use DLE to compress spaces.") do |x|
options[:dle] = x
end
opts.on("--width N", Integer, "Set screen width. Default = 80.") do |x|
options[:width] = x
end
opts.on("--indent N", Integer, "Indent N spaces.") do |x|
options[:indent] = x
end
opts.on("--name N", String, "Set variable name.") do |x|
if x.match(/^[A-Za-z_][A-Za-z0-9_]*$/)
options[:name] = x
else
$stderr.puts "Invalid name -- #{x}"
end
end
opts.on("-f", "--format FORMAT", [:string, :bytes], "Set output format (string, bytes)") do |x|
options[:format] = x
end
opts.on("--[no-]center", "Center output.") do |x|
options[:center] = x
end
opts.on("--dry-run", "Simulated output.") do
options[:dry_run] = true
end
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit
end
opts.on_tail("--version", "Show version") do
puts "aaae.rb 0.1"
exit
end
end.parse!
ARGF.each_line {|x|
x.chomp!
x.rstrip! if options[:trim]
data.push(x)
}
# option to strip leading space?
if (options[:trim])
end
# get the width of the block.
bw = data.reduce(0) {|akku, x|
next x.length if x.length > akku
next akku
}
if options[:indent] > 0
space = ' ' * options[:indent]
data = data.map {|x| space + x }
end
if options[:center]
indent = (options[:width] - bw) / 2
space = ' ' * indent
data = data.map {|x| space + x }
end
# todo -- check if any lines > screen width...
if options[:dry_run]
width = options[:width]
print "+", "-" * width, "+\n"
#print "|", " " * width, "|\n"
data.each {|x|
printf("|%-*s|\n", width, x)
}
#print "|", " " * width, "|\n"
print "+", "-" * width, "+\n"
exit 0
end
# dle!
if options[:dle]
data = data.map {|x|
x.gsub(/( {3,})/) {|m|
size = m.length
next "\x10" + (size + 32).chr
}
}
end
# now add r/n
data = data.map {|x| x + "\r" }
# now output
# should have flag for text vs bytes, asm, etc.
case options[:format]
when :string
output_strings(options[:name], data)
when :bytes
output_bytes(options[:name], data)
end