今日
23:30ぐらいから朝7時ぐらいまで寝てた。ずっと廻り出すセカイ (修正版とそうじゃないのどっちも) をかけっぱで寝てた。未修正版のほうがシガーロスっぽい。
23:30ぐらいから朝7時ぐらいまで寝てた。ずっと廻り出すセカイ (修正版とそうじゃないのどっちも) をかけっぱで寝てた。未修正版のほうがシガーロスっぽい。
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
endrubyforge の 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 についての記述はないっぽいけど、こういうリソースが妥当なのかどうか (実際あるのか) わからない。
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"
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/
atomutil のテスト書くときに (一行たしただけだけど)、はじめてさわったけど、思ったよりよさそうだ (食わず嫌いだった)
とりあえず assert_equal って補完使っても入力するのめんどくさいんだよね……
おなかいたいわけじゃないけどなぜか gerry...
というのを適当にでっちあげてみました (まだ 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 に特に暗号化されずに保存されます。
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.")
http://subtech.g.hatena.ne.jp/antipop/20071121/1195652375 を Ruby + Pit + atomutil とかで書いてみました。
最初は Perl のままアカウント情報のところだけ pit つかうようにしようと思ったのだけど、Pit もづーるがほしくなったりして、つくるなら Perl かかないととかいろいろ考えてたら Ruby で書いてしまっていた。
おつかれさまでした巫女さんが可愛いくて本当によかったですね。

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
女の子みたいな現像 (謎) をしなかったやつ
今日の写美は作者の人が作品の説明をしていたのがおもしろかった (何がおもしろいのかわからない写真だったから、すこし世界観がひろがった気分)。
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
みたいにして、命名規則で依存関係を自動でつくる、みたいなののほうがいいかなぁ……
あーだめだ。これだと引数をわたしにくい……
コピペビリティ重要 (処理がまとまっている)
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 と一緒にレポジトリにいれて管理するようにしました。
昨日のアイデアのまま 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 で内部実行してた)。
ひどすぎるバグだったのでリリースした (リリースするのたのしくなるけど、一日何回もリリースするのってアレですよね……)
なんか技術系のほうの昔の日記のほうが読めないなぁw なんでこんなひどいこと書いてるんだろうって感じで目を背けたくなる……
よびわけにこまったので shipit.rb とよぼう……
をやんないとだけど、ここにこんなふうに書いてる時点でやる気ないよなぁ (今ちょっと 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 の仕様を変えることにした。
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 pageinplace edit の API をたたく。g.hatena もおなじでできる (URL だけかえる)。はてなはサブアカでも更新できるので、スクリプトから更新するときは、専用のサブアカ作ってパスワード設定するほうがすこしだけ安全かも。
RKM ははてな全体で共通みたいなのでてきとうなところからとってきてる。ハイクだと URL にユーザ名が入らなくて手軽っぽい (config に id じゃなくてメールアドレスいれてもいけるとかいう意味で)。
shipit.rb の Step にしようとおもったけど微妙だったのでやめた……(ハイクへの通知だとサブアカでの発言になってしまう)
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);
replace のほうがマシかなぁ。一文字あるだけで違う
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;
}色とか改訂されて使えなくなりそうだ
memo
いまいち使えない感……
XPCOM 叩いたほうがよさそうだ……
Organizer で place: をかきかえても反映されないので、変更したらブックマークをつくりなおす必要があった。
mozStrage たたくしかないのかなぁ。でも自力で open したら壊れそうだ。
新年早々、いろいろと気を引き締めなさいと言われているようなことが (直接的ではないけど)、あって、少し緊張する。
Thunderbird のスレッド時のソート法がどうしても気になりだして拡張を入れたりしたのだけど、結局やりたいのは Gmail みたいな表示だったので、だったら Gmail そのまま使えばいいよなぁという話でした。(今までは IMAP 経由) それと、Thunderbird は Fx ほど userChrome.js を使って拡張する気になれないので、Greasemonkey で拡張できるならそのほうが楽かなぁとかいうのもあります。
公式の Gmail Notifier だとマルチアカウントに対応してないので Fx の拡張をいれてみた。Fx3 b2 にも対応してた。
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"
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ポイントは結局のところ
みたいですね。あと、Perl しか使わない場合でも、$YAML::Syck::ImplicitTyping = 1 で使うときは必ず $YAML::Syck::SingleQuote = 1; も指定しないとデータがこわれてしまうみたいです。
Perl については調べきれてないかもしれないです (Syck 以外でもクオートできるのかな……)。もしかするともっといい方法があったりするのかもしれない……
外部から見える変更 (書くことないときはリファクタリングしてどうなったかだけ) かな
http://subtech.g.hatena.ne.jp/cho45/20080102/1199257680 の Perl 版です。最低限うごくようになったところでコミットして #CodeRepos の方々にお世話になりながらリファクタリングをしました (ありがとうございます)。(Path::Class++) コマンドラインツールは Yappo さんが書いてくれました (Yappo++)。
テストとか一通り書いて 0.01 をリリースしました。が既にあれげなところの修正が入ったので 0.02 をリリースしました。
一通り本家 ShipIt の感じもつかめてよかった。MANIFEST の確認を怠っていたら .svn をふくんでリリースしてしまってめっさあせる……
プロトタイプだけ書いて放置していたら PHP 版が先に! はやい!
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 なのでブックマークレットとかつかって書かないといけないのはめんどい。
ちゃんと使うには
とかやらないといけない。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);
}
};
}))+"()";
p OpenStruct.new(:foo => "bar").foo
p OpenStruct.new("foo" => "bar").fooどっちでもいけて便利ですね @config = OpenStruct.new(config) とかやっとけば自然とどっちにも対応できますね
$ 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 にパスが通っていること前提) のコードをいれました。テストしてないのでうごくかわからないのですが
どうしても見出しの幅が他とあってないのが気になるのでなおした……パターンメーカーって使って作った画像をはじめて使った気がする。なんかいまいちなんだよね……
あと右側にあいてしまう部分をうめたいけどいいアイデアが思い浮ばない。
自分は、些細なきっかけで物事を嫌いになりやすいので (パチンと、スイッチが切りかわるみたいに)、好きでいたいものに接するときは、気をつけるようにしてる。一度切りかわると、元に戻りにくい。
なんか、日記特有の、緊張感みたいなものがない。あんまり馴染める空気じゃない。
WEBrick は素晴しいのですがいかんせん遅いので Mongrel 使って書いてみました。Proxy の実装は WEBrick からパクっています。
1.8.4 でしか動かしてないです。キャッシュ機能はつけるのが若干めんどいのでついてません。あとクッキー関係でちょっとおかしいけど、用途的にあんまり困らないかな。
そういえば小学生のころ、この花の蜜をなめてた。ものによるけど (土による?) 甘かった。
ああ、花の名前が思い出せなかったけどサルビアだ……記憶力がどんどん悪くなるなぁ。twitter の人とか follow しといて誰が誰だかわからなくなったのでいくらか remove した……
私とあなたが知っている「私」の表ってどっかで見たことがあるけどどこだろ。高校のとき図書室でか、あるいは健康科学論の講義かな。
ジョハリの窓 - Wikipedia あーこういうんだ
実際のところ、自分だったら、表現の場は狭めずに、人付き合いを狭めるだろうと思う。
置換プロキシつけたままサブテク日記開いたらこの日記のデザインになって混乱した。ほとんど見た目で判断しているんだなぁ。
flickr で公開されている Creative Commons の写真に「タイトル」をつけて interpretation という題にまとめるというアイデア
ループリストにいれて聴いていたら、なんかよくわからないけど、今唐突にぐっときた……
眠れない……
腰を据えてできることってなんだろう。特に興味があるのは
だけれど、今これらにあんまり手をつけていない、ということは、興味があるだけで、あんまりやる気がないのかもしれない。言語つくりは何度か手をつけてるけどまじでほんとちょー大変だ。パーサー書くのは楽しんだけど、VM つくるところで途方にくれる……
無脳は全文検索エンジン (Hyper Estraier) をそのまま利用してスクリプト言語 (Ruby binding) でかく、みたいなのはやってみたけどいまいちだった。全文検索エンジンそのまま利用するのは、自分で検索のアルゴリズムを考えずにすむぶんすぐ形にできていいと思ったので、そのまま別のアイデアとくみあわせたらうまくいくかもなぁと思ったりした。自分で全文検索エンジン書いてみると発見がありそうだ。
昼ごろから胃がいたくて、一度寝たらなおったとおもったのだけれど、夕食食べたらすごいゲリった
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
BURGER NUDS つけっぱのまま寝たらどうしようもない感じになった。彼らの、今でも続く、ハードボイルドさ、と同時にみえる弱さ、が素敵だ。
昨日撮った写真を現像していない。しよう。
教務課から休学期限手続きの書類がきた (復学・休学・退学の三枚セット。親切)。今回休学すると学生証が変わるらしい (すなわち学籍番号が変わる)。理由かくのが結構へこい。
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);
});
いよいよお金がなさすぎてヤバいんだぜ
使ってみてハマりそうなポイントにチェックをいれて他の人が使っても大丈夫なようにしてる。定数をハードコードしてるのは、Rakefile 側で代入しなおせばいいだけなので (影響が多いのもあって) 変えない。
ひさしぶりに VOCALOID 系のを聴いてまわった。
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 などで「これでいいのか」ということを相談できたり、意見を聴けたりするのは、本当に素晴しい。ただ、いつもおもうのは、そういうのに頼りすぎてはいけないということだ。バランス感覚は、常にバランスを保ち続けることで維持できるはずであるし、距離感は、いつも距離を図っていないとわからない。
さっき http://www5.big.or.jp/~seraph/zero/mbti.cgi をやったら
だった。しばらく INFP だったのが INFJ になった。(でも前にどこでやったのか覚えていない)
[[スイーツ(笑)]] の括弧は全角なのに [[ライフハック(笑)]] は半角なのがなんかうける。
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
実際つかうならハードコードされてるところをましにしたりしないといけないかな。
最近はずっと 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 の基本メソッドを全部実装しないといけないから長くなる……
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.
Mac 版 Picasa がはやくでてほしい……
とかおもいつつ Lightroom を試用してみる。買わないけど
写真現像専用にはいいかもなぁ。でも Photoshop もっているなら 30k はちょっと高い (同じことはできるし) 逆に Photoshop もってなくて写真現像しかやらねーよっていう場合はやすい気もする。
あせる。些細なことで凹みすぎだ。些細ではないかもしれないけど、いやよくわからない。
寝るのがめんどうくさい……眼を閉じたらすぐ眠れて、眼をパチっと開いたらすぐに覚醒するならいいのに……寝よう寝ようと思いながら横になって、起きるときは頭がぼーっとしてしばらくどうしようもない気持ちになる。
うまくいかないなぁ……なにがわるいんだろう……
ゆっくりと、つくったものを消費しながら、忘れていく人になるのだなぁ
灰羽連盟ほんといいなぁ
Linger の IRC gateway を Ruby でかきました。
だけです。
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 にするとよさそうかもしれない。あんまソース綺麗じゃないしなぁ (てきとうに書いたわりにそこそこ安定してる)
なんかうんこみたいなバグがいっぱいあったのでたくさんなおしました。日記書くとバグがみつかる
セッションは同じアカウントでも完全別々にはれる。lig.rb で接続しっぱで Web から見てもきられないし、occupant_id も違う。でも完全に別人として扱われるわけではなく、chatters では重複しないようになってる (よくわからない。occupant_id で判断しているんじゃないのか)
あ、user_id ってのが別にあった。occupant_id は anonymous でも絶対にあるけど、user_id はない。
Y コンビネータが今の僕には理解できない。
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 があるので名前に困ってつけてないだけです (この二つは全然ちがうものです)。
irc ライブラリをかく -> chokan の設計みなおす
同じように、未来の自分に向けて書いている。おれはおれのためにしか日記やコードを書いていない。
面白法人カヤック に来ています。
なんか一昨日までちゃんと「文乃さん やばい」で一位だったのに、今日みたら三位だった。ありえん(笑)
今日は55枚とった
セクション編集ができる 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 っぽく書けるようにした。(検索しにくくなるのであんまりファイルわけたくない。ファイルわけないとなるとインデントして定義の範囲を明確にしたい。)
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 つかうときは、同じようなテストも全部コピペしてずらずら書いたほうがよみやすい (謎のデータ構造がならぶよりはコピペのほうがマシ)
フォントサイズ 33 でやっとよめる……(全画面にしたターミナルをきりぬいて)
Google は順位をほんと変えまくる。翻弄される。あたるサーバによって順位ちがうのかなぁ。一日で特になにもしていなくても変動する。
もっかい http://www.nicovideo.jp/watch/sm2164173 みた。
モジュール最後に 1; 1; 1; 1; がツボすぎる。作りこまれててすごいいいなぁ。
そういえば POE をみんな ぴーおーいー ってよんでてびっくりした。自分の中では ぽえ だった
個人的には言語が違うとプログラムできないような人材は要らないと思ってるんですが。
サーセンwww
Perl とか Ruby でのプログラミングは、どうにか頑張れば、できるけれど、PHP は、書いていると本当に腹が立ってきて、頑張ることができなくて、無理だ。なのでぼくは言語が変わるとプログラムができなくなる人です。
オープンソースの面白さ (便利さじゃなくて) を実感するのって、結構時間がかかる気がする。最近やっとわかってきたかもしれない。
名前変えたい。なんかいいアイデアないかな
いまやってること/やりたいこと (名前がきまらなくてコミットできない)
不安だなぁ……考えが纏まらない……
名前来まんないので、citrus というコードで開発することにした。とかいってそのままこの名前に変えるかもしれないけど…… chokan の branches になってるけどオリジナルコードを殆ど使ってないw
http://svn.coderepos.org/share/lang/ruby/chokan/branches/citrus/
プラグイン機構との一番重要なところと、起動部分はできた。テストは全部 RSpec で、rcov でカバレッジみてる。
99.4% (run の部分のテストをどう書いていいかわからないお)
プラグインのテストをどうするか悩んでる。今のところ、プラグインファイルにそのまま書けるようにしてる。
テストを書きやすい設計ってすなわち疎結合で、いいものになる気がする。
あとどうでもいいけど chokan の kan は柑橘のカンであって、cho は IRC で名前を並べたとき、cho45 と並ぶようにしたからだったと思います。
http://lab.lowreal.net/test/citrus/ (citrus の rcov)
やばい。RSpec との組み合わせが最強だなぁ。めんどくせーっておもって例外のところのテストをかかなかったりするけど、100% をめざすと書かざるをえない。
テストファーストはやってみたりやらなったり>< 慣れない
その場編集つかってたのに設定戻ってしまった。
すごいうただなぁ…… ちなみに最後のアルバムはまだ買ってない。
日記に文章を書いては消し書いては消し、まとまらない。いうべきではない気がする。(社会的な意味じゃなくて、個人的な意味で、今パブリックにすべきではない感じ)
やっぱり、この唄をきいて浮かぶ風景は、完璧すぎる。