アンダースコアだけで Ruby プログラムを書くライブラリ _

を作りました。github にアップロード済み。

ref: http://github.com/mame/_/tree/master

インストール

自己責任で。

$ gem install mame-_ --source=http://gems.github.com/

サンプル

Hello, world! プログラム *1

require "_"
____ _ _____ ____ __ ____ ____ __ ___ ____ __ __ _ ______
_____ ___ _ _ ___ _____ ______ ____ _ _ ____ _ _ ____ _
____ __ __ ___ _ ______ ___ ____ __ ______ ____ _ ____ ____
__ _ ____ _ _ ___ _____ _____ _ ______ ____ _ ______ _____

ただの Ruby プログラムなので、ruby で普通に実行できます。1.8 でも 1.9 でも OK *2 。改行の位置は好きなように変えていいです (順序は変えちゃダメ) 。

$ ruby18 __hello__.rb
Hello, world!

$ ruby19 __hello__.rb
Hello, world!

エンコード

__script__ メソッドでできます。

$ echo -n 'puts"Hello, world!"' | ruby19 -r_ -e 'puts __script__($<.read)'
require "_"
____ _ _____ ____ __ ____ ____ __ ___ ____ __ __ _ ______
_____ ___ _ _ ___ _____ ______ ____ _ _ ____ _ _ ____ _
____ __ __ ___ _ ______ ___ ____ __ ______ ____ _ ____ ____
__ _ ____ _ _ ___ _____ _____ _ ______ ____ _ ______ _____

どうでもいいこと

なんとなく _ にしましたが、英文字ならなんでもいいです。

$ ruby19 -r_ -e '
abcd e fghij klmn op qrst uvwx yz abc defg hi jk l mnopqr
stuvw xyz a b cde fghij klmnop qrst u v wxyz a b cdef g
hijk lm no pqr s tuvwxy zab cdef gh ijklmn opqr s tuvw xyza
bc d efgh i j klm nopqr stuvw x yzabcd efgh i jklmno pqrst
'
Hello, world!

文字数にあわせて英作文できたらかっこよかったけど、英語力的に無理だった。

どうでもいいこと 2

github いじめ。_ という名前のリポジトリを扱えるのかなーと。やってみたところ、作るだけならできたけど push できなかった (Invalid url とかなんとか言われた) 。それでどうしたかというと、

  • まず underscore という普通の名前でリポジトリを作り、gem 生成を有効にする
  • ソース一式と _.gemspec と underscore.gemspec を push する (どっちの gemspec が動いたかは知らない)
  • リポジトリの名前を _ に変える (変えたらもう push できなくなった)
  • 宝石のアイコンをクリックして Rebuild Latest Rubygems を押す

という手順でできた。
github のソースツリーで lib 以下が見えない。バグっぽくていいですね。そのせいでソースが見えないので (gem install や git clone すれば見えるけど) 、この記事の最後にソースを貼っときます。
まあ mame-_ みたいな名前の gem を作りたいだけなら gemspec だけ編集すればよかったのかもしれない。
github をいじめた天罰か知らないけど、エイプリルフールにあわせて作ったのに github の gem 生成サーバが落ちてたせいで 4/1 中に公開できなかった。ちくしょう。

ソース

def __script__(src)
  code = []
  src = src.unpack("C*").map {|c| c.ord.to_s(6).rjust(3, "0").chars.to_a }
  src.flatten.map {|n| n.to_i(6) + 1 }.each do |n|
    code.empty? || code.last.size + n + 1 >= 60 ? code << "" : code.last << " "
    code.last << "_" * n
  end
  ([%q(require "_")] + code).join("\n")
end

$code, $fragment = [], []
def method_missing(mhd, *x)
  if x.empty?
    $code.concat($fragment.reverse)
    $fragment.clear
  end
  $fragment << mhd.to_s.size - 1
end

at_exit do
  $code.concat($fragment.reverse)
  eval($code.join.scan(/.../).map {|c| c.to_i(6) }.pack("C*"))
end

*1:require があるのが気に入らなかったら、コマンドラインに -r_ をつけるのでもいいです (1.8 だとダメかも) 。

*2:古すぎる 1.8 だと警告が出るかも。