2008年 01月 01日

今日

23:30ぐらいから朝7時ぐらいまで寝てた。ずっと廻り出すセカイ (修正版とそうじゃないのどっちも) をかけっぱで寝てた。未修正版のほうがシガーロスっぽい。

Ruby の Atom/AtomPub ライブラリ

atomutil がいいっぽいですね。http://rubyforge.org/projects/atomutil/ とかいうか他に選択肢ない感 (rubyforge で atom を検索するといっぱいでてくるけど、殆どハズれ (リリースいっこもない))

つかってみたら、feed.links に feed 直下の要素ではない link 要素も含まれてしまう。

--- atomutil.rb.orig	2008-01-01 15:07:56.000000000 +0900
+++ atomutil.rb	2008-01-01 15:05:54.000000000 +0900
@@ -604,10 +604,10 @@
     def child_xpath(ns, element_name, attributes=nil)
       ns_uri = ns.is_a?(Namespace) ? ns.uri : ns
       unless !attributes.nil? && attributes.is_a?(Hash)
-        "descendant-or-self::*[local-name()='#{element_name}' and namespace-uri()='#{ns_uri}']"
+        "child::*[local-name()='#{element_name}' and namespace-uri()='#{ns_uri}']"
       else
         attr_str = attributes.collect{|key, val| "@#{key.to_s}='#{val}'"}.join(' and ')
-        "descendant-or-self::*[local-name()='#{element_name}' and namespace-uri()='#{ns_uri}' and #{attr_str}]"
+        "child::*[local-name()='#{element_name}' and namespace-uri()='#{ns_uri}' and #{attr_str}]"
       end
     end
   end

rubyforge の Tracker は使われてんのかなぁ……

ref. http://d.hatena.ne.jp/lyokato/20071211/1197353609

URI#path がつかわれてるけど、Atom ってクエリ文字列ふくんでる URI はダメなのかな……

