GranParadiso
Firebug1.1.0b7 を入れた。うごいている。しかしいままで以上に重い。GranParadiso の重さと相乗効果
はてなのマルチログイン uc.js がないと激しく不便なのでデバッグして Fx3 向けに修正した。tumblr のやつも同じ修正が必要だけど、あんま使ってないのでそのうちでいいや。
Firebug1.1.0b7 を入れた。うごいている。しかしいままで以上に重い。GranParadiso の重さと相乗効果
はてなのマルチログイン uc.js がないと激しく不便なのでデバッグして Fx3 向けに修正した。tumblr のやつも同じ修正が必要だけど、あんま使ってないのでそのうちでいいや。
とりあえず module/pluggable を使っていたものの、別にリロードとかできなくていい (CGI なので使い捨て) ので、もっと簡単なプラグインシステムにした。ついでに rubygems への依存もなくなったので、純粋に Ruby がインストールされていればレポジトリからチェックアウトしてすぐ動くようになった。
# プラグインファイルをロードして
# インスタンスの配列を実行すべき順にソートして返す
def load_plugins
Pathname.glob(@opts[:plugin_dir] + "/**/*.rb") do |f|
load f
end
pm = self.class.const_get(:Plugin)
pm.constants.inject([]) {|r,i|
r << pm.const_get(i).new(self)
}.sort_by {|i|
i.priority
}
endみたいにして Ekfloras::Plugin::* をプラグインとみなし、メソッドをよぶ。かなり簡単だけど普通は十分なプラグイン機構だと思う。(ファイル名とクラス名間の名前の制約がなくなるので、てきとーにプラグインんが書けるようになる。逆にこれのせいでリロードとかが実装できない) こんだけ単純だと特にライブラリする必要もないので欲しくなったときに書きなぐればいいのがいい。
(priority メソッドの返り値でソートしているのは、プラグイン同士で実行順に気をつかうようにするため。blosxom だと名前順になっているから、各ユーザがプラグインの仕組みを理解してファイル名を書きかえたりしないといけなかったけど、これでだいたいてきとーにプラグインディレクトリにほうりこんでも動くようになるはず)
ちゃんとインスタンス化してメソッドをよぶようになるので、各プラグイン内のメソッドの名前がコンフリクトしたり、データが共有されることがなくていい。ちゃんとメソッド間ではデータ共有できるし (こんなのあたりまえなんだけど、Ruby 系のプラグイン機構ってこういうあたりまえのことができないのが多いイメージ)
あとは設定かな。設定はできるだけ書きたくないから (blosxom のプラグインのいいところは投げこめば動くことだと思う)、最小設定と、オプションをいくつかとかになるかな。
(EntriesCache なし)
ruby 1.8.4 1159 files, 1.212316 sec 1159 files, 1.722761 sec 1159 files, 1.390812 sec 1159 files, 1.353448 sec 1159 files, 1.423345 sec ruby 1.9.0 (2007-09-24 patchlevel 0) [i686-linux] 1159 files, 1.025227 sec 1159 files, 1.075664 sec 1159 files, 1.202309 sec 1159 files, 1.300395 sec 1159 files, 1.284752 sec
ruby 1.8.4 1159 files, 0.733907 sec 1159 files, 1.166876 sec 1159 files, 1.437776 sec 1159 files, 0.857321 sec 1159 files, 0.906379 sec ruby 1.9.0 (2007-09-24 patchlevel 0) [i686-linux] 1159 files, 0.315943 sec 1159 files, 0.301194 sec 1159 files, 0.446674 sec 1159 files, 0.254224 sec 1159 files, 0.45789 sec
EntriesCache (エントリをオブジェクト化した状態でマーシャライズしてキャッシュするプラグイン) 入れた ruby1.9 がかなりはやい。
http://coderepos.org/share/browser/lang/ruby/ekfloras
Ruby で blosxom クローンを書いてみた。他の言語と違って blosxom のプラグインの雰囲気をのこしたり、まじめに使うことをちょっと考えたりするように。
テンプレートエンジンに ERB と Erubis どっちもサポートしようとおもって書いていたけど、途中でテンプレートが Erubis 専用になってしまっていることに気付いてめんどくなったのでどっちもやめて (イミフ) 前書いた MiniERB をつかうようにした。(空白圧縮とかしないけど ERB の 2.5 倍ぐらいはやい)
いまどきブログ CGI なんて書いてもだれもつかわないんだけどなぁ。ふつうにどっかのサービスつかったほうがいい。でも blosxom 系のはブログつーるというより他の使いかたをしやすいからおもしろい。
最近の、であって、僕が書いた、じゃないですよ? (coderepos にあるもののみ)
(使えそうな順にならんでます)
Lua は付属インタプリタでは実装できない。PHP と Python はやりたいと思わない。VBScript は Windows で CGI 環境つくるのがめんどうくさい。
Haskell と C# (on mono) あたりはやってみたいけど、ここで「やってみたい」とか書いている限りやらないだろう。本当にやってみたいなら既にやっているはずだ。
mobirc で Perl の学習をする日
検索用 -> 変数に入れたメソッド名・サブルーチン名でサブルーチンを呼びだす Ruby send
$self->$method_name;
{
no strict 'refs';
&$method_name();
}
__PACKAGE__->can($method_name)->();POE と Perl の基本メモ
KERNELとかはPOEがエクスポートしてる関数。@array[1,2,3] とかは配列のスライス。ハッシュ版は @hash{'key1', 'key2'}
@_[KERNEL, SESSION] とかが全く読めなくてこまったんだぜ! (そして最終的に使わなかった)
io のやつは 50 行ぐらいだった。いい線じゃないですか!! 正規表現ないのに!!! (あるけど標準じゃない)
とかはどうでもよくて、Ruby で 40 行で ERB に似てるテンプレートエンジン (たぶんすごいだめなバグがある気がする)
class MiniERB
module Util
ESCAPES = { "&" => "&", "<" => "<" , ">" => ">"}
def escape(str)
str.to_s.gsub(/[#{ESCAPES.keys.join}]/o) {|i| ESCAPES[i] }
end
module_function :escape
end
attr_reader :src
def initialize(template)
@src = compile(template)
end
def compile(s)
ret = "_tt_string = ''¥n"
while m = s.match(/<%([^¥s]*)/)
ret << "_tt_string << #{m.pre_match.dump}¥n"
code = m.post_match.match(/(.*?)%>/)
s = code.post_match
code = code[1]
case m[1]
when "h"
ret << "_tt_string << MiniERB::Util.escape(#{code})¥n"
when "="
ret << "_tt_string << (#{code}).to_s¥n"
else
ret << "#{code}¥n"
end
end
ret << "_tt_string << #{s.dump}"
ret
end
def result(binding=TOPLEVEL_BINDING)
eval(@src, binding)
end
endsample
require "time"
entries = [
{
:title => "hoge<<<&>>>>>>>>>>",
:body => "a<a href='aa'>a</a>a",
:date => Time.now
},
{
:title => "fuaaaaa<<<",
:body => "hehe, Nice boat.",
:date => Time.now
},
]
puts MiniERB.new(DATA.read).result(binding)
__END__
<% entries.each do |entry| %>
<div class="entry">
<h2><%h entry[:title] %></h2>
<div class="body"><%= entry[:body] %></div>
<div class="info">Time: <%= entry[:date].xmlschema %></div>
</div>
<% end %>%h で htmlescape 済みの。 = で生のデータうめこみ。
できるだけ式展開するバージョン (早くなると思われる) 同じく 40 行
class MiniERBExpressionExpantion
module Util
ESCAPES = { "&" => "&", "<" => "<" , ">" => ">"}
def escape(str)
str.to_s.gsub(/[#{ESCAPES.keys.join}]/o) {|i| ESCAPES[i] }
end
module_function :escape
end
attr_reader :src
def initialize(template)
@src = compile(template)
end
def compile(s)
ret = "_tt_string = ¥""
while m = s.match(/<%([^¥s]*)/)
ret << "¥#{#{m.pre_match.dump}}"
code = m.post_match.match(/(.*?)%>/)
s = code.post_match
code = code[1]
case m[1]
when "h"
ret << "¥#{MiniERB::Util.escape(#{code})}"
when "="
ret << "¥#{(#{code}).to_s}"
else
ret << "¥"¥n#{code}¥n _tt_string << ¥""
end
end
ret << "¥" << #{s.dump}"
ret
end
def result(binding=TOPLEVEL_BINDING)
eval(@src, binding)
end
end
ベンチマーク
require "time"
data = DATA.read
entries = [
{
:title => "hoge<<<&>>>>>>>>>>",
:body => "a<a href='aa'>a</a>a",
:date => Time.now
},
{
:title => "fuaaaaa<<<",
:body => "hehe, Nice boat.",
:date => Time.now
},
]
require "benchmark"
Benchmark.bmbm do |x|
x.report("concat") { 100000.times {
MiniERB.new(data).result(binding)
} }
x.report("expexp") { 100000.times {
MiniERBExpressionExpantion.new(data).result(binding)
} }
end
__END__
<% entries.each do |entry| %>
<div class="entry">
<h2><%h entry[:title] %></h2>
<div class="body"><%= entry[:body] %></div>
<div class="info">Time: <%= entry[:date].xmlschema %></div>
</div>
<% end %>Mac 1.8.2 / 1.83GHz CoreDuo
ruby 1.8.2 (2004-12-25) [universal-darwin8.0]
Rehearsal ------------------------------------------
concat 35.230000 0.240000 35.470000 ( 36.472992)
expexp 33.690000 0.220000 33.910000 ( 35.208808)
-------------------------------- total: 69.380000sec
user system total real
concat 35.220000 0.210000 35.430000 ( 36.348813)
expexp 33.570000 0.180000 33.750000 ( 34.598484)ubuntu LTS 1.8.4 / Intel(R) Celeron(R) CPU 2.66GHz
ruby 1.8.4 (2005-12-24) [i486-linux]
Rehearsal ------------------------------------------
concat 37.250000 1.040000 38.290000 ( 38.371623)
expexp 36.270000 1.000000 37.270000 ( 42.917439)
-------------------------------- total: 75.560000sec
user system total real
concat 37.110000 0.980000 38.090000 ( 38.109001)
expexp 35.650000 1.030000 36.680000 ( 36.799591)ubuntu LTS 1.9.0
ruby 1.9.0 (2007-09-24 patchlevel 0) [i686-linux]
Rehearsal ------------------------------------------
concat 37.910000 0.060000 37.970000 ( 38.100921)
expexp 35.910000 0.010000 35.920000 ( 35.944483)
-------------------------------- total: 73.890000sec
user system total real
concat 37.870000 0.010000 37.880000 ( 37.909874)
expexp 36.040000 0.020000 36.060000 ( 37.622068)>
いちおうはやくなったようだ。誤差の範囲すぎる。
(あたまわるくて意味ないベンチした)
http://en.wikipedia.org/wiki/Schwartzian_transform
覚えた! map sort map みたいなのをいうらしい。やってたけど名前を知らなかったw
Ruby だと sort_by になるからやらなくていい。
スペルが全く覚えられない感じだけど、幼女が「しゅわるちゅへんかんー」とか言ったら萌えるんじゃないか、と一瞬思った。「だけど」の前と繋がってないな。
Chemr でいっぱい開いてると、目的のやつにたどりつくまでめんどいので、Amalgam から検索できるようにしてみた。DRb++
http://screencast.com/t/9jJng5yu7U
http://lab.lowreal.net/test/chemr/Chemr.2007-10-30.dmg (設定可能版の Chemr)
libruby ふくめてないからそのままだと落ちると思う。ぜんぶにふくめたほうがいいのだろうなぁ……
http://coderepos.org/share/browser/lang/ruby/misc/chm-generators/generate-local-gems-chm-bundle.rb
カレントディレクトリに GemRdoc.chm というバンドル (Chemr だけで読める) をつくる (ただしテンプレに Resh をつかっていること前提)。ドキュメントの実体は gempath にあるほうなので、gem install したり削除したりしたら実行しなおす。バンドルみたいにただのディレクトリだと symlink とかつかえてよい。
AR とか AS のももちろんインデクスされるので、そういう系の .chm はいらなくなった。
.chm にコンパイルするのも yaml から変換すれば簡単にできるだろうけれど、時間かかるのでめんどそう