2007年 11月 01日

blosxom clone ekfloras

http://coderepos.org/share/browser/lang/ruby/ekfloras

Ruby で blosxom クローンを書いてみた。他の言語と違って blosxom のプラグインの雰囲気をのこしたり、まじめに使うことをちょっと考えたりするように。

テンプレートエンジンに ERB と Erubis どっちもサポートしようとおもって書いていたけど、途中でテンプレートが Erubis 専用になってしまっていることに気付いてめんどくなったのでどっちもやめて (イミフ) 前書いた MiniERB をつかうようにした。(空白圧縮とかしないけど ERB の 2.5 倍ぐらいはやい)

いまどきブログ CGI なんて書いてもだれもつかわないんだけどなぁ。ふつうにどっかのサービスつかったほうがいい。でも blosxom 系のはブログつーるというより他の使いかたをしやすいからおもしろい。

最近の blosxom クローンのまとめ

最近の、であって、僕が書いた、じゃないですよ? (coderepos にあるもののみ)

(使えそうな順にならんでます)

Lua は付属インタプリタでは実装できない。PHP と Python はやりたいと思わない。VBScript は Windows で CGI 環境つくるのがめんどうくさい。

Haskell と C# (on mono) あたりはやってみたいけど、ここで「やってみたい」とか書いている限りやらないだろう。本当にやってみたいなら既にやっているはずだ。

2007年 10月 31日

Perl memo

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'}

http://twitter.com/typester/statuses/375208972

@_[KERNEL, SESSION] とかが全く読めなくてこまったんだぜ! (そして最終的に使わなかった)

n行で書くテンプレートエンジン

io のやつは 50 行ぐらいだった。いい線じゃないですか!! 正規表現ないのに!!! (あるけど標準じゃない)

とかはどうでもよくて、Ruby で 40 行で ERB に似てるテンプレートエンジン (たぶんすごいだめなバグがある気がする)

class MiniERB
	module Util
		ESCAPES = { "&" => "&amp;", "<" => "&lt;" , ">" => "&gt;"}

		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
end

sample

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 = { "&" => "&amp;", "<" => "&lt;" , ">" => "&gt;"}

		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 になるからやらなくていい。

スペルが全く覚えられない感じだけど、幼女が「しゅわるちゅへんかんー」とか言ったら萌えるんじゃないか、と一瞬思った。「だけど」の前と繋がってないな。

2007年 10月 30日

Chemr + Amalgam

Chemr でいっぱい開いてると、目的のやつにたどりつくまでめんどいので、Amalgam から検索できるようにしてみた。DRb++

http://screencast.com/t/9jJng5yu7U

http://lab.lowreal.net/test/chemr/Chemr.2007-10-30.dmg (設定可能版の Chemr)

  • http://svn.coderepos.org/share/lang/ruby/Amalgam/user-plugins/chemr.rb を ~/.amalgam/plugins に
  • うえのファイルの =begin ~/.chemr/initrc.rb から =end までを ~/.chemr/initrc.rb に追記
  • Chemr 再起動してファイルたくさんひらく
  • .d r "Chemr" (プラグインのトップレベル候補をリロード)
    • 機能のバージョンだとできないので touch ~/.amalgam/plugins/chemr.rb して .d reload_plugins
  • chm ファイル名でトップレベルに候補追加
  • 選択して RET するとサブランチャに (初回は Chemr から index をとってくるのでおもい)
  • さらに選択して RET すると該当のウィンドウがアクティブになって項目を表示

libruby ふくめてないからそのままだと落ちると思う。ぜんぶにふくめたほうがいいのだろうなぁ……

ローカル gem の chm バンドルをつくる ruby スクリプト

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 から変換すれば簡単にできるだろうけれど、時間かかるのでめんどそう

mobirc いれた

これはすばらしい。

keitairc のとき読むのがめんどくさくてずっと basic password を毎回いれてたけど、これで開放される…… (N73 は接続きれたりすると再入力になってしまう)

あとキーワード機能がすばらしいなぁ。重要なのだけピックアップできるのがすてき。

モバイルの CSS ってどんぐらい効くんだろう。N73 だと twitter がかなり綺麗に表示されるけど、あれは外部 CSS になってんのかなぁ。モバイル事情を知らなすぎる。

N73 メモ

  • ブロック要素でも縦の margin 指定がきかない
  • padding はきく
  • body { margin:0; padding:0 } しても上下にマージンがでる
  • bold にならない
  • フォントサイズは割と変えられる (というか ttf よんでる)
  • input[type="text"] に対応している (CSS2)
  • 外部スクリプトは呼べない
  • document.writeln だけ確認
  • Opera mini
    • 外部スクリプトよべる
    • alert できる (中央にメッセージ表示)
    • Opera のサーバを経由する (全部のページがケータイ向けに変換かかる)

gerry++

なんか腹痛い……