client.get_resource("http://example.com/foo?bar") がたぶん失敗する (URI#path => "/foo")。rfc5023 には特に query についての記述はないっぽいけど、こういうリソースが妥当なのかどうか (実際あるのか) わからない。

atomutil で fotolife API をたたいてみる

fotolife API は Atom 0.3 なのでちょっとだけ工夫がいるのですが

require "rubygems"
require "atomutil"
require "yaml"
require "pathname"

file = Pathname.new("2150944907_5be2ee34ac.jpg")

entry = Atom::Entry.new({
	:title => file.basename.to_s,
	:updated => Time.now,
	:content => Atom::Content.new { |c|
		c.body = [file.read].pack('m')
		c.type = "image/jpeg"
		c.set_attr(:mode, "base64")
	},
})
puts entry.to_s

config = YAML.load(Pathname.new("~/.hatena.ne.jp.yaml").expand_path.read)
client = Atompub::Client.new({
	:auth => Atompub::Auth::Wsse.new(:username => config["user"], :password => config["pass"])
})

post_uri = "http://f.hatena.ne.jp/atom/post"
p post_uri
p client.create_entry(post_uri, entry, file.basename.to_s)

とやるとできるみたいです。Atom::Entry とかがブロックをとれるので綺麗にかけていいですね! (mode="base64" は Atom 1.0 だとなくて、バイナリをそのまま Content-Type 指定して送信するみたい (まだちゃんと読んでないけど……)。base64 でいけると XHR でも画像が POST できるからいいんだけどなぁ)

ちなみに拡張子から mime-type への変換は WEBrick 使うと簡単です (mechanize でもこうやってる)

require "webrick/httputils"
mime_type = WEBrick::HTTPUtils.mime_type("foo.jpg", WEBrick::HTTPUtils::DefaultMimeTypes)
p mime_type #=> "image/jpeg"

flickr の画像そのものの URL から、もとの HTML へ戻るブックマークレット

javascript:(function c(s,i,a){if(a){window.jsonFlickrApi=c;s.type="text/javascript";s.src="http://api.flickr.com/services/rest/?method=flickr.photos.getInfo&format=json&api_key=13b98c6e595d688ce25febb790f85bc5&photo_id="+i;document.body.appendChild(s);}else{location=(s.photo.urls.url[0]._content)}})(document.createElement("script"),RegExp("http://farm\\d+.static.flickr.com/\\d+/([^_]+)_").exec(location)[1],document,1);

http://farm3.static.flickr.com/2365/2153801040_558425c251_m.jpg みたいなとこから、もどるときユーザ名がわからないからめんどくさい。

やってることは flickr.photos.getInfo を JSONP で叩いているだけです。画像の URL も HTML として扱えるブラウザならうごきます (Opera はだめ。IE はしらない)

Opera でも動くようにしました。id:os0x さんありがとう!

もっと短かくしてみた

javascript:(function c(d,i){if(i)d.body.appendChild(s=d.createElement("script"),s.type="text/javascript",s.src="http://api.flickr.com/services/rest/?method=flickr.photos.getInfo&format=json&api_key=13b98c6e595d688ce25febb790f85bc5&photo_id="+i,jsonFlickrApi=c);else{location=d.photo.urls.url[0]._content}})(document,/\/\d+\/([^_]+)/.exec(location.pathname)[1]);

flickr 自体にリダイレクタがあるみたいです。→ http://monaural.net/post/2008/12/flickr-url/

2008年 01月 02日

RSpec

atomutil のテスト書くときに (一行たしただけだけど)、はじめてさわったけど、思ったよりよさそうだ (食わず嫌いだった)

とりあえず assert_equal って補完使っても入力するのめんどくさいんだよね……

gerry++

おなかいたいわけじゃないけどなぜか gerry...

アカウント情報を管理するコマンド pit

というのを適当にでっちあげてみました (まだ gem source に反映されてないかも)。こまごまとした自動化スクリプトで、毎回 ~/domain.yaml とかにパスワード書いたりして分離するのがめんどうくさいので、そのへんをうまいことやってくれる gem です。

require "rubygems"
require "pit"

config = Pit.get("vox.com", :require => {
	"username" => "your email in Vox",
	"password" => "your password in Vox",
	"nickname" => "your subdomain in Vox"
})

みたいに書いておくと、設定されてない場合は $EDITOR で設定ファイルを開いて保存し、設定情報が config に入ります。

コマンドラインからもセットすることができて

$ pit set vox.com

とかやると、設定名が vox.com である設定を $EDITOR でひらきます。

でもって、設定のセット (プロファイル) をいくつかつくることができて、デフォルトだと default というプロファイルに保存されます。

$ pit switch devel

とかでプロファイルの切り替えができます。(プロファイル名に何も指定しないと default にもどります)


Ruby 以外でも一応つかえるように

pit get foobar

を実行すると $stdout に YAML をはきます (ただし tty のときはパスワードふくむときこわいので出力しません pit get foo | lv とかやるとみれる)


保存された設定は ~/.pit に特に暗号化されずに保存されます。

twitter4r

require "time"
require "rubygems"
gem "twitter4r"
require "twitter"
require "pit"

Twitter::Client.new(Pit.get("twitter.com", :require => {
	"login"    => "login name",
	"password" => "password"
})).status(:post, "Test posting from twitter4r with pit.")
2008年 01月 03日

Gyazo みたいにスクリーンショットを即 fotolife にアップロードするやつ

http://subtech.g.hatena.ne.jp/antipop/20071121/1195652375 を Ruby + Pit + atomutil とかで書いてみました。

最初は Perl のままアカウント情報のところだけ pit つかうようにしようと思ったのだけど、Pit もづーるがほしくなったりして、つくるなら Perl かかないととかいろいろ考えてたら Ruby で書いてしまっていた。

Shibuya.jpg

おつかれさまでした巫女さんが可愛いくて本当によかったですね。


50 mm f/2.2 0.003 sec (1/400) ISO200


50 mm f/2.8 0.003 sec (1/400) ISO200


50 mm f/3.2 0.001 sec (1/1600) ISO200


50 mm f/2.8 0.006 sec (1/160) ISO200


50 mm f/7.1 0.02 sec (1/50) ISO320


女の子みたいな現像 (謎) をしなかったやつ

今日の写美は作者の人が作品の説明をしていたのがおもしろかった (何がおもしろいのかわからない写真だったから、すこし世界観がひろがった気分)。

self portrait

Me

キモ☆ヲタ

2008年 01月 04日

Rakefile で shipit ぽいの

require "shipit"

Rake::ShipitTask.new do |s|
	s.Ask
	s.Step.new {
		puts "prepare phase"
	}.and {
		puts "run phase"
	}
	s.Twitter "Notice to twitter"
end

Rake::ShipitTask.new do |s|
	s.Ask
	s.Task :test
	s.ChangeVersion
	s.Commit
	s.Task :clean, :package
	s.RubyForge
	s.Step.new {

	}.and {
	}
	s.Twitter
end

みたいに書けるやつは書いてみた ( http://coderepos.org/share/browser/lang/ruby/misc/shipit.rb )。gem にするか悩む

Rakefile つかう場合、基本的にはタスクをつくって、依存関係まとめて、だけでも問題ないんだけど、それだと途中で例外が発生したときに哀しいことになりやすいので、準備のフェーズと実行のフェーズ (外部への副作用がある処理) を分離するようにしてみた (もちろん完全に例外が発生しないようにはできない)。例えば twitter や rubyforge のアカウント設定が正しいか、とかを準備の段階でチェックしておけば、バージョン変更してコミットするまえにわかるので、別の環境で「アカウント設定しわすれてたー」「あーこっちもー」みたいなのはなくなる。


s. かくのがめんどいけど (instance_eval つかっても先頭が大文字なので定数あつかいになる)、 Rakefile は普通コピペでつくるので (cutagem とか new なんとかとか)、多少冗長でもいいし、リリースの順序なんて一回かいたらそんなに更新しないので、ちょっとめんどうくさい、ぐらいならいいかなぁ。

もっと簡単に

namespace :shipit do
	task :twitter do
	end

	task :twitter_prepare do
	end
end

みたいにして、命名規則で依存関係を自動でつくる、みたいなののほうがいいかなぁ……

あーだめだ。これだと引数をわたしにくい……

コピペビリティ重要 (処理がまとまっている)

2008年 01月 05日

svn2cl memo

svn2cl.sh --break-before-msg=2 --group-by-day  --include-rev --separate-daylogs 

が、コミットメッセージに入れているファイル名とかがうざいので

Index: svn2cl.xsl
===================================================================
--- svn2cl.xsl	(リビジョン 979)
+++ svn2cl.xsl	(作業コピー)
@@ -200,9 +200,18 @@
      </xsl:call-template>
     </xsl:when>
    </xsl:choose>
-   <xsl:call-template name="trim-newln">
-    <xsl:with-param name="txt" select="msg" />
-   </xsl:call-template>
+   <xsl:choose>
+    <xsl:when test="contains(msg, ':')">
+     <xsl:call-template name="trim-newln">
+      <xsl:with-param name="txt" select="substring-after(msg, ':')" />
+     </xsl:call-template>
+    </xsl:when>
+    <xsl:otherwise>
+     <xsl:call-template name="trim-newln">
+      <xsl:with-param name="txt" select="msg" />
+     </xsl:call-template>
+    </xsl:otherwise>
+   </xsl:choose>
   </xsl:variable>
   <!-- add newline here if separate-daylogs is in effect -->
   <xsl:if test="$groupbyday='yes' and $separate-daylogs='yes'"><xsl:text>&newl;</xsl:text></xsl:if>

結局 svn2cl.{sh,xsl} は、dotfiles と一緒にレポジトリにいれて管理するようにしました。

Ruby で ShipIt のようなことをやる gem shipit

昨日のアイデアのまま gem にしてみました。(自動化したくなったのでとりあえず gem として使えるようにしたかった)

名前に悩んで (rake-shipit) とか、むしろオリジナルの ShipIt から離れているから名前違うほうがいいのかとか (やってることはおなじはずだけど) 考えたのだけど、名前変えるのがいろいろ面倒になった。

.shipit とか使わずに Rake のタスクにしたのは、普通 Rake でリリースタスクを書いて rake release とかでリリースしていると思うので、そのへんを変えたくなかったのと、DSL みたいなのですむならそれにこしたことないなぁと思ったからです。

今のところかなりオレオレ専用な部分が多いので (cutagem つかえばいいとおもうよ!)、使いながらなおしたい。

Rake::ShipitTask.new do |s|
	s.Step.new {
		system("svn", "up")
	}.and {}
	s.Ask
	s.Task :rubyforge
	s.Step.new {
		raise "svn2cl.sh is not found" unless system("svn2cl.sh", "--version")
	}.and {
		system("svn2cl.sh --break-before-msg=2 --group-by-day  --include-rev --separate-daylogs")
	}
	s.ChangeVersion __FILE__, "VERS"
	s.Commit
	s.Task :clean, :package
	s.RubyForge
	s.Tag
	s.Twitter
end

ちゃっちゃと gem にするだけしとこう、とか思って作業をはじめたのだけど、結局いろいろデバッグしたりする必要があった……

gem spec に指定する version をうまく更新できなくて、実はまったくうまくいってないみたいだ (たまたま最初の二回うまくいっただけ……)
ChangeVersion と Rakefile がかなり相性悪い…… (内部でやってるから)

さらに GemPackageTask が spec をたんにわたすわけじゃなくて version を (コピーとして) わたすからどうにもできない……
ChangeVersion が走ったら rakefile よみなおす、みたいなことしないとだめだ……

Rake タスクを実行するとき rake コマンドを叩きなおすようにした (いままでは invoke で内部実行してた)。
ひどすぎるバグだったのでリリースした (リリースするのたのしくなるけど、一日何回もリリースするのってアレですよね……)

2008年 01月 06日

昔の日記

なんか技術系のほうの昔の日記のほうが読めないなぁw なんでこんなひどいこと書いてるんだろうって感じで目を背けたくなる……

2008年 01月 07日

カード

佐藤広央の2008年カード
樹海とか不吉すぎる

shipit.rb

よびわけにこまったので shipit.rb とよぼう……

  • svk その他への対応
    • Commit/Tag とかの実際の処理を分離する
    • Rake::ShipitTask::VC::{SVN,SVK,Git} とかかなぁ
  • ステップ間で共有される state
    • instance_variable_set でハッシュセットすればいいかなぁ

をやんないとだけど、ここにこんなふうに書いてる時点でやる気ないよなぁ (今ちょっと svk をつかっていないので、svk 使うようになったらすぐに実装する感)

というかさっきまで全くオリジナルの ShipIt のコードを読んでなかった (Shipit::Step::Twitter だけ先に読んで処理を想像してた) ことに気付いてあわてて読んだ (全部じゃないけど)……アイデアだけでふくらませて考えてた。やばい…… CPAN はオンラインで簡単にソースよめていいなぁ。rubyforge も直接見れるリンクがほしい。

ちなみに shipit.rb で initialize と prepare にわけたのは、initialize っていう名前が Ruby 的に特別な名前なので、あんまり準備をするっていうイメージがないからです。instance_variable_set するなら initialize とわけたのは正解かなぁ (new すると initialize が走ってしまうので instance_variable_set するタイミングがない)

http://coderepos.org/share/changeset/4139

state には対応した。instance_variable_set はちょっと黒い気がしたので (みえないうちにセットされてしまうので)、いまのうちに initialize の仕様を変えることにした。

update hatena with mechanize

require "rubygems"
require "mechanize"
require "pit"

config = Pit.get("hatena.ne.jp", :require => {
	"username" => "username of hatena",
	"password" => "password of hatena",
	"diaryurl" => "http://d.hatena.ne.jp/[your id]/"
})

agent = WWW::Mechanize.new
page  = agent.get "https://www.hatena.ne.jp/login?backurl=http%3A%2F%2Fd.hatena.ne.jp%2F"

form             = page.forms.first
form["name"]     = config["username"]
form["password"] = config["password"]

page = agent.submit(form)

raise "Login failed.." unless page.forms.empty?

page = agent.get "http://h.hatena.ne.jp/"
rkm  = page.forms.last["rkm"]

page = agent.post config["diaryurl"], {
	"rkm"   => rkm,
	"title" => "test",
	"body"  => "test test from mechanize",
}
p page

inplace edit の API をたたく。g.hatena もおなじでできる (URL だけかえる)。はてなはサブアカでも更新できるので、スクリプトから更新するときは、専用のサブアカ作ってパスワード設定するほうがすこしだけ安全かも。

RKM ははてな全体で共通みたいなのでてきとうなところからとってきてる。ハイクだと URL にユーザ名が入らなくて手軽っぽい (config に id じゃなくてメールアドレスいれてもいけるとかいう意味で)。

shipit.rb の Step にしようとおもったけど微妙だったのでやめた……(ハイクへの通知だとサブアカでの発言になってしまう)

shipit.rb

rubyforge で、対象のプロジェクトの admin 権があるかどうかって自力で scrape しないとわかんないのかなぁ

続・ブックマークレットとかで、設定を先頭に書けるようにする

http://subtech.g.hatena.ne.jp/cho45/20070923/1190498279 というのを書いたけど、もういっこ考えてみた。

javascript:["foobar",0].sort(function(a){alert(a)});void(0);

最初に一文字入ってしまうけどそこそこいい感じ。二つまでは任意の引数がわたせる (三つ以上は二回以上よばれる)

javascript:["foo","bar"].sort(function(a,b){alert([a,b])});void(0);

二文字以上とかになると普通に s="foobar";(function(){})(s); とかやればいいけどグローバル変数つかうのはなんか気持ち悪いよなぁ。

script 挿入

javascript:["url",0].sort(function(a){document.body.appendChild(s=document.createElement("script"),s.type="text/javascript",s.charset="utf-8",s.src=a)});void(0);
javascript:["url",0].sort(function (a) {
	document.body.appendChild(
		s = document.createElement("script"),
		s.type="text/javascript",
		s.charset="utf-8",
		s.src=a
	)
});
void(0);
  • JS では必要な引数以上わたしても普通は問題ない。
  • 関数は引数が全て評価されてから実行される。

replace のほうがマシかなぁ。一文字あるだけで違う

Proto and Tree Style Tab

Fx3 on Mac のテーマになるらしいやつをちょっとつかってみる ( https://addons.mozilla.org/en-US/firefox/addon/6050 )

けど、縦置きのタブは全く考慮されていないので (そりゃそうだけど) スタイルあてなおした

@namespace url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);


.tabbrowser-tabs * {
width: 100% !important;
}


.tabs-stack {
width: 10em !important;
padding: 5px 0 0 0 !important;
border-style: solid !important;
border-width: 1px 0 0 0 !important;
border-color: #444 !important;
background:#797979 url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAH8AAAATCAIAAAA26UVlAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFlJREFUWMPt1MENwEAIA0GSrumXKjjZpIhIx2e3hLHkJzODbjUzks453V1VLyKX9WfGtqSIQH9nAPTX9G3bRn/zfNBfDn300Sf00Sf00Sf00Sf00Sf00ae/fcgdNtGP2RYEAAAAAElFTkSuQmCC") repeat-y top right !important;
}

.treestyletab-splitter {
background: #b3b2b3 !important;
border-style: solid;
border-width: 0 1px 0 0 !important;
border-color: #4e4e4e !important;
}

tab .tab-icon {
margin: 0 0 0 0 !important;
}

tab .tab-text-stack {
padding: 6px 4px 4px !important;
}

tab {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAaCAIAAADqseFyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAANxJREFUKM91kk2yhCAQg3NaWeNKrzEqiPzNUV93AwpjvY8QAlT1KtCz1jOhK3PdZFDTNClak1KsgpIXxJgi78QHe7oz8otvE3LKrNx5E1KFLonuqQPfnP8bi2fIayy6Gb9jEXvScEMMsSl0mYXgA6vgB4f3wTfCbRJwuYt1XUMQpz9HekF/Du507iTE2J1rgq2cwyHAMFa2tZKtZEowh2EZU0MnHPtBokVns10eDuzb/qjQrtg+28DnCZCOcF9i7UvpDp8o9erbdlcNtZXSUj23jkrAsqxLYR1tWf8AJr2Qe2DQNzkAAAAASUVORK5CYII=") repeat-x top left !important;
border: none !important;
padding: 0 0 0 0 !important;
height: 26px !important;
}

tab .tab-image-left {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAaCAIAAADnr5E1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAXtJREFUOMt9VO1ygyAQ9GnjpNOaMRM10TdoZvKjMQLKRyp90N4BCpemWU9Y4kLWkyM7/YNyDygD9uHOnuogNjlcmzzH8ABC1E1TH4/Hy+UyilEppZXWCnsdQmWJtKnregSI8W6MjxV+mKUGOOeCi6DT2sAFLfIQUb3b7UC9PogLuzkeqboAc0abdDFDzUR1UaBaShkMaDrnwUnh1p6maXXskQ6J73meMXcubRHJkPj+sVZJ9SKIbztbuWJyIUlLfFtrpwiZdIHTta0F3zFGSsbxUS0Q8Owp/qrh23MhMLjjbjeEXwRRQwYZZ8zd7EnPqPp7ZgMbBsZcLGRwBMaMfJ27uQ+34UUkO7YsIUfwdzdEf+t7bJD6BsdRXVWVr5r+2mP0fSQLJ5UGZYaZ5QKcXr+uEQuP6q5tXa3V588zpM3Xogp16Ws02YNd1/nqhJL7+Hh/227zTb5WvkdUt7B4255a9FPXzeFQ4RmCp8VypuyT86RNiJ+Eb4JzY/MLtC97An2cRbkAAAAASUVORK5CYII=") no-repeat top left !important;
width: 10px !important;
}

tab .tab-image-right {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAaCAIAAAABhlpxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAASVJREFUKBUFwdGRU0cUQMG+0lSZYp2PSQuihE+cyoqVtHpvDt3z/fsPMpjRee7X6/X8fN4/7rfbbf35c5shjcluH8fxeDwfjwfWt/++UYbGnOfxeH7ePz7e399///97XS7DIIPpcr3M5TJzGawCwJBSBCsBgyallLBmZkBgZmZmZmYGSwIABIKVAKCQJKwKAGpv7XaFJQCgbAKsyhAYUSXBSsKQVISE1c5QMNrtXdUOK2lGKClVCUsoKFOVIli7DQAVaScsxSSGLWpHYRUCGVVRBWu3jWmQtmqn3cYSSRC7qAQrQQykShLW29c3xIg5zuN6Xeo4Dqyfv35iBuRsn6/j+fm83x9Yb2//mgQzzt3r9Xm5Xpnb7ba+fPkHAPbelxk5zxN/Ab8bI0CpEO7fAAAAAElFTkSuQmCC") no-repeat top left !important;
width: 10px !important;
}

tab[selected="true"]  {
color: #000 !important;
border: none !important;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAaCAIAAADqseFyAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADhJREFUKM9jyMzKTAeCDAhGQQx+uAHD5k2bcaFRuVE5DLndu3bjQnjTWUYGKGkiJVEoBwgYKnEDAAQjv6hLimGWAAAAAElFTkSuQmCC") repeat-x top left !important;
height: 26px !important;
}

tab[selected="true"] .tab-image-left {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAaCAIAAADnr5E1AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAPpJREFUOMuV1N1uwiAUB3CfcAXcRXspaTLpOGS6FCP1NWYfo0m/aPHlZEuNaaru8A9w9Qs5J+GwOt5iisKfWh++93sAJTLx4bOd9l+2q+M9JtcaQG44j+P47VEmXZxO+qCFEGmann/OVVU1dbNckzbGgFJZltV1Y63t2u6V1nnOOS/L0tOHbqa/drskSdqmfXbrTPsaKGWv6V1/SskY67sepUFKyqjtLUpLr2mgHuyA1YTQcRhxGoAQgtXgdUTc6JCVQBRFzjnk3dLri7tguwzTvkusVkqt1+/YusPeYNj7Dpud5Vz6jpfrpn+/h9nMM0afz3xRhP4n/+cKjYKqgQhXyaIAAAAASUVORK5CYII=") no-repeat top left !important;
width: 10px !important;
}

tab[selected="true"] .tab-image-right {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAaCAIAAAABhlpxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEFJREFUKM9jSE/PwIMY/PAChs2bNuNBo9Kj0tST3r1rNx5EKKWmQ0EGEMCYUAwEDJWooLy8vLCwMCsrKyEhAagbALBg8EPs/C58AAAAAElFTkSuQmCC") no-repeat top left !important;
width: 10px !important;
}

色とか改訂されて使えなくなりそうだ

place: URI

memo

いまいち使えない感……

  • タグでの検索はどうやるんだろう (terms は title と url だけっぽい?)
  • 定数なのがいちいちめんどい (うえのソースから検索)
  • というか生の SQL かかせてほしい
  • 現在みている URL によって……みたいなことをしたい

XPCOM 叩いたほうがよさそうだ……

Organizer で place: をかきかえても反映されないので、変更したらブックマークをつくりなおす必要があった。

mozStrage たたくしかないのかなぁ。でも自力で open したら壊れそうだ。

2008年 01月 08日

新年早々、いろいろと気を引き締めなさいと言われているようなことが (直接的ではないけど)、あって、少し緊張する。

2008年 01月 07日

Gmail の web UI を常用してみる

Thunderbird のスレッド時のソート法がどうしても気になりだして拡張を入れたりしたのだけど、結局やりたいのは Gmail みたいな表示だったので、だったら Gmail そのまま使えばいいよなぁという話でした。(今までは IMAP 経由) それと、Thunderbird は Fx ほど userChrome.js を使って拡張する気になれないので、Greasemonkey で拡張できるならそのほうが楽かなぁとかいうのもあります。

公式の Gmail Notifier だとマルチアカウントに対応してないので Fx の拡張をいれてみた。Fx3 b2 にも対応してた。

2008年 01月 08日

Rake タスクの引数のほげほげ

http://d.hatena.ne.jp/rubikitch/20080107/rakeargs をみてて、使えるようになったノカーとか思いつつ、このままだとちょっと使えないなぁと思ったので、Rakefile で対応できる範囲でつかいやすくしてみた

def args(hash)
	name = hash.keys.first
	args = hash[name]
	task name, *args
end

desc "foo task"
args :foo => [:bar, :baz]
task :foo do |t,a|
	p t.arg_names
	p a.bar
	p a.baz
end

desc "bar task"
task :bar do |t|
	puts "this is bar."
end

# ARGV は Rakefile が実行される時には既に rake 自体への引数は全てとりのぞかれている
Rake.application.top_level_tasks.replace(ARGV.map {|a|
	name, vals = *a.split(/@/, 2)
	vals ? "#{name}[#{vals}]" : a
})

これで

$ rake 'foo[aaa,bbb]'
(in /Users/cho45/tmp)
[:bar, :baz]
"aaa"
"bbb"

$ rake foo@aaa,bbb
(in /Users/cho45/tmp)
[:bar, :baz]
"aaa"
"bbb"

になって、どっちでもいけるようになる。


あと引数の宣言の DSL がめちゃくちゃわかりにくいと思うのでオレオレメソッドを定義してみた (あの DSL で、後ろに書いてあるのが引数だと想像できる人はどれほどいるんだろう……)。先に args の宣言がくるのはちょっとキモいけど、task メソッドうわがきせずやるとこんなもんなのかなぁ。


でもそんなに引数めちゃくちゃとりたいケースってないのかもしれない……

いまさらだけど別に ARGV みなくても top_level_tasks.map! でいいのだった。(最初は ARGV をもっといじくるコードを書いてたなごり)

文字列の繰り返し

ref. http://d.hatena.ne.jp/higeorange/20080107/1199710820

String.prototype.repeat = function (n, sep) {
	if (n < 1) return "";
	return Array(n).join(this + (sep || "")) + this;
};

print("hoge".repeat(-1, '+')); //=> ""
print("hoge".repeat(0, '+'));  //=> ""
print("hoge".repeat(1, '+'));  //=> "hoge"
print("hoge".repeat(3, '+'));  //=> "hoge+hoge+hoge"
print("fuga".repeat(4, '-'));  //=> "fuga-fuga-fuga-fuga"
print("foo".repeat(4));        //=> "foofoofoofoo"

Perl の YAML と Ruby の YAML の相互運用

Ruby は標準添付の yaml で、Perl は YAML::Syck にします。でもって、Syck のオプションを

$YAML::Syck::ImplicitTyping = 1;
$YAML::Syck::SingleQuote    = 1;

にするとたぶん互換になるみたいです。ImplicitTyping は POD にも「こうすると互換になるよ」って書いてあるやつです。SingleQuote は 8 進数みたいな文字列 (/0[0-7]+/) をよみかきするときに必要になります。

use strict;
use warnings;
use Data::Dumper;
sub p { print Dumper shift }

use YAML::Syck;
p YAML::Syck::Load(YAML::Syck::Dump({foo=>"0100"}));
p YAML::Syck::Dump({foo=>"0100"});
$VAR1 = {
          'foo' => '0100'
        };
$VAR1 = '--- 
foo: 0100
';

$YAML::Syck::ImplicitTyping = 1;
$YAML::Syck::SingleQuote = 1;
p YAML::Syck::Load(YAML::Syck::Dump({foo=>"0100"}));
p YAML::Syck::Dump({foo=>"0100"});
$VAR1 = {
          'foo' => '0100'
        };
$VAR1 = '--- 
"foo": \'0100\'
';

$YAML::Syck::ImplicitTyping = 1;
$YAML::Syck::SingleQuote = 0;
p YAML::Syck::Load(YAML::Syck::Dump({foo=>"0100"}));
p YAML::Syck::Dump({foo=>"0100"});
$VAR1 = {
          'foo' => 64
        };
$VAR1 = '--- 
foo: 0100
';

use YAML;

p YAML::Load(YAML::Dump({foo=>"0100"}));
p YAML::Dump({foo=>"0100"});
$VAR1 = {
          'foo' => '0100'
        };
$VAR1 = '---
foo: 0100
';

use YAML::XS;

p YAML::XS::Load(YAML::XS::Dump({foo=>"0100"}));
p YAML::XS::Dump({foo=>"0100"});
$VAR1 = {
          'foo' => '0100'
        };
$VAR1 = '---
foo: 0100
';

Ruby の YAML.load の挙動は YAML::Syck の $YAML::Syck::ImplicitTyping = 1; のときの挙動と一緒です。すなわちクオートしない /0[0-7]+/ は8進数の数値になります。YAML.dump は数値っぽい文字列を自動でクオートします。

require "yaml"

p YAML.load(<<EOS) #=> {"foo"=>64}
---
foo: 0100
EOS

p YAML.load(<<EOS) #=> {"foo"=>"0100"}
---
foo: "0100"
EOS

puts YAML.dump({"foo" => "0100"})
# --- 
# foo: "0100"
#
puts YAML.dump({"foo" => "aaa"})
# --- 
# foo: aaaa

ポイントは結局のところ

  • Dump 時に8進数っぽい文字列がクオートされるか
  • Ruby の yaml は特にオプションとかがない (なので、クオートされないものはつかえない)

みたいですね。あと、Perl しか使わない場合でも、$YAML::Syck::ImplicitTyping = 1 で使うときは必ず $YAML::Syck::SingleQuote = 1; も指定しないとデータがこわれてしまうみたいです。

Perl については調べきれてないかもしれないです (Syck 以外でもクオートできるのかな……)。もしかするともっといい方法があったりするのかもしれない……

2008年 01月 10日

Changes の基準

外部から見える変更 (書くことないときはリファクタリングしてどうなったかだけ) かな

設定を管理する pit の Perl もづーる Config::Pit

http://subtech.g.hatena.ne.jp/cho45/20080102/1199257680 の Perl 版です。最低限うごくようになったところでコミットして #CodeRepos の方々にお世話になりながらリファクタリングをしました (ありがとうございます)。(Path::Class++) コマンドラインツールは Yappo さんが書いてくれました (Yappo++)。

テストとか一通り書いて 0.01 をリリースしました。が既にあれげなところの修正が入ったので 0.02 をリリースしました。

一通り本家 ShipIt の感じもつかめてよかった。MANIFEST の確認を怠っていたら .svn をふくんでリリースしてしまってめっさあせる……


プロトタイプだけ書いて放置していたら PHP 版が先に! はやい!

2008年 01月 11日

svn log と Trac につけたはてなスターをつかって ChangeLog を自動生成するアイデア

svn2cl がアレなのはノイズが多いからだよなぁと思って (でも ChangeLog と svn log をどっちも書くのはめんどう)

 ~/coderepos/lang/perl/Config-Pit/trunk
$ changelog-with-hatenastar.rb
ChangeLog of http://svn.coderepos.org/share/lang/perl/Config-Pit/trunk

2008-01-09  SATOH Hiroh <cho45@lowreal.net>

        * [interface] @4310:

            Implement pipe function for output stdout (but tty)
            Always notice profile switching for ppit ui.


        * [interface] @4309:
                 like ruby pit

        * [bug] @4282:

            Add local not to violate global env.

あんま☆つけてなくておもしろくないというか、タグの changeset は trunk の log に残らないので release のログは工夫しないとだせないことに気付いた…… あとマルチユーザを考慮してないのでまずい (4390 は SATOH さん(笑)のコミットではない)

この方法の利点は、はてなスターによってあとからつけられるので、「このチェンジセットをもうすこし詳しくして ChangeLog に書きたい」みたいなのを簡単にできるところと、他の人のチェンジセットにも情報増やせるところ。ただ、はてなスターの quote は quote なのでブックマークレットとかつかって書かないといけないのはめんどい。

ちゃんと使うには

  • svn log に書く内容からタグを抽出 (簡単)
  • はてスタ簡単につけるブックマークレット (UI がめんどい)
  • 出力の形式をまともに (めんどい)

とかやらないといけない。ChangeLog を手書きするのと、svn log から抽出しつつ、はてスタで補足するのとではどっちが楽かってなんか微妙だ。


ここまで書いてきづいたけれど、ChangeLog を先に書いて、svn di ChangeLog した内容を svn ci 時のデフォルトにすれば、すくなくとも ChangeLog と svn log をどっちも書くのはめんどう は解決できるからそのほうがいい気がした。あれー

tags もみるようにして、出力を改善した。

開発してるときはコミットログにタグいれるのよくわすれるからあとからどうにでもなるのはいいかもなぁ、とおもってちょっと使ってみる (あたらしい gem で)

自由なスタークオート

location.href = "javascript:"+encodeURIComponent(uneval(function () {
	var orig = Hatena.Star.AddButton.prototype.addStar;
	Hatena.Star.AddButton.prototype.addStar = function (e) {
		if (e.shiftKey) {
			var q = prompt("Star quote:");
			var t = new Ten.Element("div", {style:{display:"none"}}, q);
			document.body.appendChild(t);
			var r = window.getSelection().selectAllChildren(t);
			orig.call(this, e);
			document.body.removeChild(t);
		} else {
			orig.call(this, e);
		}
	};
}))+"()";

OpenStruct で String キーの Hash と Symbol キーの Hash のめんどいのをどうにかする

p OpenStruct.new(:foo => "bar").foo
p OpenStruct.new("foo" => "bar").foo

どっちでもいけて便利ですね @config = OpenStruct.new(config) とかやっとけば自然とどっちにも対応できますね

2008年 01月 12日

2008年 01月 11日

userscripts.org でコマンドラインからスクリプトの追加/アップデート

$ sudo gem install userscripts_org
$ userjs create foobar.user.js
$ userjs update foobar.user.js

とかできるやつです。

ついでに linkuserjs.rb を統合してあります

$ userjs install foobar.user.js
# Fx で foobar.user.js をひらくだけ

$ userjs install -l foobar.user.js
# Fx で foobar.user.js をひらき、インストールされたあとに
# インストール済みのファイルを指定したファイルへの symlink にする

なんか説明しにくいのですが、ようは symlink にすると svn ci がすぐできるようになります。Mac のコードしか書いてないので他の OS だとうごかない (チェックさえしてないのでつけよう)

一応 Windows (cygwin) と Linux (firefox にパスが通っていること前提) のコードをいれました。テストしてないのでうごくかわからないのですが

2008年 01月 12日

どうしても見出しの幅が他とあってないのが気になるのでなおした……パターンメーカーって使って作った画像をはじめて使った気がする。なんかいまいちなんだよね……
あと右側にあいてしまう部分をうめたいけどいいアイデアが思い浮ばない。

2008年 01月 13日


自分は、些細なきっかけで物事を嫌いになりやすいので (パチンと、スイッチが切りかわるみたいに)、好きでいたいものに接するときは、気をつけるようにしてる。一度切りかわると、元に戻りにくい。

なんか、日記特有の、緊張感みたいなものがない。あんまり馴染める空気じゃない。

CocProxy の Mongrel 版

WEBrick は素晴しいのですがいかんせん遅いので Mongrel 使って書いてみました。Proxy の実装は WEBrick からパクっています。

1.8.4 でしか動かしてないです。キャッシュ機能はつけるのが若干めんどいのでついてません。あとクッキー関係でちょっとおかしいけど、用途的にあんまり困らないかな。

2008年 01月 14日

そういえば小学生のころ、この花の蜜をなめてた。ものによるけど (土による?) 甘かった。

ああ、花の名前が思い出せなかったけどサルビアだ……記憶力がどんどん悪くなるなぁ。twitter の人とか follow しといて誰が誰だかわからなくなったのでいくらか remove した……

暗い写真ばっかりとってるわけではないのです。(でもこれもちょっと構図が暗めだ)

私とあなたが知っている「私」の表ってどっかで見たことがあるけどどこだろ。高校のとき図書室でか、あるいは健康科学論の講義かな。

ジョハリの窓 - Wikipedia あーこういうんだ

2008年 01月 15日

実際のところ、自分だったら、表現の場は狭めずに、人付き合いを狭めるだろうと思う。

置換プロキシつけたままサブテク日記開いたらこの日記のデザインになって混乱した。ほとんど見た目で判断しているんだなぁ。

interpretation

flickr で公開されている Creative Commons の写真に「タイトル」をつけて interpretation という題にまとめるというアイデア

BURGER NUDS - 神様ごっこ

ループリストにいれて聴いていたら、なんかよくわからないけど、今唐突にぐっときた……

眠れない……

腰を据えてできることってなんだろう。特に興味があるのは

  • 人工無脳 (not 知能)
    • 自動学習あたり
  • 画像処理 (現像/認識/検索)
    • どこからはじめればいいかわからない分野
  • プログラミング言語
    • パーサーかくにしても VM かくにしても大変だけど、既存の例が多い

だけれど、今これらにあんまり手をつけていない、ということは、興味があるだけで、あんまりやる気がないのかもしれない。言語つくりは何度か手をつけてるけどまじでほんとちょー大変だ。パーサー書くのは楽しんだけど、VM つくるところで途方にくれる……

無脳は全文検索エンジン (Hyper Estraier) をそのまま利用してスクリプト言語 (Ruby binding) でかく、みたいなのはやってみたけどいまいちだった。全文検索エンジンそのまま利用するのは、自分で検索のアルゴリズムを考えずにすむぶんすぐ形にできていいと思ったので、そのまま別のアイデアとくみあわせたらうまくいくかもなぁと思ったりした。自分で全文検索エンジン書いてみると発見がありそうだ。

2008年 01月 16日

ケータイ

2008年 01月 15日

gerry

昼ごろから胃がいたくて、一度寝たらなおったとおもったのだけれど、夕食食べたらすごいゲリった

2008年 01月 16日

RAW のメモ

5D の CR2 (13MB) のサムネイルサイズは 2496 x 1664 jpg (約半分サイズ)。とりだすと 1.3MB ぐらい。このサムネイル JPG はカメラ設定で RAW のみを選択しても必ず現像される (現像パラメータはピクチャスタイル?)。たぶん撮影後の拡大してみる機能のためにある? これは dcraw -e で高速にとりだせる (CR2 は TIFF なので TIFF よめれば簡単にとりだせそう)。

メタデータは現像パラメータより

Filename: IMG_6483.CR2
Timestamp: Wed Jan 16 14:07:04 2008
Camera: Canon EOS 5D
ISO speed: 400
Shutter: 1/664.0 sec
Aperture: f/4.0
Focal length: 50.0 mm
Embedded ICC profile: no
Number of raw images: 1
Thumb size:  2496 x 1664
Full size:   4476 x 2954
Image size:  4386 x 2920
Output size: 2920 x 4386
Raw colors: 3
Filter pattern: RGGBRGGBRGGBRGGB
Daylight multipliers: 2.224558 0.928662 1.164364
Camera multipliers: 1796.000000 1024.000000 1759.000000 1024.000000


メタデータよむために http://www.exiv2.org/ をためしてみる (MakerNote に対応していそうなので)。ただ ubuntu LTS のパッケは古いっぽいのでソースからインストール。というか最後のリリースが 10-Jan-2008 とかですばらしい。ruby-exiv2 という binding が rubyforge にあるみたいだけどコンパイルできなかった。

めんどいのでコマンドラインたたいてみると CR2 もちゃんとメタデータ見れる。すばらしい。サムネイル展開するには

$ exiv2 -e t extract IMG_6483.CR2  

とかすればいいみたいだ。と、おもったら、これでとれるサムネイルは dcraw でとれるサムネイルとは違う。21KB のもっと小さいサイズのサムネイルだった。

メタデータは

$ exiv2 print -p t IMG_6483.CR2

するとデータ型もふくめて全部 dump される。http://www.exiv2.org/sample.html

2008年 01月 17日

BURGER NUDS つけっぱのまま寝たらどうしようもない感じになった。彼らの、今でも続く、ハードボイルドさ、と同時にみえる弱さ、が素敵だ。
昨日撮った写真を現像していない。しよう。


前にも同じようなのを撮った。

教務課から休学期限手続きの書類がきた (復学・休学・退学の三枚セット。親切)。今回休学すると学生証が変わるらしい (すなわち学籍番号が変わる)。理由かくのが結構へこい。

2008年 01月 18日

GreaseMonkey の GM_xmlhttpRequest を順番に(略)

http://d.hatena.ne.jp/drgqst/20080110/1199976698

JSDeferred だとこんな感じかなぁ

	function parseJSON (d) {
		// unsafe
		return eval("("+d.responseText+")");
	}

	next(function () {
		return xhttp.get("http://twitter.com/statuses/public_timeline.json").next(parseJSON);
	}).
	next(function (d) {
		var id = d[0].user.screen_name;
		GM_log(id);
		return xhttp.get("http://twitter.com/users/show/" + id + ".json").next(parseJSON);
	}).
	next(function (d) {
		GM_log(uneval(d));
	}).
	error(function (e) {
		alert(e);
	});
2008年 01月 20日

いよいよお金がなさすぎてヤバいんだぜ

2008年 01月 19日

shipit.rb

使ってみてハマりそうなポイントにチェックをいれて他の人が使っても大丈夫なようにしてる。定数をハードコードしてるのは、Rakefile 側で代入しなおせばいいだけなので (影響が多いのもあって) 変えない。

2008年 01月 20日

ニコニコ

ひさしぶりに VOCALOID 系のを聴いてまわった。

けんたろさんに会ったけれど、全然違和感みたいなのがなかった。

Ruby の名前空間

orz... Fx3 + Firebug でクラッシュしてから edit ページひらいて送信したら消えてしまった……変なタイミングで入力の復帰が行なわれたようだ……できるかぎり復元してみる

JS かいたり Scheme かいたりしたあと Ruby をかこうとするとなんかハマる。メソッドの名前と変数の名前が分離しているからなんだけど、たまにきもちわるい感じがする (スイッチがきりかわるとそうでもないんだけど……)。

class Foo
end

def Foo
end

ができるということはいいのだけど (Hpricot とか Pathname がやってる)、おなじようなノリで

class Foo
    module Bar
    end
end

def Foo::bar
end

みたいなのはもちろんできない。やるとしたら

module Foo
	module Bar
	end


	def Bar
		:a
	end

	def self.Bar
		:b
	end
end

p Foo.Bar    #=> :b
p Foo::Bar() #=> :b

include Foo
p Bar        #=> Foo::Bar
p Bar()      #=> :a

みたいになるけど、(わざとやっているとはいえ) きもい><

あああ、もうほんと、僕は全然大人になれる気がしない。あるいは例えば、誰か何か、僕が必死になれるような人がいれば、そうならざるを得なくなり、いわゆる「大人」になれるのかもしれないけれど、僕はそういう人を見付けられる気がしない。正直に話をすれば、女の子よりもプログラミングのほうが素敵なのではないかとちらちら考えてしまうし、もし素敵な子がいたとしても、僕よりも素晴らしい人がいるのだからそれでいいだろうと考える。逃げまわることが大好きらしい。

酔っぱらっていたり、少し追いつめられていたりすると、頭の中の言葉、いうべきことではないことも、全て水面までうきあがり、それをキーボードにうちこむことができる。でも、一方で、そういう、特殊な状態に頼った自己表現を嫌い人もいる。自分もどっちかというと嫌いだ。言うべきことはしっかりと考え、言葉、単語ひとつひとつを熟考してから、書くべきだと思う。ただし、それではいつまでたっても、自分が納得できる文章というのが書けない以上、表現が成立しない。

これは全くプログラミングと一緒だ。汎用性をもたせよう、完璧にしようと考えるあまり、実装に手がつかず、途方にくれる、ということがよくある。それは本当に間違いだ。実装はとりあえずすればよい。動かなければ意味がない。表現はとりあえずしてみなければならない。あとからそれをとりけすのは、少しやっかいではあるが、あとからとりけすのが非常にやっかいなものは、まだやるべきことではない。「ごめんなさいまちがえました」といい、訂正できる程度のことを、完全に動くまでテストし、リリースすることが重要だと考える。

僕は本当に恵まれた環境にあるということを、泣きそうになるぐらいに実感する必要があるが、泣きそうになるほどに実感はしていない。なんてすばらしいんだろうと考えることはよくある。

普通、ソフトウェア、ライブラリのリリースはめちゃくちゃ孤独だ。「これでいいのか」「すでに同じようなモジュールがないか」「名前空間を必要以上に汚染していないか」ということを、殆ど独りで考え、結論をだし、自分のバランス感覚・距離感を信じてリリースする必要がある。そういう意味で、例えば、IRC などで「これでいいのか」ということを相談できたり、意見を聴けたりするのは、本当に素晴しい。ただ、いつもおもうのは、そういうのに頼りすぎてはいけないということだ。バランス感覚は、常にバランスを保ち続けることで維持できるはずであるし、距離感は、いつも距離を図っていないとわからない。

MBTI

さっき http://www5.big.or.jp/~seraph/zero/mbti.cgi をやったら

だった。しばらく INFP だったのが INFJ になった。(でも前にどこでやったのか覚えていない)

2008年 01月 21日

はてキ

[[スイーツ(笑)]] の括弧は全角なのに [[ライフハック(笑)]] は半角なのがなんかうける。

2008年 01月 20日

JSDeferred 重い処理を自動で分割する。

JSDeferred の loop 関数は軽かろうが重かろうか一回ずつ setTimeout はさむんで効率わるいので、for ループと loop 関数の間ぐらいの関数をてきとうに書いてみた。

	function aloop (n, f) {
		var i   = 0;
		var end = new Object;
		var ret = null;
		return Deferred.next(function () {
			var t = (new Date()).getTime();
			try {
				do {
					ret = f(i)
					i++;
					if (i > n) throw end;
				} while ((new Date()).getTime() - t < 100)
				log("Devided: " + ((new Date()).getTime() - t) + "msec.");
				return Deferred.call(arguments.callee);
			} catch (e) {
				if (e == end) {
					log("End");
					return ret;
				} else {
					throw e;
				}
			}
		});
	}

	aloop(100, function (n, o) {
		var dummy = 0;
		log(n);
		for (var i = 0; i < n * n * n; i++) {
			dummy++;
		}
	});

関数一回の処理に 100msec 以上かかってしまったら、一度ブラウザに処理をかえす。

この例だとこんなふうになります

Firebug has been disabled for www.google.com

Enable Firebug
Enable Firebug for this web site
http://lowreal.net/Test: 0
http://lowreal.net/Test: 1
http://lowreal.net/Test: 2
http://lowreal.net/Test: 3
http://lowreal.net/Test: 4
http://lowreal.net/Test: 5
http://lowreal.net/Test: 6
http://lowreal.net/Test: 7
http://lowreal.net/Test: 8
http://lowreal.net/Test: 9
http://lowreal.net/Test: 10
http://lowreal.net/Test: 11
http://lowreal.net/Test: 12
http://lowreal.net/Test: 13
http://lowreal.net/Test: 14
http://lowreal.net/Test: 15
http://lowreal.net/Test: 16
http://lowreal.net/Test: 17
http://lowreal.net/Test: 18
http://lowreal.net/Test: 19
http://lowreal.net/Test: 20
http://lowreal.net/Test: 21
http://lowreal.net/Test: 22
http://lowreal.net/Test: 23
http://lowreal.net/Test: 24
http://lowreal.net/Test: 25
http://lowreal.net/Test: 26
http://lowreal.net/Test: 27
http://lowreal.net/Test: 28
http://lowreal.net/Test: 29
http://lowreal.net/Test: 30
http://lowreal.net/Test: 31
http://lowreal.net/Test: 32
http://lowreal.net/Test: 33
http://lowreal.net/Test: 34
http://lowreal.net/Test: 35
http://lowreal.net/Test: 36
http://lowreal.net/Test: 37
http://lowreal.net/Test: 38
http://lowreal.net/Test: 39
http://lowreal.net/Test: Devided: 109msec.
http://lowreal.net/Test: 40
http://lowreal.net/Test: 41
http://lowreal.net/Test: 42
http://lowreal.net/Test: 43
http://lowreal.net/Test: 44
http://lowreal.net/Test: 45
http://lowreal.net/Test: 46
http://lowreal.net/Test: 47
http://lowreal.net/Test: Devided: 116msec.
http://lowreal.net/Test: 48
http://lowreal.net/Test: 49
http://lowreal.net/Test: 50
http://lowreal.net/Test: 51
http://lowreal.net/Test: 52
http://lowreal.net/Test: Devided: 109msec.
http://lowreal.net/Test: 53
http://lowreal.net/Test: 54
http://lowreal.net/Test: 55
http://lowreal.net/Test: 56
http://lowreal.net/Test: Devided: 113msec.
http://lowreal.net/Test: 57
http://lowreal.net/Test: 58
http://lowreal.net/Test: 59
http://lowreal.net/Test: Devided: 103msec.
http://lowreal.net/Test: 60
http://lowreal.net/Test: 61
http://lowreal.net/Test: 62
http://lowreal.net/Test: Devided: 119msec.
http://lowreal.net/Test: 63
http://lowreal.net/Test: 64
http://lowreal.net/Test: 65
http://lowreal.net/Test: Devided: 137msec.
http://lowreal.net/Test: 66
http://lowreal.net/Test: 67
http://lowreal.net/Test: Devided: 103msec.
http://lowreal.net/Test: 68
http://lowreal.net/Test: 69
http://lowreal.net/Test: Devided: 112msec.
http://lowreal.net/Test: 70
http://lowreal.net/Test: 71
http://lowreal.net/Test: Devided: 122msec.
http://lowreal.net/Test: 72
http://lowreal.net/Test: 73
http://lowreal.net/Test: Devided: 133msec.
http://lowreal.net/Test: 74
http://lowreal.net/Test: 75
http://lowreal.net/Test: Devided: 144msec.
http://lowreal.net/Test: 76
http://lowreal.net/Test: 77
http://lowreal.net/Test: Devided: 158msec.
http://lowreal.net/Test: 78
http://lowreal.net/Test: 79
http://lowreal.net/Test: Devided: 168msec.
http://lowreal.net/Test: 80
http://lowreal.net/Test: 81
http://lowreal.net/Test: Devided: 182msec.
http://lowreal.net/Test: 82
http://lowreal.net/Test: 83
http://lowreal.net/Test: Devided: 194msec.
http://lowreal.net/Test: 84
http://lowreal.net/Test: Devided: 103msec.
http://lowreal.net/Test: 85
http://lowreal.net/Test: Devided: 106msec.
http://lowreal.net/Test: 86
http://lowreal.net/Test: Devided: 110msec.
http://lowreal.net/Test: 87
http://lowreal.net/Test: Devided: 114msec.
http://lowreal.net/Test: 88
http://lowreal.net/Test: Devided: 118msec.
http://lowreal.net/Test: 89
http://lowreal.net/Test: Devided: 122msec.
http://lowreal.net/Test: 90
http://lowreal.net/Test: Devided: 126msec.
http://lowreal.net/Test: 91
http://lowreal.net/Test: Devided: 131msec.
http://lowreal.net/Test: 92
http://lowreal.net/Test: Devided: 135msec.
http://lowreal.net/Test: 93
http://lowreal.net/Test: Devided: 140msec.
http://lowreal.net/Test: 94
http://lowreal.net/Test: Devided: 144msec.
http://lowreal.net/Test: 95
http://lowreal.net/Test: Devided: 148msec.
http://lowreal.net/Test: 96
http://lowreal.net/Test: Devided: 153msec.
http://lowreal.net/Test: 97
http://lowreal.net/Test: Devided: 158msec.
http://lowreal.net/Test: 98
http://lowreal.net/Test: Devided: 166msec.
http://lowreal.net/Test: 99
http://lowreal.net/Test: Devided: 171msec.
http://lowreal.net/Test: 100
http://lowreal.net/Test: End

実際つかうならハードコードされてるところをましにしたりしないといけないかな。

2008年 01月 21日

キーボード

最近はずっと HHKP を使ってるなぁ。MacBook のバッテリがダメダメになって常時AC電源でやってるから、もういろいろコードを繋げまくり。今だに記号とか数字を見ないで打てない……

ノード生成関数

みじかめで、よさそうなのを書こうとしているけどわりとびみょうだなぁ http://subtech.g.hatena.ne.jp/cho45/20071117/1195309573 をもとにしてj

function $N (str, childs) {
	if (str.nodeType) return str;
	var t, cur, stack = [cur = document.createDocumentFragment()];
	while (str.length) {
		if (str.indexOf("<") == 0) {
			if (t = str.match(/^\s*<(\/?[^\s>\/]+)([^>]+?)?(\/)?>/)) {
				var tag = t[1], attrs = t[2], isempty = !!t[3];
				if (tag.indexOf("/") == -1) {
					child = document.createElement(tag);
					if (attrs) attrs.replace(/([a-z]+)=(?:'([^']*)'|"([^"]*)")/gi,
						function (m, name, v1, v2) {
							child.setAttribute(name, v1 || v2);
						}
					);
					cur.appendChild(child);
					if (!isempty) {
						stack.push(cur);
						cur = child;
					}
				} else cur = stack.pop();
			} else throw("Parse Error: " + str);
		} else if (t = str.match(/^([^<]+)/)) cur.appendChild(document.createTextNode(t[0]));
		str = str.substring(t[0].length);
	}
	var ret = stack.pop();
	if (ret.childNodes.length == 1) ret = ret.firstChild;
	if (childs) for (var i = 0; i < childs.length; i++) {
		ret.appendChild(arguments.callee(childs[i]));
	}
	return ret;
}

みたいなのにしてみた (innnerHTML は table 関係の要素を扱うとき、補完とかされてかえってめんどうくさい。)

	document.body.insertBefore(
		$N("<div/>", [
			"<p>aaa<em>foobar</em></p>",
			document.createElement("br"),
			"<p><a href=''>foobar</a></p>",
		]),
		document.body.firstChild
	);

みたいにする。文字列だけあつかえてもあんまり嬉しくないので、DOM オブジェクトを混在させてもいいように

ただ、あんまり読みやすくない。jQuery みたいなのはいいんだけど、特殊なオブジェクトをつくって DOM の基本メソッドを全部実装しないといけないから長くなる……

2008年 01月 22日

freenode の ChanServ

access #*** add <nick> 10

<cho45> level #*** list
-ChanServ@fn(ChanServ@services.)- -- Access Levels for [#***] --
-ChanServ@fn(ChanServ@services.)- Index Level Type      Description
-ChanServ@fn(ChanServ@services.)- ----- ----- ----      -----------
-ChanServ@fn(ChanServ@services.)- 1     -1    AUTODEOP  Automatic deop/devoice
-ChanServ@fn(ChanServ@services.)- 2     OFF   AUTOVOICE Automatic voice
-ChanServ@fn(ChanServ@services.)- 3     8     CMDVOICE  Use of command VOICE
-ChanServ@fn(ChanServ@services.)- 4     30    ACCESS    Allow ACCESS modification
-ChanServ@fn(ChanServ@services.)- 5     5     CMDINVITE Use of command INVITE
-ChanServ@fn(ChanServ@services.)- 6     30    AUTOOP    Automatic op
-ChanServ@fn(ChanServ@services.)- 7     10    CMDOP     Use of command OP
-ChanServ@fn(ChanServ@services.)- 8     10    CMDUNBAN  Use of command UNBAN
-ChanServ@fn(ChanServ@services.)- 9     15    AUTOKICK  Allow AKICK modification
-ChanServ@fn(ChanServ@services.)- 10    20    CMDCLEAR  Use of command CLEAR
-ChanServ@fn(ChanServ@services.)- 11    25    SET       Modify channel SETs
-ChanServ@fn(ChanServ@services.)- 14    10    TOPIC     Change the channel topic
-ChanServ@fn(ChanServ@services.)- 15    50    LEVEL     Use of command LEVEL
-ChanServ@fn(ChanServ@services.)- -- End of list --

を ChanServ に送ると指定 nick をチャンネルのアクセスリストに加えられる。30 とかやると autoop になる?
一定以上の level は contact じゃないと設定できない 。contact の nick でログインし NickServ で identify していても、 ChanServ に identify しないとだめ。現在の自分の level 未満しか設定できないっぽい。contact は level 50 みたいで、49 までしか設定できない (すなわち 50 になるためには contact にならないといけない?)。help すると mask を設定すると書いてあるけど、http://freenode.net/using_the_network.shtml では registered nick を指定するように書いてある。

デフォルトだと split したあとに level 0 のユーザ (access list にないユーザ) は deop される。


ある nick が登録されているかどうかは /msg NickServ info nick すればいいみたいだ。登録されてない nick を access list に入れるとどうなるんだろう。 Nick [fagaslgol] is not registered みたいにおこられた。


以下ヘルプ転載 (これまとめてあるのどこにあるんだろ……)
ChanServ

<cho45> help
-ChanServ@fn(ChanServ@services.)- ChanServ allows you to register and control various
-ChanServ@fn(ChanServ@services.)- aspects of channels.  ChanServ can often prevent
-ChanServ@fn(ChanServ@services.)- malicious users from "taking over" channels by limiting
-ChanServ@fn(ChanServ@services.)- who is allowed channel operator priviliges.  Any channel
-ChanServ@fn(ChanServ@services.)- which is not used for 120 days will be expired and may
-ChanServ@fn(ChanServ@services.)- be dropped.  ChanServ's commands are listed below.
-ChanServ@fn(ChanServ@services.)- For more information on a specific command, type
-ChanServ@fn(ChanServ@services.)- /msg ChanServ help <command>.
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)-     REGISTER   Register a channel
-ChanServ@fn(ChanServ@services.)-     DROP       Cancel the registration of a channel
-ChanServ@fn(ChanServ@services.)-     IDENTIFY   Identify yourself with your password
-ChanServ@fn(ChanServ@services.)-     SET        Set various channel options
-ChanServ@fn(ChanServ@services.)-     ACCESS     Modify the list of privileged users
-ChanServ@fn(ChanServ@services.)-     AUTOREM    Maintain the AutoRemove list
-ChanServ@fn(ChanServ@services.)-     LEVEL      Change the level required for functions
-ChanServ@fn(ChanServ@services.)-     LIST       Display list of channels matching a pattern
-ChanServ@fn(ChanServ@services.)-     INFO       Display information for a channel
-ChanServ@fn(ChanServ@services.)-     GETKEY     Retrieve the key (+k) to a channel
-ChanServ@fn(ChanServ@services.)-     INVITE     Invite yourself to a channel
-ChanServ@fn(ChanServ@services.)-     OP         Op yourself on a channel
-ChanServ@fn(ChanServ@services.)-     VOICE      Voice yourself on a channel
-ChanServ@fn(ChanServ@services.)-     UNBAN      Unban yourself on a channel
-ChanServ@fn(ChanServ@services.)-     CLEAR      Clear various channel modes
<cho45> help register
-ChanServ@fn(ChanServ@services.)- Syntax: REGISTER <channel> [password]
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Registers <channel> in ChanServ's database.  [password] is
-ChanServ@fn(ChanServ@services.)- used via ChanServ IDENTIFY to identify the channel contact
-ChanServ@fn(ChanServ@services.)- for some functions. If no password is specified, only
-ChanServ@fn(ChanServ@services.)- the channel contact nick can use ChanServ IDENTIFY.
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Guidelines for running a freenode channel are found here:
-ChanServ@fn(ChanServ@services.)- http://freenode.net/channel_guidelines.shtml Pick someone
-ChanServ@fn(ChanServ@services.)- to register your project channel who is around frequently. 
-ChanServ@fn(ChanServ@services.)- If your channel contact's nick expires,
-ChanServ@fn(ChanServ@services.)- ChanServ will drop their channel when NickServ drops
-ChanServ@fn(ChanServ@services.)- their nick. Consider setting an ALTERNATE (/msg
-ChanServ@fn(ChanServ@services.)- ChanServ HELP SET ALTERNATE) to avoid
-ChanServ@fn(ChanServ@services.)- this situation.
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Give channel staffers the ability to maintain
-ChanServ@fn(ChanServ@services.)- your channel via the ACCESS command (/msg ChanServ
-ChanServ@fn(ChanServ@services.)- HELP ACCESS).  Level '10' lets them gain ops,
-ChanServ@fn(ChanServ@services.)- voice and devoice users, etc. Try to ensure your
-ChanServ@fn(ChanServ@services.)- channel has 24-hour coverage.  Staffers should
-ChanServ@fn(ChanServ@services.)- IDENTIFY to NickServ so that their nicks don't expire,
-ChanServ@fn(ChanServ@services.)- and so that ChanServ will recognize them.
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- If no one on a channel's ACCESS list enters the
-ChanServ@fn(ChanServ@services.)- channel within 120 days, the channel will be
-ChanServ@fn(ChanServ@services.)- considered expired and may be dropped.
<cho45> help drop
-ChanServ@fn(ChanServ@services.)- Syntax: DROP <channel> [password]
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Cancels the registration of <channel>.  Only a
-ChanServ@fn(ChanServ@services.)- channel contact may DROP a channel.  Also,
-ChanServ@fn(ChanServ@services.)- the contact must IDENTIFY before using this
-ChanServ@fn(ChanServ@services.)- command, or supply the correct channel password.
<cho45> help identify
-ChanServ@fn(ChanServ@services.)- Syntax: IDENTIFY <channel> [password]
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Identifies you as the channel contact for <channel>. 
-ChanServ@fn(ChanServ@services.)- Some ChanServ commands require that you IDENTIFY before
-ChanServ@fn(ChanServ@services.)- using them.
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- If you are the contact (your master nick is equal to
-ChanServ@fn(ChanServ@services.)- the stored contact nick), you need not use the channel
-ChanServ@fn(ChanServ@services.)- password, otherwise you have to. If there is no channel
-ChanServ@fn(ChanServ@services.)- password, only the contact nick can use this command.
<cho45> help set
-ChanServ@fn(ChanServ@services.)- Syntax: SET <channel> <option> [parameters]
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Allows the channel contact or level 25 to set various
-ChanServ@fn(ChanServ@services.)- channel options and other information. All options may
-ChanServ@fn(ChanServ@services.)- be abbreviated, such as:
-ChanServ@fn(ChanServ@services.)- /msg ChanServ set #channel CONT newcontact
-ChanServ@fn(ChanServ@services.)- to set the CONTACT nickname to "newcontact".  For more
-ChanServ@fn(ChanServ@services.)- specific information on each option, type:
-ChanServ@fn(ChanServ@services.)- /msg ChanServ HELP SET <option>
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Available options:
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)-     CONTACT     Set the contact of a channel (contact)
-ChanServ@fn(ChanServ@services.)-     ALTERNATE   Set the alternate contact for the channel
-ChanServ@fn(ChanServ@services.)-     PASSWORD    Set the contact password (contact)
-ChanServ@fn(ChanServ@services.)-     MLOCK       Lock channel modes on or off
-ChanServ@fn(ChanServ@services.)-     TOPICLOCK   Restrict topic changes
-ChanServ@fn(ChanServ@services.)-     PRIVATE     Hide channel from ChanServ lists
-ChanServ@fn(ChanServ@services.)-     SECUREOPS   Stricter control of chanop status
-ChanServ@fn(ChanServ@services.)-     SECURE      Activate ChanServ security features
-ChanServ@fn(ChanServ@services.)-     ENTRYMSG    Send a message to users upon entry
-ChanServ@fn(ChanServ@services.)-     EMAIL       Set the channel email address
-ChanServ@fn(ChanServ@services.)-     URL         Set the channel url
-ChanServ@fn(ChanServ@services.)-     GUARD       Have ChanServ join your channel
-ChanServ@fn(ChanServ@services.)-     SPLITOPS    Let anyone keep ops from a netsplit
-ChanServ@fn(ChanServ@services.)-     VERBOSE     Notify chanops on access changes
<cho45> help access
-ChanServ@fn(ChanServ@services.)- Syntax: ACCESS <channel> ADD <mask> <level>
-ChanServ@fn(ChanServ@services.)-         ACCESS <channel> DEL <mask | index>
-ChanServ@fn(ChanServ@services.)-         ACCESS <channel> LIST [mask]
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Maintains the channel access list for <channel>.
-ChanServ@fn(ChanServ@services.)- Users matching a hostmask on the access list will
-ChanServ@fn(ChanServ@services.)- have access to various ChanServ commands depending on
-ChanServ@fn(ChanServ@services.)- what level they have (/msg ChanServ HELP LEVEL for
-ChanServ@fn(ChanServ@services.)- how to view and change the level required for each
-ChanServ@fn(ChanServ@services.)- command).  Anyone not on the channel's access list
-ChanServ@fn(ChanServ@services.)- has a default access level of 0.  You may type:
-ChanServ@fn(ChanServ@services.)- /msg ChanServ HELP ACCESS {ADD|DEL|LIST} for more
-ChanServ@fn(ChanServ@services.)- specific information on each command.
<cho45> help autorem
-ChanServ@fn(ChanServ@services.)- Syntax: AUTOREM <channel> ADD <mask> [reason]
-ChanServ@fn(ChanServ@services.)-         AUTOREM <channel> DEL <mask | index>
-ChanServ@fn(ChanServ@services.)-         AUTOREM <channel> LIST [mask]
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Maintains the channel autoremove list for <channel>.
-ChanServ@fn(ChanServ@services.)- If a user on the autoremove list attempts to join the
-ChanServ@fn(ChanServ@services.)- channel, ChanServ will ban/remove the user.
-ChanServ@fn(ChanServ@services.)- /msg ChanServ HELP AUTOREM {ADD|DEL|LIST} for more
-ChanServ@fn(ChanServ@services.)- specific information on each command.
<cho45> help level
-ChanServ@fn(ChanServ@services.)- Syntax: LEVEL <channel> SET <type|index> <level>
-ChanServ@fn(ChanServ@services.)-         LEVEL <channel> RESET <type|index|ALL>
-ChanServ@fn(ChanServ@services.)-         LEVEL <channel> LIST
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Changes the access level required to be able to execute
-ChanServ@fn(ChanServ@services.)- certain commands.  This allows the channel contact to be
-ChanServ@fn(ChanServ@services.)- able to customize the access level list to the needs of
-ChanServ@fn(ChanServ@services.)- the channel.  For more specific help on each command,
-ChanServ@fn(ChanServ@services.)- type: /msg ChanServ HELP LEVEL {SET|RESET|LIST}
<cho45> help list
-ChanServ@fn(ChanServ@services.)- Syntax: LIST <pattern>
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Lists all registered channels that match <pattern>.
-ChanServ@fn(ChanServ@services.)- Channels that have SET PRIVATE ON, will not be
-ChanServ@fn(ChanServ@services.)- displayed.
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Example: LIST #*bleh*
-ChanServ@fn(ChanServ@services.)-            Lists all channels that contain bleh
<cho45> help info
-ChanServ@fn(ChanServ@services.)- Syntax: INFO <channel>
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Displays information for <channel>, including channel
-ChanServ@fn(ChanServ@services.)- contact, time of registration, topic, and mode lock, if
-ChanServ@fn(ChanServ@services.)- any.
<cho45> help getkey
-ChanServ@fn(ChanServ@services.)- Syntax: GETKEY <channel>
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Returns the key to <channel>.  Useful if the channel
-ChanServ@fn(ChanServ@services.)- is set +k.
<cho45> help invite
-ChanServ@fn(ChanServ@services.)- Syntax: INVITE <channel>
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Invites the sender to <channel>.  Useful if SET MLOCK
-ChanServ@fn(ChanServ@services.)- is set to +i on the channel.
-ChanServ@fn(ChanServ@services.)- Example:
-ChanServ@fn(ChanServ@services.)-         /msg ChanServ INVITE #channel
-ChanServ@fn(ChanServ@services.)-           ChanServ will invite you to #channel.
<cho45> help op
-ChanServ@fn(ChanServ@services.)- Syntax: OP <channel | ALL> [nicknames]
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Gives channel operator status to [nicknames].  If no
-ChanServ@fn(ChanServ@services.)- nicknames are specified, ChanServ will op the nick who gave
-ChanServ@fn(ChanServ@services.)- the command.  Placing a - in front of a nick will
-ChanServ@fn(ChanServ@services.)- deop that nick.  If SECUREOPS is ON, ChanServ will not
-ChanServ@fn(ChanServ@services.)- op nicks who do not have a level of CmdOp or higher.
-ChanServ@fn(ChanServ@services.)- Examples:
-ChanServ@fn(ChanServ@services.)-          /msg ChanServ OP #channel
-ChanServ@fn(ChanServ@services.)-            Ops the nick who gave the command on #channel.
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)-          /msg ChanServ OP #channel nick1 -nick2 nick3
-ChanServ@fn(ChanServ@services.)-            Ops nick1 and nick3, but deops nick2 on #channel.
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)-          /msg ChanServ OP ALL
-ChanServ@fn(ChanServ@services.)-            Ops you in all channels you are currently in, if
-ChanServ@fn(ChanServ@services.)-           you have CMDOP access.
<cho45> help voice
-ChanServ@fn(ChanServ@services.)- Syntax: VOICE <channel> [nicknames]
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Gives voice status to [nicknames].  If no nicknames
-ChanServ@fn(ChanServ@services.)- are specified, ChanServ will voice the nick who gave the 
-ChanServ@fn(ChanServ@services.)- command.  Placing a - in front of a nick will
-ChanServ@fn(ChanServ@services.)- devoice that nick.
-ChanServ@fn(ChanServ@services.)- ChanServ will refuse to voice an user who is on the access
-ChanServ@fn(ChanServ@services.)- list as autodevoiced. To disable this, prefix the nick
-ChanServ@fn(ChanServ@services.)- with a +.
-ChanServ@fn(ChanServ@services.)- Examples:
-ChanServ@fn(ChanServ@services.)-          /msg ChanServ VOICE #channel
-ChanServ@fn(ChanServ@services.)-            Voices the nick who gave the command on #channel.
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)-          /msg ChanServ VOICE #channel nick1 -nick2 +nick3
-ChanServ@fn(ChanServ@services.)-            Voices nick1, nick3 even if autodevoiced,
-ChanServ@fn(ChanServ@services.)-            but devoices nick2 on #channel.
<cho45> help unban
-ChanServ@fn(ChanServ@services.)- Syntax: UNBAN <channel> [ALL]
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Unbans every ban matching your user@host or user@ip and
-ChanServ@fn(ChanServ@services.)- every gecos ban matching your ircname on <channel>. If
-ChanServ@fn(ChanServ@services.)- you specify ALL, every ban and gecos ban on <channel>
-ChanServ@fn(ChanServ@services.)- will be cleared. You must have CMDCLEAR access to
-ChanServ@fn(ChanServ@services.)- <channel> to use the ALL option.
-ChanServ@fn(ChanServ@services.)- Examples:
-ChanServ@fn(ChanServ@services.)-          /msg ChanServ UNBAN #channel
-ChanServ@fn(ChanServ@services.)-             Clears every ban on #channel matching you
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)-          /msg ChanServ UNBAN #channel ALL
-ChanServ@fn(ChanServ@services.)-             Clears every ban on #channel.
<cho45> help clear
-ChanServ@fn(ChanServ@services.)- Syntax: CLEAR <channel> <option>
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- ChanServ will clear certain channel modes depending on
-ChanServ@fn(ChanServ@services.)- <option>.
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)- Options:
-ChanServ@fn(ChanServ@services.)- 
-ChanServ@fn(ChanServ@services.)-      OPS       - Deops every channel op
-ChanServ@fn(ChanServ@services.)-      VOICES    - Devoices every voiced user
-ChanServ@fn(ChanServ@services.)-      MODES     - Clears all channel modes
-ChanServ@fn(ChanServ@services.)-      BANS      - Removes all channel bans
-ChanServ@fn(ChanServ@services.)-      GECOSBANS - Remove all channel gecos bans
-ChanServ@fn(ChanServ@services.)-      USERS     - Removes all users from channel
-ChanServ@fn(ChanServ@services.)-      ALL       - Combination of OPS, VOICES, MODES,
-ChanServ@fn(ChanServ@services.)-                      and BANS (does not remove users)

