I thought of adding more bits by using other whitespace characters, but
in the end stuck with space and tab, since everything will render them
as whitespace (whereas almost any other whitespace I tried showed up as
garbage in one editor/reader or another). Also, I didn't use linefeed
nor carriage return, since non-binary transmission from one system to
another could potentially break the file (ie, eol conversion).
Anyway, here's my solution. I tried to keep it short and simple but
should still be easily understood.
#!/usr/bin/env ruby
Bits = '01'
Blank = " \t"
def shebang(f)
f.pos = 0 unless f.gets =~ /^#!/
end
def confuse(fname)
File.open(fname, File::RDWR) do |f|
shebang f
f.pos, data = f.pos, f.read
f.puts "require '#{File.basename($0, '.*')}'"
f.write data.unpack('b*').join.tr(Bits, Blank)
f.truncate f.pos
end
end
def clarify(fname)
File.open(fname, File::RDONLY) do |f|
shebang f
f.gets # skip require 'whiteout'
eval [f.read.tr(Blank, Bits)].pack('b*')
end
end
if __FILE__ == $0
ARGV.each { |fname| confuse fname }
else
clarify($0)
end