/ 最近 .rdf 追記 設定 本棚

脳log[2009-02]



2009年02月02日 (月) [Vista] リソース モニタのキーボードインターフェイス: P(CPU項目を展開)、D(ディスク項目を展開)、N(ネットワーク項目を展開)、M(メモリ項目を展開)、L(全て展開)、Shift+P,D,N,M,L(それぞれの項目を展開、折り畳み切り替え)

[Ruby][tDiary] tDiaryは、1.9系の Rubyでは 1.9.2から動くようになるのか。

やっぱり nobuさんがやってくれました。

requireの処理の中で、セーフレベルを一時的に 0 に下げる部分があって、この範囲を広げることで、SecurityErrorが出ないようになっていた。(3日前)

画像は、tDiaryの amazon.rbが、リポジトリから持ってきただけの素の Ruby-1.9.2dev(2009-02-03)上で動いているところ。

既に正式版がリリースされて*しまって*いる Ruby-1.9.1との違いを、先月の日記に書いた例で見ていくと、

 $SAFE=1で、カレントディレクトリのスクリプトを requireしたとき

irb192> RUBY_DESCRIPTION
=> "ruby 1.9.2dev (2009-02-03) [i386-mswin32_90]"
irb192> $SAFE=1
=> 1
irb192> require "a"
SecurityError: cannot load from insecure path - Y:/.../Desktop/a.rb
        from (irb):3:in `require'
        from (irb):3
        from C:/Program Files (x86)/ruby/bin/irb192.bat:20:in `<main>'
irb192> require "a.rb"
SecurityError: cannot load from insecure path - Y:/.../Desktop/a.rb
        from (irb):4:in `require'
        from (irb):4
        from C:/Program Files (x86)/ruby/bin/irb192.bat:20:in `<main>'
irb192>

2009-02-03版の ruby-1.9.2devでは、$SAFE=1のとき、カレントディレクトリのスクリプトを requireできない。これは $:($LOAD_PATH)に汚染されていない "." が含まれていようと、require の引数の文字列が汚染されていなかろうと、requireできない。見つけた抜け道は、絶対パスで requireするか、$:($LOAD_PATH)にカレントディレクトリを絶対パスで追加すること("."が含まれる場合はそれより前に追加する必要もある)。

ruby-1.9.1の結果は Release Candidateのときと変わらず、

irb191> RUBY_DESCRIPTION
=> "ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-mswin32]"
irb191> $SAFE=1
=> 1
irb191> require "a"
SecurityError: Insecure operation - require
        from (irb):3:in `require'
        from (irb):3
        from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:20:in `<main>'
irb191> require "a.rb"
a.rb required.
=> true
irb191>

ruby-1.9.1では、拡張子を付けてやるとカレントディレクトリのスクリプトも requireできる。拡張子を付けないときに requireできないのは ruby-1.9.2devも同じだが 、ruby-1.9.1には ruby-1.9.2devにない爆弾がある。$SAFE=1のときの拡張子を付けない requireは、添付ライブラリの requireであっても失敗したりする。

irb191> $SAFE=1
=> 1
irb191> require "stringio"
SecurityError: Insecure operation - require
        from (irb):2:in `require'
        from (irb):2
        from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:20:in `<main>'
irb191> require "stringio.so"
=> true
irb191>

これが原因で、tDiaryを ruby-1.9.1で動かすのは絶望的だと思っている*。(ruby-1.9.1はリリースされちゃったし、スクリプトで対応できる範囲を超えているから)

この部分は SecurityErrorが出ない方向に修正されると思っていたから、ruby-1.9.2devで両方のパターンが SecurityErrorになったのは意外。

 $SAFE=1で、汚染されたパスが $:($LOAD_PATH)に含まれるとき

ruby-1.9.2devでは、汚染されたパスが $:($LOAD_PATH)のどの位置にあるかが重要。