NichServ

<cho45> help
-NickServ@fn(NickServ@services.)- NickServ allows you to "register" a nickname and
-NickServ@fn(NickServ@services.)- prevent others from using it. The following
-NickServ@fn(NickServ@services.)- commands allow for registration and maintenance of
-NickServ@fn(NickServ@services.)- nicknames; to use them, type /msg NickServ <command>.
-NickServ@fn(NickServ@services.)- For more information on a specific command, type
-NickServ@fn(NickServ@services.)- /msg NickServ help <command>.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)-     REGISTER   Register a nickname
-NickServ@fn(NickServ@services.)-     DROP       Cancel the registration of a nickname
-NickServ@fn(NickServ@services.)-     IDENTIFY   Identify yourself with your password
-NickServ@fn(NickServ@services.)-     ACCESS     Modify the list of authorized addresses
-NickServ@fn(NickServ@services.)-     SET        Set various options for your nickname
-NickServ@fn(NickServ@services.)-     LIST       Display list of nicks matching a pattern
-NickServ@fn(NickServ@services.)-     RECOVER    Kill another user who has taken your nick
-NickServ@fn(NickServ@services.)-     RELEASE    Regain custody of your nick after RECOVER
-NickServ@fn(NickServ@services.)-     GHOST      Kill a ghosted nickname
-NickServ@fn(NickServ@services.)-     INFO       Get information for a nickname
-NickServ@fn(NickServ@services.)-     LINK       Link your nickname to another
-NickServ@fn(NickServ@services.)-     UNLINK     UnLink your nickname
<cho45> help register
-NickServ@fn(NickServ@services.)- Syntax: REGISTER <password>
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- This enables you to register your nickname with a
-NickServ@fn(NickServ@services.)- password so only you can use it.  Please try to
-NickServ@fn(NickServ@services.)- use obscure passwords that cannot be easily guessed.
-NickServ@fn(NickServ@services.)- Passwords *ARE* case sensitive.  Once you have
-NickServ@fn(NickServ@services.)- registered a nickname, you can use the SET and
-NickServ@fn(NickServ@services.)- ACCESS commands to configure it.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- Please IDENTIFY yourself to nickserv when you
-NickServ@fn(NickServ@services.)- connect to the network. Many clients will allow you
-NickServ@fn(NickServ@services.)- to automate this function.  If you don't IDENTIFY
-NickServ@fn(NickServ@services.)- to NickServ for a period of 60 days or more, your
-NickServ@fn(NickServ@services.)- nickname will be considered to be expired and it
-NickServ@fn(NickServ@services.)- may be dropped.
<cho45> help drop
-NickServ@fn(NickServ@services.)- Syntax: DROP <nickname> <password>
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- DROP allows you to cancel the registration of your
-NickServ@fn(NickServ@services.)- nickname, thus allowing others to re-register it.
<cho45> help identify
-NickServ@fn(NickServ@services.)- Syntax: IDENTIFY <password>
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- Most commands require that you identify yourself, in order to
-NickServ@fn(NickServ@services.)- use them.  Also, nicknames which have kill protection will
-NickServ@fn(NickServ@services.)- be killed if the user has not identified within one minute.
-NickServ@fn(NickServ@services.)- If SET AUTOMASK is ON, and you IDENTIFY from a host
-NickServ@fn(NickServ@services.)- which is not on your ACCESS list, the new hostmask will
-NickServ@fn(NickServ@services.)- automatically be added to it.
<cho45> help access
-NickServ@fn(NickServ@services.)- Syntax: ACCESS {ADD|DEL|LIST} [mask]
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- The ACCESS command allows you to modify the list of
-NickServ@fn(NickServ@services.)- recognized hostmasks for your nickname.  If you use a
-NickServ@fn(NickServ@services.)- hostmask that is not on your ACCESS list, you must
-NickServ@fn(NickServ@services.)- IDENTIFY with NickServ.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- Examples:
-NickServ@fn(NickServ@services.)-     ACCESS ADD *wnder@*underworld.net
-NickServ@fn(NickServ@services.)-        Gives users matching *wnder@*underworld.net
-NickServ@fn(NickServ@services.)-        permission to use your nickname.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)-     ACCESS DEL *wnder@*underworld.net
-NickServ@fn(NickServ@services.)-        Opposite of previous command.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)-     ACCESS LIST
-NickServ@fn(NickServ@services.)-        Displays list of authorized hostmasks for your
-NickServ@fn(NickServ@services.)-        nickname.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- Type: /msg NickServ HELP ACCESS <option> for more information
<cho45> help set
-NickServ@fn(NickServ@services.)- Syntax: SET <option> [parameters]
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- Configures various nickname options.
-NickServ@fn(NickServ@services.)- Options:
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)-     KILL       Turn kill protection on or off
-NickServ@fn(NickServ@services.)-     AUTOMASK   Auto add new hostmasks on IDENTIFY
-NickServ@fn(NickServ@services.)-     PASSWORD   Reset your nickname password
-NickServ@fn(NickServ@services.)-     SECURE     Turn nickname security on or off
-NickServ@fn(NickServ@services.)-     UNSECURE   Set nickname security very low
-NickServ@fn(NickServ@services.)-     PRIVATE    Hide nickname information from LISTs
-NickServ@fn(NickServ@services.)-     MEMOS      Allow memos sent to your nick
-NickServ@fn(NickServ@services.)-     NOTIFY     Turn notification of new memos on/off
-NickServ@fn(NickServ@services.)-     SIGNON     Turn notification of memos on signon on/off
-NickServ@fn(NickServ@services.)-     EMAIL      Associate an email address with your nick
-NickServ@fn(NickServ@services.)-     URL        Associate a url with your nick
-NickServ@fn(NickServ@services.)-     HIDE       Hide information in your INFO reply
-NickServ@fn(NickServ@services.)-     UIN        Set ICQ UIN for this user
-NickServ@fn(NickServ@services.)-     GSM        Set number of mobile phone for this user
-NickServ@fn(NickServ@services.)-     PHONE      Set the phone for this user
-NickServ@fn(NickServ@services.)-     UNFILTERED Allow messages from unregistered users
-NickServ@fn(NickServ@services.)-     MASTER     Reset the master nickname for your link
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- Type /msg NickServ HELP SET option for more information
-NickServ@fn(NickServ@services.)- on a specific option.
<cho45> help list
-NickServ@fn(NickServ@services.)- Syntax: LIST <pattern>
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- Lists all registered nicknames that match <pattern>.
-NickServ@fn(NickServ@services.)- Nicknames that have SET PRIVATE ON, will not be
-NickServ@fn(NickServ@services.)- displayed.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- Example: LIST *nick*
-NickServ@fn(NickServ@services.)-            Lists all nicknames that contain nick
<cho45> help recover
-NickServ@fn(NickServ@services.)- Syntax: RECOVER <nickname> [password]
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- If someone has stolen your nickname, you can use
-NickServ@fn(NickServ@services.)- RECOVER to get it back.  RECOVER performs
-NickServ@fn(NickServ@services.)- a nick collide on <nickname> and enforces the
-NickServ@fn(NickServ@services.)- nickname until you use the RELEASE command on
-NickServ@fn(NickServ@services.)- it, or just wait until the release timeout.  If
-NickServ@fn(NickServ@services.)- you match a hostmask on <nickname>'s ACCESS
-NickServ@fn(NickServ@services.)- list, and <nickname> has NOT SET SECURE ON,
-NickServ@fn(NickServ@services.)- or if you are identified to a linked nickname,
-NickServ@fn(NickServ@services.)- you do not need to supply a password.
-NickServ@fn(NickServ@services.)- Otherwise, you have to supply the correct
-NickServ@fn(NickServ@services.)- password.
<cho45> help release
-NickServ@fn(NickServ@services.)- Syntax: RELEASE <nickname> [password]
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- If NickServ is enforcing your nickname, as it would
-NickServ@fn(NickServ@services.)- after a RECOVER or if you didn't IDENTIFY
-NickServ@fn(NickServ@services.)- in time, you can use RELEASE to regain control
-NickServ@fn(NickServ@services.)- of your nickname.  If you match a hostmask on
-NickServ@fn(NickServ@services.)- <nickname>'s ACCESS list, and <nickname>'s
-NickServ@fn(NickServ@services.)- SET SECURE is OFF, or if you are
-NickServ@fn(NickServ@services.)- identified to a linked nickname, you do not
-NickServ@fn(NickServ@services.)- need to supply a password.  Otherwise, you
-NickServ@fn(NickServ@services.)- have to supply the correct password.
<cho45> help ghost
-NickServ@fn(NickServ@services.)- Syntax: GHOST <nickname> [password]
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- If you suddenly get disconnected from your isp or
-NickServ@fn(NickServ@services.)- the irc server, sometimes a ghosted client will
-NickServ@fn(NickServ@services.)- be left behind.  This command can be used to
-NickServ@fn(NickServ@services.)- kill the ghosted client so you can get your
-NickServ@fn(NickServ@services.)- nickname back.  If <nickname> has SET SECURE
-NickServ@fn(NickServ@services.)- OFF, and you match a hostmask on <nickname>'s
-NickServ@fn(NickServ@services.)- ACCESS LIST, or if you are identified to a linked
-NickServ@fn(NickServ@services.)- nickname, you do not need to supply a password.
-NickServ@fn(NickServ@services.)- Otherwise, you have to supply the correct
-NickServ@fn(NickServ@services.)- password.
<cho45> help info
-NickServ@fn(NickServ@services.)- Syntax: INFO <nickname>
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- Displays information for <nickname> such as time registered,
-NickServ@fn(NickServ@services.)- SET options, whether they are online, etc.
<cho45> help link
-NickServ@fn(NickServ@services.)- Syntax: LINK <nickname> <password>
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- This command will link your current nickname to
-NickServ@fn(NickServ@services.)- <nickname>, assuming you have supplied the correct
-NickServ@fn(NickServ@services.)- password for <nickname>. Once you have linked nicknames,
-NickServ@fn(NickServ@services.)- your ACCESS list will be deleted, and you will share
-NickServ@fn(NickServ@services.)- <nickname>'s access list. Your memos will also be added
-NickServ@fn(NickServ@services.)- to <nickname>'s memos. Your channel access will be merged
-NickServ@fn(NickServ@services.)- with <nickname>'s access. If <nickname> was previously
-NickServ@fn(NickServ@services.)- unlinked, it will become the master nickname for your
-NickServ@fn(NickServ@services.)- link.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- When any nickname in your link gives a command to services,
-NickServ@fn(NickServ@services.)- it will be processed as if it came from the master nickname,
-NickServ@fn(NickServ@services.)- with the exception of DROP, UNLINK, SET PASSWORD,
-NickServ@fn(NickServ@services.)- SET EMAIL, and SET URL.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- The advantage of linked nicknames is whenever you
-NickServ@fn(NickServ@services.)- IDENTIFY for one nick, you will be identified for
-NickServ@fn(NickServ@services.)- every nick in the link. Also, memos sent to any nickname
-NickServ@fn(NickServ@services.)- will all be stored in the master nickname's record, for
-NickServ@fn(NickServ@services.)- any nickname in the link to read. Furthermore, if any
-NickServ@fn(NickServ@services.)- nickname in the link is on a channel's access list, all
-NickServ@fn(NickServ@services.)- nicknames will receive the same access. Also, all
-NickServ@fn(NickServ@services.)- linked nicknames have the same cloak.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- Example:
-NickServ@fn(NickServ@services.)-         /msg NickServ LINK CoolGuy CoolGuysPassword
-NickServ@fn(NickServ@services.)-           Links your nickname to "CoolGuy".
<cho45> help unlink
-NickServ@fn(NickServ@services.)- Syntax: UNLINK [nickname [password]]
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- This command will unlink your nickname from your current
-NickServ@fn(NickServ@services.)- link. Or, if [nickname [password]] is specified, it will
-NickServ@fn(NickServ@services.)- unlink [nickname] from its current link. When you unlink,
-NickServ@fn(NickServ@services.)- the access list of the master of the link will be copied
-NickServ@fn(NickServ@services.)- to your own. Memos, however, are not copied. The channel
-NickServ@fn(NickServ@services.)- access remains with the other nicks; the unlinked nick
-NickServ@fn(NickServ@services.)- will not have any channel access. If you are unlinking
-NickServ@fn(NickServ@services.)- the master nickname, the next nickname in the link will
-NickServ@fn(NickServ@services.)- become the new master.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)- Example:
-NickServ@fn(NickServ@services.)-         /msg NickServ UNLINK
-NickServ@fn(NickServ@services.)-           Unlinks your nickname from your link.
-NickServ@fn(NickServ@services.)- 
-NickServ@fn(NickServ@services.)-         /msg NickServ UNLINK CoolGuy CoolGuysPassword
-NickServ@fn(NickServ@services.)-           Unlinks "CoolGuy" from whatever link he
-NickServ@fn(NickServ@services.)-           was in.

