2007年 10月 13日

Erubis

gems 使えるコンテキストでは全部 Erubis 使うようにしよう。Erubis::EscapedEruby つかおう。
デメリットがない

gems

なんで gem spec のファイルを YAML にしちゃったのかなぁ。Ruby で eval できるコードを吐けばもっと高速で YAML への依存が減らせるのに
この場合 YAML 使う理由ってなんだろう。他の言語から読みかきするわけじゃないしというか結局吐く YAML が Ruby 依存になるし……

とおもったら、ローカル spec は Ruby で eval できるコード吐いてた (キャッシュは Marshal)。すいませんすいません。サーバとのやりとりだけ YAML なのかな

Ruby に use を実装する。

RubyGems みたいに、あらかじめ spec をキャッシュしておく、みたいなのが許されるなら、こういうのもありなんじゃないかなぁと思った。以下の実装はいろいろだめなところがあるだろうけど…… (プラットホーム依存のところがほげほげとか)

# module 名 -> ファイル名へのハッシュテーブルを作る
# ruby 起動しまくって時間がかかるので前もってキャッシュする
require "pathname"
module_files = {}
$LOAD_PATH.each do |path|
	path = Pathname.new(path)
	next if path.relative?
	Pathname.glob(path + "**/*").each do |t|
		next unless t.file?
		next if t.to_s =~ /tk/
		puts t
		ENV.delete("RUBYOPT")
		ret = nil
		IO.popen("ruby", "r+") do |io|
			io.puts <<-CODE
				# 自分自身はロード済みにしないと、ループして require している場合にまずい
				$LOADED_FEATURES << '#{t.relative_path_from(path)}'
				$depend_lib = []
				def __modules
					ret = []
					ObjectSpace.each_object(Module) do |o|
						ret << o
					end
					ret
				end

				alias _require_orig require
				def require(lib)
					prev = __modules
					ret = _require_orig(lib)
					if ret
						$depend_lib.concat(__modules - prev)
					end
					ret
				end

				def set_trace_func(*)
				end

				prev = __modules
				stdout = STDOUT.dup
				STDOUT.reopen($stderr)
				begin
					_require_orig '#{t}'
				ensure
					STDOUT.reopen(stdout)
					print Marshal.dump((__modules - prev - $depend_lib).map {|i| i.to_s })
					STDOUT.flush
					exit!
				end
			CODE
			io.close_write
			ret = io.read
			ret = Marshal.load(ret)
		end
		ret.each do |m|
			(module_files[m] ||= []) << t.to_s
		end
	end
end

require "pp"
File.open("module.cache", "wb") do |f|
	Marshal.dump(module_files, f)
end

本体

def use(mod)
	mod  = mod.to_s
	mods = Marshal.load(File.read("module.cache"))
	raise LoadError, "#{mod} is not found." unless mods[mod]
	mods = mods[mod].map {|i|
		[i, i.split(File::ALT_SEPARATOR || File::SEPARATOR).size]
	}.sort_by {|i,ii|
		ii
	}
	mods.select {|i,ii| ii == mods.first[1] }.each do |i,ii|
		require i
	end
end

use %(Test::Unit::AutoRunner)
use %(Test::Unit::TestCase)

class UseTEST < Test::Unit::TestCase
	def test_success
		use %(Pathname)
		assert_kind_of Class, Pathname

		use %(Test::Unit::AutoRunner)
		assert_kind_of Class, Test::Unit::AutoRunner

		use %(ERB)
		assert_kind_of Class, ERB

		use %(ERB::Util)
		assert_kind_of Module, ERB::Util

		use %(WEBrick)
		assert_kind_of Module, WEBrick

		use %(Net::HTTP)
		assert_kind_of Module, Net
		assert_kind_of Class, Net::HTTP

		assert_raise(LoadError) do
			use %(NotInTableModule)
		end
	end
end

Test::Unit::AutoRunner.run($0 != "-e" && $0)

テーブルは require しているファイルに定義されているクラスを除いているので、test/unit.rb みたいな require をしている場合、そのファイルにいくら定義があっても「クラスの再定義/上書き」という判断しかできないので、use "Test::Unit" とかしても test/unit.rb は読みこまれない。

あとは webrick なんかを例にとると webrick.rb は他のファイルを require するだけなので、直接はこのファイルはモジュールハッシュ上にあらわれない。use では同じ深さを持っていて、WEBrick を定義している全てのファイルを require してる。

もっとたくさんテスト書いて、実装精密にすればつかえるかなぁ……

どっかのサーバで rubyforge の gems をミラーして解析して、このテーブルをつくっておいて、パッケージ検索できるようにするとか、あるいはそのままパッケージシステムにしてしまうとかがおもしろいかなぁ。既存の gems をそのままもってこれてたのしそう。

2007年 10月 12日

It's All Text! 使うことにした

C-f (Vim の Command モードとかのバインド) で開くようにしてみた。

でも input type="text" には無力なんだなぁ

今日の ~/tmp/test.rb

require "rubygems"
require "pathname"
require "active_record"

ActiveRecord::Base.establish_connection(
	:adapter => "sqlite3",
	:database => "test.db"
)

class Article < ActiveRecord::Base

end

~/tmp を定期的に晒すとか面白そう。でもだいたい公開できない。

gerry++

はらいたい

2007年 10月 11日

n ly n nazo

#!ruby

require "nkf"

data = DATA.read.split(/¥n/)

def copy(str)
	puts str
	str = NKF.nkf("-s", str)
	IO.popen("pbcopy", "w") do |io|
		io.print str
	end
	str
end

copy(data.shift)
board = `pbpaste`
loop do
	boardn = `pbpaste`
	boardn = nil if  boardn.empty?
	unless board == boardn
		str = data.shift
		copy(str)
	end
	board = `pbpaste`
	sleep 0.3
end

__END__
1
2
3

NSPasteboard はデータ取得がいまいち安定しない。

2007年 10月 10日

リリースプロセス

よくわかんないなぁ。変更して「まだあるかもしれない」とおもってリリースしないでいると、「あれどこまでの変更をリリースしたっけ」とか思ってしまう。うーん

rubyforge にリリースできない

リリースしようとするとエラーでるなぁ。普通にウェブからやってもエラーでる。rubyforge (gem のほう) は、hpricot とか使って Error: の部分を出すようにすべきだ……

gem って post-installed フックできないのかしら