rubyのAPIドキュメントをruby-doc-server.exeでなく,CGIとして任意のディレクトリで動かしたい
http://localhost/ruby-doc/ にドキュメント置きたい
localhost にあるとナニカと便利なAPIドキュメント.
rubydoc-serverをローカルホストで動かしたいなとか思った。apache/webrickで動かそうと思ったんです。検索して見つけた!と思ったらrubyAPIドキュメントサーバーをReverseProxyで動かす話で,ガッカリしたので、ソースを調べた。
るりまで検索すると楽だけど,僕はHTMLが欲しいんですね.オフラインでも使うので.
http://www.ruby-lang.org/ja/documentation/ を見ていると、htmlのDLは無く、refeパッケージだけが見つかるのです・・・
CGIで使うために、動作をちゃんと追いかけてみた
起動ファイルの中身
rubydoc サーバーの起動ファイルは次のようになっていた.
server.rb
#!/usr/bin/ruby -Ke Dir.chdir File.dirname(__FILE__) standalone = "bitclust/standalone.rb" src = File.read(standalone).sub(/\$0/) { standalone.dump } ARGV.unshift "--bind-address=127.0.0.1" ARGV.unshift "--baseurl=" ARGV.unshift "--debug" ARGV.unshift "--auto" ARGV.unshift "--capi" eval src, binding, standalone, 1
シェルスクリプトを実行するファイルだった.実体はstandalone.rbらしい
起動スクリプトから standalone.rb を見ればいいと分る
呼ばれている standalone.rb を見る
standalone.rb もシェルスクリプトとして実行される.optparseが引数を受け取って展開する.
起動スクリプトに戻り、指定されるオプションを調べる.
次のオプションが指定されている.
standalone に渡されるオプション
autop = true debugp = true capi = true baseurl = "" bind-address=127.0.0.1 $0 = /usr/local/doc/ruby/server.rb #ruby doc インストールした場所。
以上の初期値を持ってWebrickを作成しているようだ.
#optparse の基本設定から導出
set_srcdir = lambda {|path| srcdir = path datadir ||= "#{srcdir}/data/bitclust" themedir ||= "#{srcdir}/theme" libdir ||= "#{srcdir}/lib" } set_srcdir.call "MY_PATH"
メインの処理部分
ココがメインらしい
if autop #autop=trueなのでここが実行される app = BitClust::App.new( :dbpath => Dir.glob("db-*"), # インストール済みのRubyドキュメント :baseurl => baseurl, #=> set_srcdir より :datadir => datadir, #=> set_srcdir より :templatedir => templatedir, #=> set_srcdir より :theme => theme, #=>default 固定 :encoding => encoding, #=> euc固定 :capi => capi ) app.interfaces.each do |version, interface| server.mount File.join(basepath, version), interface end server.mount(File.join(basepath, '/'), app) end server.mount File.join(basepath, 'theme/'), WEBrick::HTTPServlet::FileHandler, themedir
仕組みが分ったので、webrick で任意の場所にマウントしてみる
毎回、起動するのが面倒なので、いつも常駐しているWebrickにマウントしておく
$:.push "/usr/local/doc/ruby/bitclust/lib" #bitclust をパスに含める require 'bitclust' require 'bitclust/app' # 変数の初期化 baseurl = dbpath = srcdir = libdir = datadir = themedir = theme = templatedir = nil set_srcdir = lambda {|path| srcdir = path datadir ||= "#{srcdir}/data/bitclust" themedir ||= "#{srcdir}/theme" libdir ||= "#{srcdir}/lib" } set_srcdir.call "/usr/local/doc/ruby/bitclust" #ドキュメントのインストール場所指定 baseurl="/ruby" #webrickのマウントパス basepath = URI.parse(baseurl).path encoding = "euc" capi = true app = BitClust::App.new( :dbpath => Dir.glob("/usr/local/doc/ruby/db-*"),#バージョン毎のドキュメントを探す :baseurl => baseurl, :viewpath => baseurl, :datadir => datadir, :templatedir => templatedir, :theme => theme, :encoding => encoding, :capi => capi ) #CGIマウント処理 app.interfaces.each do |version, interface| # バージョン毎のドキュメントをそれぞれマウントする /1.8.7/... /1.9.2/... を実現している箇所 srv.mount File.join(basepath, version), interface end # cssを設定 srv.mount File.join(basepath, 'theme/'), WEBrick::HTTPServlet::FileHandler, themedir #メインページ srv.mount(File.join(basepath, '/'), app)
BitClust::Appの適当な実装を修正
readme.htmlの探し先が結構適当なので、デフォルトの場所から詠むように修正.
100: if File.exist?("readme.html") 101: @index = File.read("readme.html").sub(%r!\./bitclust!, '').sub(/<!--links-->/) { links } 102: else 103: @index = "<html><head><title>bitclust</title></head><body>#{links}</body></html>" 104: end
以下のように書換え
100: if File.exist?("readme.html") 101: @index = File.read("readme.html").sub(%r!\./bitclust!, '').sub(/<!--links-->/) { links } 102: elsif File.exist?(File.join(@options[:datadir],"../../../readme.html")) 103: @index = File.read(File.join(@options[:datadir],"../../../readme.html")).sub(%r!\./bitclust!, './').sub(/<!--links-->/) { links } 104: else 105: @index = "<html><head><title>bitclust</title></head><body>#{links}</body></html>" 106: end
最後に関数に仕上げた.
好きな場所にマウントしたくなったので関数にして置いた.
def mount_rubydoc(server,mount_point_uri_path,path_to_ruby_doc) $:.push File.join(path_to_ruby_doc, "bitclust/lib") require 'bitclust' require 'bitclust/app' baseurl = dbpath = srcdir = libdir = datadir = themedir = theme = templatedir = nil set_srcdir = lambda {|path| srcdir = path datadir ||= "#{srcdir}/data/bitclust" themedir ||= "#{srcdir}/theme" libdir ||= "#{srcdir}/lib" } set_srcdir.call File.join(path_to_ruby_doc,"bitclust") baseurl=mount_point_uri_path basepath = URI.parse(baseurl).path app = BitClust::App.new( :dbpath => Dir.glob(File.join(path_to_ruby_doc,"db-*"), :baseurl => baseurl, :viewpath => baseurl, :datadir => datadir, :templatedir => templatedir, :theme => theme, :encoding => "euc", :capi => true ) app.interfaces.each do |version, interface| server.mount File.join(basepath, version), interface end server.mount(File.join(basepath, '/'), app) server.mount File.join(basepath, 'theme/'), WEBrick::HTTPServlet::FileHandler, themedir end
使い方
srv = WEBrick::HTTPServer.new({:BindAddress => '127.0.0.1',:Port => 80}) mount_rubydoc(srv,"/ruby-doc","/usr/local/doc/ruby") trap("INT"){ srv.shutdown } srv.start
感想
役に立つか立たないかは分らない.だけどただ動いている.それだけでチョッと幸せになれます.
参考資料
リバプロでやってる人.
http://d.hatena.ne.jp/msh_trumpet/20080103/1199371363