freenode の umode とか

Adobe Lightroom

Mac 版 Picasa がはやくでてほしい……

とかおもいつつ Lightroom を試用してみる。買わないけど

  • 結構レスポンスがいい。smb 経由で一枚 13MB ぐらいの写真をあつかっているけど、プレビューの生成とかのタイミングが結構いいっぽい。
  • 現像パラメータは Photoshop CS 3 と全く一緒。UI がすこしちがう。トーンカーブの設定がかっこよくなっていて、ハイライトとかの設定とポイントのカーブ設定が統合されている (より直感的)
  • ダブルクリックで 100% と全体表示をきりかえされるのは気持ちがいい。
  • TAB でさらに全画面にすぐできるのも気持ちがいい。
  • 補正前と補正後の二枚表示とか、複数写真の拡大率同期しながらの比較は便利
  • 「ライブラリ」と「現像」のきりかえは遅い

写真現像専用にはいいかもなぁ。でも Photoshop もっているなら 30k はちょっと高い (同じことはできるし) 逆に Photoshop もってなくて写真現像しかやらねーよっていう場合はやすい気もする。

2008年 01月 23日

あせる。些細なことで凹みすぎだ。些細ではないかもしれないけど、いやよくわからない。

寝るのがめんどうくさい……眼を閉じたらすぐ眠れて、眼をパチっと開いたらすぐに覚醒するならいいのに……寝よう寝ようと思いながら横になって、起きるときは頭がぼーっとしてしばらくどうしようもない気持ちになる。