irb192> $SAFE=1
=> 1
irb192> $:.unshift "!tainted!".taint
=> ["!tainted!", "C:/Program Files (x86)/ruby/lib/ruby192/site_ruby/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/site_ruby/1.9.2/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby192/site_ruby", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby/1.9.2/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby", "C:/Program Files (x86)/ruby/lib/ruby192/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/1.9.2/i386-mswin32_90", "."]
irb192> require "cgi"
SecurityError: cannot load from insecure path - Y:/.../Desktop/!tainted!/cgi.rb
       from (irb):3:in `require'
       from (irb):3
       from C:/Program Files (x86)/ruby/bin/irb192.bat:20:in `<main>'
irb192> $:.push $:.shift
=> ["C:/Program Files (x86)/ruby/lib/ruby192/site_ruby/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/site_ruby/1.9.2/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby192/site_ruby", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby/1.9.2/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby192/vendor_ruby", "C:/Program Files (x86)/ruby/lib/ruby192/1.9.2", "C:/Program Files (x86)/ruby/lib/ruby192/1.9.2/i386-mswin32_90", ".", "!tainted!"]
irb192> require "cgi"
=> true
irb192>

ruby-1.9.2devでは、$SAFE=1で、汚染された LOAD_PATHからスクリプトを requireすることはできないが、汚染されていない LOAD_PATHからスクリプトを先に見つけた場合は、requireに成功する。ruby-1.9.1(とruby-1.8.7-p72)ではどうだったかというと、より厳しくて、

irb191> $SAFE=1
=> 1
irb191> $:.unshift "!tainted!".taint
=> ["!tainted!", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby/1.9.1/i386-msvcrt", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby/1.9.1/i386-msvcrt", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/i386-mswin32", "."]
irb191> require "cgi"
SecurityError: Insecure operation - require
        from (irb):3:in `require'
        from (irb):3
        from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:20:in `<main>'
irb191> $:.push $:.shift
=> ["C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby/1.9.1/i386-msvcrt", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/site_ruby", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby/1.9.1/i386-msvcrt", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/vendor_ruby", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1", "C:/Program Files (x86)/ActiveScriptRuby-1.9.1/lib/ruby/1.9.1/i386-mswin32", ".", "!tainted!"]
irb191> require "cgi"
SecurityError: Insecure operation - require
        from (irb):5:in `require'
        from (irb):5
        from C:/Program Files (x86)/ActiveScriptRuby-1.9.1/bin/irb.bat:20:in `<main>'
irb191>

ruby-1.9.1では、汚染されたパスが一つでも $:($LOAD_PATH)に含まれると、(相対パスでの) requireはできない。絶対パスならできるが、そんな書き方はしないので $:($LOAD_PATH)に追加するパスは常に untaintしなければならない。

 ruby-1.9.2dev(2009-02-03)は概ね期待通りの動作だが……

requireしたときのカレントディレクトリの扱いに、不満が残る。

多分、従来の Ruby、ruby-1.9.1や ruby-1.8.7は $:($LOAD_PATH)の要素の汚染状況なんて気にしていなかった。$:に含まれるか含まれないかだけが重要。2005年から現在まで変わっていない、リファレンスマニュアルのこの記述がそれを物語っていないか。

Level 1以上では起動時に以下の違いがある

  • 環境変数 RUBYLIB を $: に加えない
  • カレントディレクトリを $: に加えない
  • (以下略)

その方針に異議を唱えるものではないけれど、この方式には、セーフレベルによる分岐が起動時に限定されるという制限がある。コマンドラインオプション -T を指定したときにしか有効にならず、$SAFEを使ってセーフレベルをコントロールするシナリオでは機能しない。

ruby-1.9.2devは、$:($LOAD_PATH) の要素の汚染状況に注目することで、$SAFEを使ってセールレベルをコントロールする場合でも「環境変数 RUBYLIB を $: に加えない」「カレントディレクトリを $: に加えない」のと同等の制限を課せる可能性を持っている。つまり、「環境変数RUBYLIBとカレントディレクトリは常に $:($LOAD_PATH)に追加される。ただし汚染された状態で。」ということ。

それなのに現在の ruby-1.9.2devの、$SAFE=1の下での requireに対するカレントディレクトリの扱いは、ruby-1.8.7より、むしろ退化している。

ruby-1.8.7では $:($LOAD_PATH)に "." を追加したり取り除いたりすることでカレントディレクトリの扱いを、セーフレベルによらず、スクリプトがコントロールできた。

拡張子の有無で結果が変わる、動作に筋の通らない ruby-1.9.1の requireは論外として、

ruby-1.9.2devでは、カレントディレクトリのスクリプトの requireは $:($LOAD_PATH)によらず、SecurityErrorになる。カレントディレクトリを絶対パスで $:($LOAD_PATH)に追加することでコントロール可能だが、既に含まれているかもしれない "." が邪魔をする。ruby-1.9.2devは、$:($LOAD_PATH)に含まれる "." の汚染状況(あるいは "."が $:に含まれないこと)によってのみカレントディレクトリの扱いを変えるべきで、カレントディレクトリが特別に SecurityErrorになる、現在の ruby-1.9.2devには同意できない。

セールレベル1ではまだスクリプトを信用しているのだから、少なくとも ruby-1.8.7と同等のコントロールをスクリプトに渡して欲しい。

requireが利用する File.expand_pathの仕様によりカレントディレクトリからの相対パスが汚染されるのだろうが、File.expand_pathは requireが $:($LOAD_PATH)に依拠していることを知らないのだから requireが何とかすべき。

* その後の変更で、ruby-1.9.1らしき挙動の requireを検出したときはセーフレベルを 1から 0に下げてプラグインを実行することになっている。セーフレベル0なら今回のことは関係ないから。セーフレベルを下げるという発想は全く頭になかった。なんか、こう、負けた気がするからだろう。ruby-1.9.0だとセキュアモード(セーフレベル4)で動かないという話もあったけどどうなったんだろう。


2009年02月03日 (火) Safariは本当に文字がきれいだ。Windowsで、メイリオで、だよ。これに慣れてしまったら普段の環境なんて、目が潰れるほどひどいもんだ。「ぼやけてる」「焦点が合わなくて目が悪くなりそうだ」なんて感じさせないさじ加減が絶妙。GDI++を Firefoxに適用して、終わらないチューニングに苦労しながら、思う。


2009年02月06日 (金) Apple Software Updateは賢い。まず起動のトリガーが目の敵にされやすいスタートアップでなくタスクスケジューラ。更新がなかったときにはウィンドウを表示しない。更新が終わって更新がひとつも残っていなかったら、その旨のメッセージを表示しメッセージと共に自ら終了する。よく考えられている。


2009年02月09日 (月) すでに世の中、一般人も RSSです……よ?

[tDiary] テーマ自作 > badboy2007.css

screenshot (theme: badboy2007)

自分好みの見た目に拘るようになるにつれ、既存のテーマから得られる部分が減り、打ち消す手間が目立ってきた。そろそろ一から積み上げる方が楽だと感じたので。

公開されるテーマは汎用性を求められるぶん、個人的には冗長だったり、かゆいところに手が届かなくて CSSを追加したりする必要があったりするが、公開を前提としない自作なら、十分かつ必要最小限なものになる。(この現状を十分とは口が裂けても言えないけれど)

以下、備忘録としてスタイルを決めた際のポイントを。(すごく雑多)

  • タイヤの下には地面。
  • 「ツッコミを入れる」リンクの目的は移動ではなくアクションなのでボタンっぽく。
  • 「ツッコミを入れる」前後の [角かっこ]は skel/diary.rhtmlから削除。(ナビゲーションリンクの &laquo;, &raquo;も削除しています。なんでラベルに含めないんだろ。今なら CSSの contentも広く使えるのに、文字のハードコーディングは不便)
  • IE8RC1のデフォルトスタイルシートは<pre>の文字を小さくするので抵抗した。
  • 引用文は自分の書いた文章ではないので異物感。
  • 引用の中のPREはそれとわからないように。(実験的)
  • 色の決定には色名に対する好みが多分に入っている。(好き > navy, crimson)

ヘッダとフッタに関してもポイントを。(未来の自分が思い出せるように)

  • 日記著者向けのリンク(追記など)は、目立たないように、閲覧者向けのナビゲーションリンクと混ぜないように。(ページ最下部でも良い)
  • 目次はスクロールの必要なく、一画面に収まるように。(マージンとヘッダの内容と表示日数を削った)
  • ページトップに前後方向のナビゲーションはいらない。(目次の下とページ最下部に置いてみました)
  • フラットなカレンダーを先頭に置くと Tabキーによるフォーカス移動が大変。(カレンダーはページ最下部にとりあえず放り込みました)

古い日記はレイアウトが崩れてるかも。過去の日記の凍結(ヘッダ、フッタ、プラグインの出力を日記執筆時点のものに固定)という名の HTML書き出し機能が欲しい。

実は squeeze.rbを少し変更してヘッダ、フッタを含む HTMLを書き出し、mod_rewriteを使ってその HTMLファイルが存在するときはそちらを参照するように .htaccessで設定したりしていた。

RewriteEngine on
RewriteBase /ds14050/diary

# Rewrite rule1
#  shows static html, if exists.
RewriteCond /home/vvvvvv/www/cgi_file/ds14050/diary/snap/$1.html -f
RewriteCond %{REQUEST_METHOD} =GET [OR]
RewriteCond %{REQUEST_METHOD} =HEAD
RewriteCond %{HTTP:Cache-Control} !=no-cache [nocase]
RewriteRule ^([0-9]{8})\.html$ /cgi_file/ds14050/diary/snap/$1.html [L]

でも静的 HTMLをブラウザが直接参照するので tDiaryが起動せず、リファラの記録が行われなくなるし、多分ツッコミ(&トラックバック)が入るだけで HTMLが新しく生成されてしまう。翌日の日記へのナビゲーションリンクも基本的に出ない。ツッコミの読み込みとリファラの記録を静的 HTMLに埋め込んだ JavaScriptで行うことで、内容を最新に保ちつつ HTMLの生成を抑制できるが、実際にやってみるほどのメリットを見いだせず。スクリプトを実行しないブラウザ対応もパッと思いつかない(使える道具って<script>と<noscript>だけなのだろうか。コメント部を別 HTMLファイルとして保存して SSIで埋め込むとか……。うーむ)。


2009年02月10日 (火) Kindle2、2月24日発売。薄くて軽くて(といっても携帯電話3個分、約300g)電池の持ちが良くてワイヤレスネットワーク機能と USBコネクタを搭載していて、読み上げ機能があり、内蔵辞書や Wikipedia連動機能があり、コンテンツはアマゾンで買えちゃう。日本ではこういうの成功しなかったよね。新聞とマンガとライトノベルと文庫本を置き換えたいんだけどなー。コンテンツを持ってる出版社が動きなさいよ。部屋が埋まってしまっていて購入ペースが落ちてるってーの。


2009年02月12日 (木) ruby-1.8.7も最近 p0から p72にしました。それ以上のはコンパイルできませんでした。おとなしくリリースを待ちます。

[tDiary] tDiaryを 2.3.0.20080302から 2.3.1.20090129へアップデート。

手動で migrate.rbを実行して UTF-8化してあったのに、再度 90migrate.rbが走ってしまって、データが壊れた。慌てず ZIPファイルを解凍して元通り。

grepと同じ程度に簡単に、データファイルや tdiary.confのバージョンナンバーをすべて書き換える方法(sed?)が思いつかなかったので、tdiary/lang/ja.rbの migrate_to_utf8を無効化して済ませた。

def migrate_to_utf8( str )
	return str
	to_native( str, 'EUC-JP' )
end

素通しとはいえ migrationは実行されるので、数十から百ちかい数のファイルを開いて書き込んで閉じてといった負荷をレンタルサーバーにかけた。ローカルでは一分以上かかった。

 2.3.1になってカテゴリが大文字小文字の区別なくソートされる*

のが嬉しい。気になっていて、よっぽど自分でやってやろうかと思っていたので。

 古い tdiary.confを引き継ぐと

@accesskey_enabledの設定が存在しない(=>nil => falseと判断される)ために、アクセスキーがなくなってしまって戸惑った。ここはデフォルトを過去と互換にして欲しかった(設定名を @disable_accesskeyにするとか)。いまさらだけど。

 category.rbが nilにアクセスして NoMethodErrorを出すと思ったら

NaviUserCGIが木偶だからだった。原因は category.rbにはなく、できの悪い CGIのモックを渡した navi_user.rbにある。

 エラーを出した category.rbのコード
class Info
	include ERB::Util

	def initialize(cgi, years, conf, args = {})
		@cgi = cgi
		@years = years
		@conf = conf
		@category = args[:category] || @cgi.params['category']
		@year = args[:year] || @cgi.params['year'][0] #=> NoMethodError: undefined method `[]' for nil:NilClass
 NaviUserCGIの定義
class NaviUserCGI
	attr_reader :params, :referer, :user_agent
	def initialize(datestr)
		@params = {'date' => [datestr]} # <<<注目!
		@referer = nil
		@user_agent = nil
	end

	def request_method
		'GET'
	end
end

オリジナルの CGI#paramsは単一のデフォルト値( [].freeze )を持った Hashなんだよね……。

navi_user.rbも recent_list.rbと同じように書き換えてやろうか。

* 一か所、大文字も小文字も存在しない配列のソートを普通のソートに戻しました。


2009年02月15日 (日) 本文中の URL自動リンクがセミコロンで切れていたので、/shjs/lang/sh_ruby.jsと /shjs/lang/sh_javascript.jsを修正した。そこで使っていた正規表現は『詳説 正規表現 第3版』で、大抵の場合うまくいくと紹介されていたものでした。(CGIパラメータを ; で区切るのはいまだに異端でしたか)

[Ruby][tDiary] ruby-1.9.1*で、不思議で困ったことが起こった。

この断片で理解してもらえるだろうか。

categorized.keys.each do |c|
	PStore.new(cache_file(c)).transaction do |db|
		categorized.fetch(c) #=> key not found (KeyError)
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

あるハッシュのキーについて繰り返しているのに、ハッシュにはそのキーが存在しないという、この不思議。

このとき、c は、

"\xE6\x9C\xAC\xE6\x97\xA5\xE3\x81\xAE\xE8\xB3\xBC\xE5\x85\xA5" ASCII-8BIT

ハッシュのキーリストとそのエンコーディングは、

"\xE6\x9C\xAC\xE6\x97\xA5\xE3\x81\xAE\xE8\xB3\xBC\xE5\x85\xA5" ASCII-8BIT
"本" UTF-8
"マンガ" UTF-8
"雑誌" UTF-8

存在しているだろうに……。

 追記@2009-02-20: 同じ目に遭っている人がいた。

さくらインターネット上で tDiary を ruby1.9.1-p0 で動かす - まちゅダイアリー(2009-02-19)(14:57現在、日別表示が不可能な状態。最新表示は可能)

* 正しくは ruby-1.9.2dev(2009-02-03)

最終更新: 2009-08-29T06:18+0900

[HTML][Ruby] 中途半端なメソッドは提供しないのもまた親切なのでは? > URI.escape

> URI.escape("http://exmaple.com/foo bar?a=b=c;d=e#hoge#fuga")
=> "http://exmaple.com/foo%20bar?a=b=c;d=e%23hoge%23fuga"

URLをパーツに分解せずに gsub一発でエスケープ(エンコード)するなんて不可能だと思うのです。仮にそうまでしても、上の例のように、「#」が CGIパラメータとして受け渡されるように、「%23」にエンコードするべきか、URLを構成する fragmentを示す記号として、「#」のまま残すべきか、判断できない(でしょう?)。

できないことをできるかのように見せかけるより、できない(のでメソッドを提供しない)という方が親切だと思う。

JavaScriptの提供する encodeURIComponent(「/」も「?」も「#」も「=」もエンコードするメソッド)相当のメソッドがあれば、それで十分だと思うんだけど。

 つぶやき

http://exmaple.com/foo bar/baz/

なんてのは不正な URLだから、どこにも存在しないのです。アドレスバーに表示するときに人間に読みやすいように、と上のようにデコードして表示することはあるかもしれないけれど、オリジナルの正しい URLは同時に保持しておくべきで、表示用の文字列からエンコードしようなんて思っちゃダメなのです。ブラウザのアドレスバーは表示と同時に編集も可能だから話は簡単ではないけど……これまでのところ、Firefoxは(自らの責任で)よきに計らってくれています。

RFC(古いのと新しいのと二種類?)も読んでいない放言なので、実は「できる」という可能性がなきにしもあらず。


[ruby-dev:39188] Re: URI.escape_component から、

 さておき、URI.escapeは独特の動きをするので、JavaScript/ECMAScript の
 escape とも encodeURI とも encodeURIComponent とも違います。

 そういえば、現在の仕様の意図をお聞きしたかったんだった
 [ruby-dev:38124]

 なお、面倒な話が出てきた時には、とりあえず akr さんが
 既に取り上げていないか調べるわけですが、やっぱり扱っているわけです。
 http://www.a-k-r.org/d/d2004_07.html
 https://www.codeblog.org/blog/akr/20070222.html

2009年02月18日 (水) 未読リストが『NEXT』だけになってしまった。このリストはもう伸びないんだよね……。

[] [単行本] マイクル・クライトン【恐怖の存在 (下) (ハヤカワ・ノヴェルズ)】 早川書房

地球温暖化問題に異議を唱える本、という認識を持っていた。読んでみたら確かにその通り。かといって化石燃料の消費を助長する内容でもない。環境問題が論じられるところに科学が存在しないことを憂えている。また、環境保護=善(無条件に実行すべきこと)でもなくて、デメリットやコストを考慮してメリットを上回ることを確かめなければいけない、とも(具体例は読んでください。フロンや DDTの使用禁止にも考慮すべきデメリットがあるそうです)。温暖化・環境問題を「常識」として知っている人は、バランスをとるために是非とも読むべき。

訳者あとがきに、関連する複数の書籍への言及がある。知ってる人は知っていることなんだろう。(待っていても、TVのニュースからでは絶対に聞けない意見だろうけど。あるいはこちらの方で、そういう、環境保護に異論を唱える人に対して、うさんくさい人(産業界のまわし者)フィルターをかけてしまって、耳を塞いでいた可能性もある)

読んでいて、少し前に読んだ[文庫] サイモン シン【宇宙創成〈上〉 (新潮文庫)】 新潮社を思い出した。こちらは宇宙論の歴史を題材に《科学的方法》の意義を啓蒙する本だった。奇しくも、クライトンの本にも引用と共にカール・セーガンの名前がでてくる。


2009年02月22日 (日) HPの TouchSmart PCのラインアップに 64ビット OSが戻ってきたら手に入れる。今度の入力デバイスはタッチスクリーンだ。

[MX610] MX610は電池を抜かれて休眠中。

トラックボールを買いましたから。もともとマウスの使用に熟達していなかったからか、不自由を感じる暇もなく移行完了。2005年12月1日に届いてから 3年と2か月、ほぼ毎日数時間ずつ使用してきたが、MX610よ、ネズミさんよ、さようなら。

12ボタン+ホイールを誇る MX610だったけど、4ボタンしかない TM-150でも、なければないで不自由はしていない。例えば

タブ切り替え(左右チルト)
キーボードで Ctrl(+Shift)+Tab。
閉じる(ホイールクリック)
キーボードで Ctrl+W。(「新しいタブで開く」はもともと右クリックで行っていたので関係ない)
MUA起動(メールボタン)
キーボードにもメールボタンがある。
マリア様がみてる ボイスクロック 時刻読み上げ(IMボタン)
クイック起動に登録して Win+[1-9]

MX610のボタンに割り当てていたキー操作をキーボードで行っているだけなのでした。

MX610を使っていたときは全ての操作をマウスで、かつポインタの移動は最小で、を目標にしていたが、4ボタントラックボールでは従来の、ほとんどの操作をキーボードで、の基本姿勢に戻っている。キーボードでは全てを行えないから、切り替えコストを下げるためにトラックボールは左手で操作している(面倒だからボタン割り当ては右手用のままで)。

本当は全てキーボードで操作したいのだけど、ポインティングデバイスへの持ち替えを余儀なくされる(それもわりと頻度の高い)操作がある。

  • ファイルの、プログラムへのドラッグ&ドロップ (Ctrl+Vでドロップできるといいんだけど)
  • ポインタの避難 (タスクバーから表示されるサムネイルや、通知領域のアイコンのツールチップを消したいとき)
  • Firefoxで、目の前に見えているリンクのクリック
  • Firefoxの、リンクツールバー アイテムのクリック

Firefoxの、フォーカス先を画面内の要素に限定する機能は document.commandDispatcherを操作するだけで実現できそうな雰囲気だけど(advanceFocus()と suppressFocusScroll)、userContent.jsは敷居が高い。advanceFocus()のロジックを書き換えてやろうかとも思ったが、Firefoxのビルドがこれまた更に難しい。デフォルトの動作でないのが信じられないぐらい、必要としている機能なんだけど。


2009年02月23日 (月)

[Ruby][tDiary] 続報・ruby-1.9.1で、不思議で困ったことが起こった

問題のコード(再掲)はこれ。あるハッシュのキーについて繰り返しているのに、ハッシュにそのキーが存在しない。(すべてのキーが見つからないわけではないが、見つからないキーはいつでも見つからない)

categorized.keys.each do |c|
	PStore.new(cache_file(c)).transaction do |db|
		categorized.fetch(c) #=> key not found (KeyError)
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

fetchをブロックの最初に持って行くと、そこではエラーにならない。

categorized.keys.each do |c|
		categorized.fetch(c) #=> O.K.
	PStore.new(cache_file(c)).transaction do |db|
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

cache_file(c)の呼び出しが原因。その中でも includeしてある ERB::Utilの u()メソッドが核心。

categorized.keys.each do |c|
		::ERB::Util.u(c)
		categorized.fetch(c) #=> key not found (KeyError)
	PStore.new(cache_file(c)).transaction do |db|
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

引数にした文字列のエンコーディングが変わってしまっている。

categorized.keys.each do |c|
		enc1 = c.encoding;
		::ERB::Util.u(c)
		enc2 = c.encoding
		categorized.fetch(c) { raise "#{enc1} #{enc2} #{::ERB.version}" } #=> UTF-8 ASCII-8BIT erb.rb [2.1.0 2009-01-11] (RuntimeError)
	PStore.new(cache_file(c)).transaction do |db|
		db['category'] = {} unless db.root?('category')
		db['category'].update(categorized[c])
	end
end

ERB::Util.url_encodeの定義を見ると、引数の文字列を dupした後にエンコーディングを変更しているにも関わらず、呼び出し元に影響を与えてしまっている。

    def url_encode(s)
      s.to_s.dup.force_encoding("ASCII-8BIT").gsub(/[^a-zA-Z0-9_\-.]/n) {
        sprintf("%%%02X", $&.unpack("C")[0])
      }
    end
    alias u url_encode

そんなわけだから呼び出し側(category.rb)で

u( c.dup )

なんてやっても効果はなく、

u( ""+c )

あるいは

u( "#{c}" )

とやって初めて、今回の現象を回避することができた。

これは、文字列の複製を遅らせた結果、期せずしておこった現象にみえる

バグのはずなんだけど、irbで再現しようと思ってもできないんだこれが。


 追記@2009-08-13: 見る人が見れば修正はあっという間でした。

http://redmine.ruby-lang.org/issues/show/1929

(ここに、見るべき場所を見つけることもできなかった人間がひとり)

* 正しくは ruby-1.9.2dev(2009-02-03)


2009年02月24日 (火) [tDiary] highlight.rbプラグインが document.titleを書き換えるとは知らなかった。title_tagメソッドとフォーマットを統一した。


2009年02月26日 (木)

[tDiary] なにかおかしい。サーバーのRuby? 俺の書いたスクリプト? 改行コード?

過去にこんなことを書いた。

過去の日記を「編集」するとその日の全てのセクションが rdfに上ってくるのね。tDiary-2.3系の目玉はセクション単位での編集機能だなあ。

セクション単位の編集機能を実装しおえて、makerss.rbの対応もやっとくか、とソースを読んでみたらきっちり内容比較をしていた。だから当然、変更されたセクションのみが RSSで上に上がってくる。一文字も変更せずに日記を送信した場合、RSSも更新されない。ローカルの tDiaryで確認した。でもサーバー( http://vvvvvv.sakura.ne.jp/ds14050/diary/ )ではそうなっていない。過去に書いたとおり、どんな場合でもその日のすべてのセクションが上がってくる。

そういえばこんなこともあった。

日記を更新すると、TDiary::Config#data_path/category/ 以下の、カテゴリごとに作られるキャッシュファイルがずいぶんたくさん更新される。全部ではないが半分近い 21のファイルが更新されていた。日記の内容はというと一つのカテゴリしか使っていない。

根が同じかどうかはわからないが、なにかがおかしい。


そういえば、makerss.rbの作成するキャッシュファイルもカテゴリインデックスと同じ PStore形式だった。におう、におうぞ。


必ずしも上がってくるというものでもないみたい。サーバーの makerss.rbも概ね期待通りの動作をしている。うにゅう。

あまりに古い日記を編集していて、makerss.cacheから記事が掃き出されているために変更の有無を確認できない、というのとも違うんだけど。……と思うんだけど。(もういいや)


とりあえず内容を比較する前に stripしてみた。これで様子見。(複数のエントリが同じ時刻に更新されたかのように記録されることがなくなければ O.K.)

if cache[id].section.body_to_html.strip != section.body_to_html.strip or
		cache[id].section.subtitle_to_html.strip != section.subtitle_to_html.strip then
	cache[id] = RDFSection::new( id, Time::now, section )
end

最終更新: 2009-12-10T00:55+0900

[tDiary] この日記では一日一エントリールールを採用していません。

ルールを守るために未来日記を書く人もいるようですが、これはあくまで普通の日記だし、書いた日付と内容は切り離せないので、一日に複数のエントリを書いたりもします。だから、セクション単位での編集機能を、もちろんブラウザで

 edit_section.diff

編集画面プレビュー画面プレビュー画面(競合あり)登録画面(競合あり)
edit_section_screenshot(edit).pngedit_section_screenshot(preview).pngedit_section_screenshot(preview,conflict).pngedit_section_screenshot(append,conflict).png

変更内容はこのような感じ。

 section=n (n=1,2,...)パラメータ追加。

例えば、2009年2月26日の第1セクションの編集フォームへのリンクはこうなる。

update.rb?edit=1;year=2009;month=2;day=26;section=1

 編集対象セクションの変更を検知。

現在編集中のセクションが他の人によって書き換えられていたり、セクションの挿入や削除によってセクションナンバーが変わっていたときは、エラーメッセージを表示して(プレビュー画面でも確認可能)、変更をコミットしない。(「戻る」の後でも直前の編集内容が残っているかどうかは使用しているブラウザ次第)

 著者情報を保存。

従来の一日単位での編集では失われていた*著者情報が、セクション単位の編集では保存される。(編集対象のセクションは一番最後の変更者名になる)

ついでに、ある日の編集フォームを利用して、別の日に追記したとき――編集画面で日付を書きかえた後、この日付の日記を編集ボタンを押さずに、登録ボタンを押すことで可能――、記録されていなかった*著者名も記録する。

 Big5わかりません。

というわけで、skel/update.rhtml.zhと skel/preview.rhtml.zhは手つかずなので、従来の編集画面と機能になる。

skel/update.rhtml.enと skel/preview.rhtml.enは書きかえたけど動作未確認。

 wikiスタイルでしか試していません。

とはいえ、スタイル関連で利用するメソッドは each_section、append、replaceだけなので動くはず(期待)。

ただ、Diary#to_srcが Section#to_srcを単純に連結したものである、という仮定をおいてしまっているのだが、新旧wiki_style、rd_style、emptdiary_style、hatena_style、markdown_styleは大丈夫なものの、etdiary_styleは少しだけ違っているのが若干気になる。(といっても末尾の改行を一つにまとめてるだけなんだけど)

 [このセクションだけを編集]ボタンは、[この日付の日記を編集]ボタンと同じもの。

type="submit" name="edit"

上記が共通部分。(ボタンのラベルも送信されるけど、使われないので違ってて構わない)


 セクションの著者情報ってどこに保存されてるの?

新旧Wikiスタイルの場合、*.td2にはないよね。

tdiary_styleの場合、書き出される(TdiarySection#to_srcに含まれる)けど、読み込んだらカテゴリの一つになってしまいそう。

etdiary_styleも書き出すけど、読み込みは考えてなさそう。EtdiarySection#initializeに明示的に authorを渡しても使われない。

不毛だ。


プラグインの表示したフォームを送信すると、次の画面が普通の一日分の編集画面になる。<input type="hidden" name="date" value="yyyymmdd"> というようなフォームを埋め込む責任が個々のプラグインに委ねられているのでどうしようもない。

TODO: 元の画面に戻ることを保証することと、プレビュー画面に form_procを表示すること。

プレビュー画面への form_proc表示はもうやってるし、form_procを利用したファイルのアップロードを別タブの編集画面でやれば、変更内容が失われる心配もない。知ってるから困らないけど、わかりにくいのは確か。


 plugin/edit_section_link.rb

一日表示のとき、セクションごとに編集リンクを付ける。

add_subtitle_proc {|date, section, subtitle|
	subtitle += %Q(<span class="adminmenu edit_section"><a href="#{h @conf.update}?edit=1;year=#{@date.year};month=#{@date.month};day=#{@date.day};section=#{section}" rel="nofollow">[edit]</a></span>);
} if @mode == 'day';

サブタイトル(<h3>の中)に関係のないテキストを加えるより、サブタイトルの直前に挿入されるこっちの方がいいかも。

add_section_enter_proc {|date, section|
	%Q(<span class="adminmenu edit_section"><a href="#{h @conf.update}?edit=1;year=#{@date.year};month=#{@date.month};day=#{@date.day};section=#{section}" title="edit (author only)" rel="nofollow">✍</a></span>);
} if @mode == 'day';

*,(2) 未確認