✖
gerry++
gerry++
一年ぶりぐらいにリリース http://github.com/cho45/jsdeferred/tree/release-0.3.0
を API を変えてとりこんだものです。コールバックを引数にとる任意の関数を Deferred を返す関数に変更できます。
var timeout = Deferred.connect(setTimeout, { target: window, ok: 0 });
timeout(1).next(function () {
alert('after 1 sec');
});これもセコンさんが実装していたやつをだいたいそのまんま入れたものです。
Deferred.retry(3, function () {
return http.get(...);
}, { wait: 1 }).
next(function (res) {
res // 成功したらこっち
}).
error(function (e) {
e // 3回リトライしてもダメなときはエラー
});これもセコンさんが(ry
Deferred 処理中に発生した例外を全部キャッチすることができます。デバッグに便利です。デフォルトでは undefined なので、適当な関数をつっこんでください。この関数によってエラーをキャンセルしたりとかはできません。
Deferred.onerror = function (e) { if (window.console) console.log(e) };これもセ(r
$.fn.deferred が追加で定義されるようになり、コールバックをとる任意の jQuery メソッドを Deferred を使うようにできます。今までは $.ajax 系のみが Deferred を返すように jQuery をいじっていましたが、このメソッドは汎用性が高くなっています。
var click = $('div').deferred('click');
loop(10, function (i) {
console.log(i);
return click;
});とかやるとステップ実行が実装できそうですね (試してない)
セ(rさんが作ってたやつです。http://subtech.g.hatena.ne.jp/secondlife/20091013/1255435673
Android では select をクリックすると選択肢がいい感じにポップアップしてくれ見た目を大幅に変えることができそれによりアクションを選択するような場面で場所をとらずに有効に使うことができる以下例
フォーカス (オレンジの outline) がついているのが select である。クリックすると
というふうにポップアップされる。ここで、したい操作を選ぶ、という感じになる。もちろん選択肢が増えても適切にスクロールバーがでるため問題ない。
上の例に関係する部分の CSS と JS をぬきだす。ようは onchange イベントを監視しているだけでポイントというほどのところではないけど selectedIndex は代入できセレクトされているものを変更できるので戻しているところか
form select.post {
position: absolute;
top: 0;
right: 5px;
width: 25px;
height: 24px;
margin: 7px 0;;
padding: 0 5px;
outline: none;
border: 1px solid #000;
background: #999;
color: #fff;
text-align: center;
-webkit-appearance: none;
}new function PostOperations () {
var define = {
Post : function (form) {
form.submit();
},
Location : function (form, input) {
// do
}
};
var form = document.getElementById("input");
if (form) {
var input = form.querySelector("input[name=msg]");
var select = document.querySelector("select.post");
select.addEventListener("change", function (e) {
var fun = define[select.value];
try {
if (fun) fun(form, input);
} catch (e) { alert(e) }
select.selectedIndex = 0;
}, false);
}
};
腹痛ではないが下痢ってる。アルコールのせいかな
net-irc を gemcutter にうつしてリリースした http://gemcutter.org/gems/net-irc 。RubyForge からの migration が
gem migrate net-irc
だけでできて感動した。単に RubyForge から gem もってきて push しているだけっぽいけど
でもって、net-irc の Rakefile を修正し、リリース
Rake::ShipitTask.new do |s|
s.ChangeVersion "lib/net/irc.rb", "VERSION"
s.Commit
s.Task :clean, :package, :upload_doc
s.Step.new {
}.and {
system("gem", "push", "pkg/net-irc-#{VERS}.gem")
}
s.Tag
s.Twitter
endshipit.rb に gemcutter のステップを定義してないので手動実行させてる。shipit.rb は git に対応しているので (いつのまに! っておもったら自分でやってた……)、元 (svn) のタスク定義からそんなに変わってはいない。ただし push まではしないので、自分で git push --tags, git push とかやる必要がある。ステップ定義すればいいんだけど、ぼくは確認してから push したいので定義してない。
gemcutter 側の Links とかに表示されているやつは gemspec にデータになっている。ちょっと残念なのは、RDoc のホストはやってくれないところだ。正直 gemcutter の説明だけで「この gem は使えそうだ」という判断はできない。CPAN みたいになるといいなぁ
module Levenshtein
def levenshtein(a, b)
if Inline::USABLE
Inline.levenshtein(a, b)
else
PureRuby.levenshtein(a, b)
end
end
module PureRuby
def levenshtein(a, b)
case
when a.empty?
b.length
when b.empty?
a.length
else
d = Array.new(a.length + 1) { |s|
Array.new(b.length + 1, 0)
}
(0..a.length).each do |i|
d[i][0] = i
end
(0..b.length).each do |j|
d[0][j] = j
end
(1..a.length).each do |i|
(1..b.length).each do |j|
cost = (a[i - 1] == b[j - 1]) ? 0 : 1
d[i][j] = [
d[i-1][j ] + 1,
d[i ][j-1] + 1,
d[i-1][j-1] + cost
].min
end
end
d[a.length][b.length]
end
end
module_function :levenshtein
end
module Inline
begin
require "rubygems"
require "inline" # sudo gem install RubyInline
inline do |builder|
builder.c <<-'EOS'
VALUE levenshtein (VALUE array1, VALUE array2) {
VALUE ret;
long len1 = RARRAY(array1)->len;
long len2 = RARRAY(array2)->len;
long i, j;
long** d = ALLOC_N(long*, len1 + 1);
for (i = 0; i <= len1; i++) {
d[i] = ALLOC_N(long, len2 + 1);
memset(d[i], 0, sizeof(d[i]));
}
for (i = 1; i <= len1; i++) d[i][0] = i;
for (j = 1; j <= len2; j++) d[0][j] = j;
for (i = 1; i <= len1; ++i) {
for (j = 1; j <= len2; ++j) {
int del = d[i-1][j ] + 1;
int ins = d[i ][j-1] + 1;
int sub = d[i-1][j-1] + (
rb_equal(
RARRAY(array1)->ptr[i-1],
RARRAY(array2)->ptr[j-1]
) ? 0 : 1
);
d[i][j] =
(del <= ins && del <= sub) ? del:
(ins <= del && ins <= sub) ? ins:
sub;
}
}
ret = LONG2FIX(d[len1][len2]);
for (i = 0; i < len1; i++) free(d[i]);
free(d);
return ret;
}
EOS
end
module_function :levenshtein
USABLE = true
rescue LoadError
USABLE = false
end
end
end
require 'rubygems'
require 'spec'
[Levenshtein::Inline, Levenshtein::PureRuby].each do |m|
describe m do
it "should return correct levenshtein distance" do
[
["kitten", "sitting", 3],
["foo", "foo", 0],
["", "", 0],
["foO", "foo", 1],
["", "foo", 3],
].each do |a, b, expected|
m.levenshtein(a.split(//), b.split(//)).should == expected
m.levenshtein(b.split(//), a.split(//)).should == expected
end
end
end
end
Spec::Runner.run
require "benchmark"
Benchmark.bm(10) do |x|
n = 10000
x.report("inline") do
n.times {
Levenshtein::Inline.levenshtein("kitten".split(//), "sitting".split(//))
}
end if Levenshtein::Inline::USABLE
x.report("pureruby") do
n.times {
Levenshtein::PureRuby.levenshtein("kitten".split(//), "sitting".split(//))
}
end
end
なんか度々使うたびに移植している気がするのでメモ
結構 Ruby でやると遅いので RubyInline でも書いてみた。
ruby 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0]
user system total real
inline 0.330000 0.010000 0.340000 ( 0.346537)
pureruby 2.500000 0.020000 2.520000 ( 2.596968)1.9 にすれば pureruby でも 1.8 の pureruby の倍ぐらいにはなる。
割とちょこちょこ触ることが多く、svn だと不便なので、http://github.com/cho45/net-irc に移動した
でもって要望があって気がむいたので 2ig.rb というものを作ってみた。
ruby example/2ig.rb --debug
で起動する
実況スレみるにはいいかもしれない。(実況系の板でしか試してないのでほかの板だとへんかも)
Android には Gears が入っていて、gears の geolocation API が使えることは使えるのだけど、GPSをちゃんと使う方法がなかなかわからなかったのでメモ (素朴に使うと WiFi + IP アドレス?しか使わないっぽくて、とれないことが多い)
var geo = navigator.geolocation || google.gears.factory.create('beta.geolocation');
geo.getCurrentPosition(
function (pos) {
alert([pos.coords.latitude, pos.coords.longitude].join(','));
},
function (e) {
alert(e.message);
},
{
enableHighAccuracy: true
}
);enableHighAccuracy が true じゃないと GPS 情報を使わないようだ。このままだと Google の Geoloation API をまだ叩きにいく。さらに gearsLocationProviderUrls: [] とか指定すれば、純粋にGPSだけの情報がとれるようだ。
{
enableHighAccuracy: true,
gearsLocationProviderUrls: []
}ただ、なんか GPS のタイムアウト時間が短いので、前もって別のアプリケーションで GPS fix させてからじゃないとダメな気がする。要検証。watchPosition でとれるまで待つという方法もあるかもしれない
追加検証してみたけど、ちゃんと座標を取得したいなら、watchPosition でとれるまで待って、clearWatch するのがよさそう (キャンセルボタンもつけて)。
watchPosition ならとれるまで試行できる。
gearsLocationProviderUrls: [] を指定すると Chrome でエラーがでるようになったようだ。なのでつけないほいがいい、ないしブラウザ判定を入れる必要がある
todo: ブックマークレットの token 処理についてあとで書く