うまくいかないなぁ……なにがわるいんだろう……

ゆっくりと、つくったものを消費しながら、忘れていく人になるのだなぁ

2008年 01月 24日

g:jpg を作ったはいいけど、CSS 書くのがめんどうなのだよなぁ (グループの CSS だけ書いてつかれた)

現像のアイデアをすこし変えてみた。

灰羽連盟ほんといいなぁ

2008年 01月 25日

lig.rb

Linger の IRC gateway を Ruby でかきました。

  • 部屋に入れる (パスワードつきの部屋にも入れる)
  • 発言できる

だけです。

  • チャンネル名は URL の末尾のやつ (チャンネルの名前ではない)
  • leave しないで放置して繋ぎなおすと、いっぱいメッセージが流れるかもしれないですが処理していません。
  • 部屋の nick がそのまま IRC の nick として流れます。なのでクライアントが u8 の nick を処理できないと死にます。

Ruby のライブラリが一応公開されていたのでそれつかっています。http://svn.lingr.com/api/toolkits/ruby/infoteria/api_client.rb

chokan の rice/irc が必要です。

$ mkdir lig
$ cd lig
$ svn export http://svn.coderepos.org/share/lang/ruby/chokan/trunk/rice/
$ wget http://svn.lingr.com/api/toolkits/ruby/infoteria/api_client.rb
$ wget http://svn.coderepos.org/share/lang/ruby/misc/lig.rb

今は net-irc gem の一部になっています。HEAD をかなり頻繁に更新しているので

$ svn co http://svn.coderepos.org/share/lang/ruby/net-irc/trunk/ net-irc
$ ruby examples/lig.rb --help

してください


tiarra の設定例

lingr {
	host: localhost
	port: 16669
	name: username@example.com
	password: password on lingr
	in-encoding: utf8
	out-encoding: utf8
}

haskell_hackathon_2008 を IRC から見たかったのでつくりました。最初は http://search.cpan.org/src/MIYAGAWA/POE-Component-Client-Lingr-0.04/eg/lingr-ircd.pl を使おう/いじってみようとおもったのですが、せっかくなので Lingr の API をさわってみた感じです。

rice をもとにして IRC サーバをもっと簡単にかくライブラリを書いて gem にするとよさそうかもしれない。あんまソース綺麗じゃないしなぁ (てきとうに書いたわりにそこそこ安定してる)

なんかうんこみたいなバグがいっぱいあったのでたくさんなおしました。日記書くとバグがみつかる

Lingr めも

セッションは同じアカウントでも完全別々にはれる。lig.rb で接続しっぱで Web から見てもきられないし、occupant_id も違う。でも完全に別人として扱われるわけではなく、chatters では重複しないようになってる (よくわからない。occupant_id で判断しているんじゃないのか)

あ、user_id ってのが別にあった。occupant_id は anonymous でも絶対にあるけど、user_id はない。

Y

Y コンビネータが今の僕には理解できない。

JSDeferred の parallel が直接繋げられない理由

http://void.heteml.jp/blog/archives/2008/01/asdeferred.html ASDeferred !

parallel に直接つなげられない理由をとりあえず書いておきます。(ASDeferred での回避法はちゃんと読んでない><)

まずそもそも

next(function ..).
wait(1).
next(function ..);

みたいなときの wait(1) は

next(function ..).
next(function () {
    return wait(1);
}).
next(function ..);

を簡単に書くためだけにあります。でもこの二つには決定的な違いがあって、それは wait(..) の引数の評価タイミングです。wait みたいに引数がいつ評価してもかわらないようなのならいいのですが、parallel みたいなのだと困ります。(wait でも、変数を書いて、非同期にその値を書きかえる、っていう場合は同じように問題でてきます)

next(function () {
	alert(0);
	return wait(3).next(function () {
		alert(1);
	});
}).
next(function () {
	return parallel({
		foo: wait(1).next(function () { alert(2) }),
		bar: wait(2).next(function () { alert(3) })
	});
}).
next(function (results) {
	alert(4);
});

これは正しく 0, 1, 2, 3, 4 と表示されますが、

Deferred.register("parallel", parallel);

next(function () {
	alert(0);
	return wait(3).next(function () {
		alert(1);
	});
}).
parallel({
	foo: wait(1).next(function () { alert(2) }),
	bar: wait(2).next(function () { alert(3) })
}).
next(function (results) {
	alert(4);
});

これは parallel の引数の wait(1) と wait(2) が、最初の next() とかと同時に評価されるので、順がくずれ 0, 2, 3, 1 になります。(4 もよばれないけど、あとから継続をセットしてもよばないせい。変えようか迷ってるけど変えてない)


でもって、あんまり深く考えず、next().wait().next() みたいに書くのはあくまで速記法だから parallel はなくてイイヤーってのが今の状態です><

ちなみに call() の速記版がないのは、もともと prototype.call があるので名前に困ってつけてないだけです (この二つは全然ちがうものです)。

2008年 01月 26日

全開にして収差だす (50mm f/1.4 は開放の性能がよくないので全開で撮って編集するとトイカメラっぽくなる)

irc

irc ライブラリをかく -> chokan の設計みなおす

2008年 01月 27日

コードも日記も

同じように、未来の自分に向けて書いている。おれはおれのためにしか日記やコードを書いていない。

kayac

面白法人カヤック に来ています。

文乃さん

なんか一昨日までちゃんと「文乃さん やばい」で一位だったのに、今日みたら三位だった。ありえん(笑)

SoozyConference #4

帰宅した。
とりあえずカヤックオシャレすぎる。


超LTのクオリティが高すぎてうけた。

写真

今日は55枚とった

2008年 01月 28日

wikiforme の (だいたい) 最小の syntax 定義と部分編集

セクション編集ができる wiki がほしいなぁとおもって wikiforme だとどうなんかなぁと思いつつ、syntax 定義をもぞもぞ書く (内部でどういう構造になってるのかよくわからないのでためしに)

HTML のセクションから、ソースのその範囲を取得できればいいのだから、トップレベルのセクションを列挙して、番号をふり (直接ふらなくてもいいけど)、それがソースではどの範囲にあたるかをとれればいい。行番号は parse した直後のやつには含まれているけど、それを保存して、構造化 HTML をはく process はないみたいなので自分で書くしかない。


とおもいながら書いていたのだけど、process で行番号がとれないことに気付いた。行番号はエラー表示のためだけにあるみたいだ (assemble.rb L42 あたり)。なおそうと思うと結構広範囲に影響しそうでやりにくい。のでとりあえずやめた。

#!/usr/bin/env ruby

require "pp"

$LOAD_PATH << "core"

require "wikiforme"

wikiforme = WikiForme.new("foobar.4me")

array =  wikiforme.parse(DATA)

params    = {}
root      = :page
root_text = "test"

pp array

p array.assemble(params, root, root_text).process(:html)

__END__
** Foobar

aaa

** Baz

bbb
# foobar.4me/foobar.rb

Format.block :page  do
	contain        :section
	module_eval do
		def process_html
			@children
		end
	end
end

Format.block :section do
	default_syntax "**"
	contain        :@contents, :@blank
	module_eval do
		def preprocess
			super
		end

		def process_html
			p self
			XML[
				:div, {:class => "section"},
					[:div, {:class => "heading"}, @text.process],
					@children
			]
		end
	end
end

Format.block :blank do
	default_syntax :blank
	group          :@blank
	module_eval do
		def process_html
			""
		end
	end
end

Format.block :paragraph do
	group          :@contents
	default_syntax :text
	module_eval do
		def process_html
			XML[:p, @text.process]
		end
	end
end

勝手にブロック引数とって DSL っぽく書けるようにした。(検索しにくくなるのであんまりファイルわけたくない。ファイルわけないとなるとインデントして定義の範囲を明確にしたい。)

Ruby. サブクラスでの定数の再定義

class Foo
	AAA   = "aaa"
	@@foo = "aaa"
	@foo  = "aaa"

	def aaa
		"aaa"
	end

	def c
		AAA
	end

	def cv
		@@foo
	end

	def iv
		self.class.instance_variable_get(:@foo)
	end

	def cg
		self.class.const_get(:AAA)
	end

	def m
		aaa
	end
end

class Bar < Foo
	AAA   = "bbb"
	@@foo = "bbb"
	@foo  = "bbb"

	def aaa
		"bbb"
	end
end

puts
p Foo.new.c  #=> "aaa"
p Bar.new.c  #=> "aaa"

puts
p Foo.new.cv #=> "bbb"
p Bar.new.cv #=> "bbb"

puts
p Foo.new.iv #=> "aaa"
p Bar.new.iv #=> "bbb"

puts
p Foo.new.cg #=> "aaa"
p Bar.new.cg #=> "bbb"

puts
p Foo.new.m  #=> "aaa"
p Bar.new.m  #=> "bbb"

なんか勘違いしてた……クラス変数はサブクラスでうわがきしてもスーパークラスに影響はないとおもってた。

RSpec

RSpec つかうときは、同じようなテストも全部コピペしてずらずら書いたほうがよみやすい (謎のデータ構造がならぶよりはコピペのほうがマシ)

ustream

フォントサイズ 33 でやっとよめる……(全画面にしたターミナルをきりぬいて)

2008年 01月 29日

dnbk


ぐぐるたん

Google は順位をほんと変えまくる。翻弄される。あたるサーバによって順位ちがうのかなぁ。一日で特になにもしていなくても変動する。

SoozyCon

もっかい http://www.nicovideo.jp/watch/sm2164173 みた。

モジュール最後に 1; 1; 1; 1; がツボすぎる。作りこまれててすごいいいなぁ。


そういえば POE をみんな ぴーおーいー ってよんでてびっくりした。自分の中では ぽえ だった

個人的には言語が違うとプログラムできないような人材は要らないと思ってるんですが。

サーセンwww

Perl とか Ruby でのプログラミングは、どうにか頑張れば、できるけれど、PHP は、書いていると本当に腹が立ってきて、頑張ることができなくて、無理だ。なのでぼくは言語が変わるとプログラムができなくなる人です。

OSS

オープンソースの面白さ (便利さじゃなくて) を実感するのって、結構時間がかかる気がする。最近やっとわかってきたかもしれない。

2008年 01月 30日

chokan

名前変えたい。なんかいいアイデアないかな

いまやってること/やりたいこと (名前がきまらなくてコミットできない)

  • プラグインシステムを改訂 (ファイル名に依存しないように)
  • オレオレ RICE をやめて Net::IRC (これもオレオレ RICE なんだけど) に
  • RSpec 書きまくる。(プラグインも)

不安だなぁ……考えが纏まらない……

citrus (かいはつこーど)

名前来まんないので、citrus というコードで開発することにした。とかいってそのままこの名前に変えるかもしれないけど…… chokan の branches になってるけどオリジナルコードを殆ど使ってないw

http://svn.coderepos.org/share/lang/ruby/chokan/branches/citrus/

プラグイン機構との一番重要なところと、起動部分はできた。テストは全部 RSpec で、rcov でカバレッジみてる。
99.4% (run の部分のテストをどう書いていいかわからないお)

プラグインのテストをどうするか悩んでる。今のところ、プラグインファイルにそのまま書けるようにしてる。

テストを書きやすい設計ってすなわち疎結合で、いいものになる気がする。


あとどうでもいいけど chokan の kan は柑橘のカンであって、cho は IRC で名前を並べたとき、cho45 と並ぶようにしたからだったと思います。

rcov 楽しい

http://lab.lowreal.net/test/citrus/ (citrus の rcov)

やばい。RSpec との組み合わせが最強だなぁ。めんどくせーっておもって例外のところのテストをかかなかったりするけど、100% をめざすと書かざるをえない。

テストファーストはやってみたりやらなったり>< 慣れない

2008年 01月 31日

はてダ

その場編集つかってたのに設定戻ってしまった。

向日葵 - Syrup16g

すごいうただなぁ…… ちなみに最後のアルバムはまだ買ってない。

日記に文章を書いては消し書いては消し、まとまらない。いうべきではない気がする。(社会的な意味じゃなくて、個人的な意味で、今パブリックにすべきではない感じ)

ミナソコ - BURGER NUDS

やっぱり、この唄をきいて浮かぶ風景は、完璧すぎる。