オフィシャル側で対応頂いたので、このグリモンの必要性は無くなりました。はてなスター日記
twitter上に、はてなスターを置く為のグリモン「つい☆すた」のサイト、「Twitter: What are you doing?」上でtwitterユーザのアイコンが表示されるようにするグリモン書いた。
2008/01/31
Minibuffer用のはてなブックマークコマンド書いた
Firefoxをshellの様に扱えるグリモン「Minibuffer ? Userscripts.org」で使える、はてなブックマークコマンド「hatena-bookmark」書いた。
Minibufferは、LDRizeと併用すると「pinned-link」や「pinned-node」というルートコマンド(フィルタコマンドではない)が追加される。
例えば、LDRizeでpinを付けたリンクをタブで開くには
この順番になるように、以下のスクリプト入れると、「hatena-bookmark」コマンドが追加される。
LDRizeを入れておくと、ブログ等の記事1つずつにpinが付けられるようになっていて、そのpinを付けたものに対してパイプ形式にコマンドを繋げられる。
例えば、pinをつけたリンクのGoogleキャッシュを開くには
※pinをつけるには「p」を押す。
「hatena-bookmark」の使い方は、何もpinしていない状態で「Alt-x」(ALTキーを押しながらx)を押して
なお
ちなみにソースはこんな感じ。
あ、あと記事とは無関係ですが、今日CodeReposのLDRize-SITEINFO書いときました。
追記1
bookmarkコマンドで、stdinを返すように修正した。
これで
追記2
申し訳ない。objがtypeofでstringとして戻るパターンとobjectとして戻るパターンがあるようです。修正しました。
例えば、LDRizeでpinを付けたリンクをタブで開くには
:pinned-link | open
とすれば良い。ここで注意しなければならないのがグリモンの設定で
- Minibuffer
- LDRize
- ...LDRizeプラグインもしくはMinubufferプラグイン...
この順番になるように、以下のスクリプト入れると、「hatena-bookmark」コマンドが追加される。
LDRizeを入れておくと、ブログ等の記事1つずつにpinが付けられるようになっていて、そのpinを付けたものに対してパイプ形式にコマンドを繋げられる。
例えば、pinをつけたリンクのGoogleキャッシュを開くには
:pinned-link | google-cache | open
とすればよい。※pinをつけるには「p」を押す。
「hatena-bookmark」の使い方は、何もpinしていない状態で「Alt-x」(ALTキーを押しながらx)を押して
:hatena-bookmark
とすると、現在見ているページのはてなブックマーク登録画面が立ち上がる。またpinを付けた状態で
:pinned-link | hatena-bookmark
とすると、pinが指すリンクのブックマーク登録画面が立ち上がる。なお
:pinned-node | hatena-bookmark
では、pinしているHTMLノードの先頭にあるリンクを使ってブックマーク登録画面を表示する。
ちなみにソースはこんな感じ。
// ==UserScript==
// @name Minibuffer Hatena Command
// @namespace Minibuffer.Hatena-Command
// @description add hatena-bookmark command to Minibuffer.
// @include http://*
// @include https://*
// ==/UserScript==
var SCRIPT_VERSION = 'Thu, 15 Nov 2007'
var Minibuffer_Hatena = new function() {
var self = this;
this._run_bookmark = function(u, t) {
var link;
if (t) link = 'http://b.hatena.ne.jp/add?mode=confirm&is_bm=1&title='+escape(t)+'&url='+escape(u);
else link = 'http://b.hatena.ne.jp/add?mode=confirm&is_bm=1&url='+escape(u);
setTimeout(function(){
window.open(link, '_blank', 'width=550,height=600,resizable=1,scrollbars=1');
}, 10);
}
this.bookmark = function ( stdin ) {
if (stdin.length == 0) {
self._run_bookmark(location.href, document.title);
} else {
stdin.forEach(function(obj){
if (typeof obj == 'string' && obj.match(/^https?:.*/)) self._run_bookmark(obj);
else if (typeof obj == 'object') {
try {
var links = obj.getElementsByTagName('a');
for(var n = 0; n < links.length; n++) {
if (links[n].href.match(/^https?:.*/)) {
self._run_bookmark(links[n].href);
break;
}
}
} catch(e) { }
}
});
}
};
this.condition = function() { return true; };
};
if (window.Minibuffer) {
Minibuffer.addCommand({
"hatena-bookmark": Minibuffer_Hatena.bookmark,
});
}
インストール:minibuffer.hatena.user.jsちなみに、ファイル名が「minibuffer.hatena.bookmark.user.js」になっていないのは、いずれ他のコマンドも作って行きたいから...。
あ、あと記事とは無関係ですが、今日CodeReposのLDRize-SITEINFO書いときました。
追記1
bookmarkコマンドで、stdinを返すように修正した。
これで
:pinned-link | hatena-bookmark | clear-pin
とか出来る様になった。追記2
申し訳ない。objがtypeofでstringとして戻るパターンとobjectとして戻るパターンがあるようです。修正しました。
javascriptのArray.popがfunction越しに呼び出せない件
そうなのか...知らなかった。
The Future of JavaScript
例えば
コンテキスト保持しておけば
これってperlなら
pythonなら
rubyなら
luaなら
ちなみにC++なら
つまり、著名な言語で問題が発生しているのはjavascriptだけって事か...
それって...
まずくない?
The Future of JavaScript
var a = [1,2,3]; var a2 = a.pop; var b = a2() は?なんでだろ。 メソッド呼び出し時に正しくコンテキストスイッチしてないって事?
this のコンテキストが変わってるのでエラーになる
例えば
var obj = new(function Clazz() {
var self = this;
self.value = 0;
self.plus = function() { self.value++; };
})();
var func_plus = obj.plus;
func_plus();
alert(obj.value);
なら結果は「1」になるよね?それってもしかして
var obj = new(function Clazz() {
this.value = 0;
this.plus = function() { this.value++; };
})();
var func_plus = obj.plus;
func_plus();
alert(obj.value);
こうなってるって事じゃないの?うむ...それっていいの?コンテキスト保持しておけば
function Clazz() {
var self = this;
self.value = 0;
self.plus = function() { self.value++; };
}
var obj1 = new Clazz();
var obj2 = new Clazz();
var func_plus = obj1.plus;
func_plus();
obj2.plus = func_plus;
obj2.plus();
alert(obj1.value + "," + obj2.value);
こんな事しても、例外出ずに動くよね?obj1.valueがインクリメントされる結果になるけど...これってperlなら
#!/usr/bin/perl
use strict;
use warnings;
package Clazz;
sub new {
my $class = shift;
my $self = { value => 0 };
return bless $self, $class;
}
sub plus {
my $self = shift;
++$self->{value};
1;
}
my $obj1 = Clazz->new;
my $obj2 = Clazz->new;
my $func_plus = *Clazz::plus;
warn "func_plus=".$func_plus."\n";
$func_plus->($obj1);
warn sprintf "obj1->{value}=%d, obj2->{value}=%d\n",
$obj1->{value}, $obj2->{value};
$obj2->{plus} = $func_plus;
$obj2->plus();
warn sprintf "obj1->{value}=%d, obj2->{value}=%d\n",
$obj1->{value}, $obj2->{value};
こんなサンプルかな。実行結果は
func_plus=*Clazz::plus
obj1->{value}=1, obj2->{value}=0
obj1->{value}=1, obj2->{value}=1
サブルーチンにはselfを渡すのはインスタンス自身になるから問題無く動くね。javascriptのようにfunctionの参照自身がインスタンス参照を保持しちゃってる訳じゃなので問題は発生しないか...pythonなら
class Clazz:
def __init__(self):
self.value = 0
def plus(self):
self.value = self.value + 1
obj1 = Clazz()
obj2 = Clazz()
func_plus = obj1.plus
print "func_plus=%s" % func_plus
func_plus()
print "obj1.value=%d, obj2.value=%d" % (obj1.value, obj2.value)
obj2.plus = func_plus
obj2.plus()
print "obj1.value=%d, obj2.value=%d" % (obj1.value, obj2.value)
こんなサンプルかな?実行結果は
func_plus=<bound method Clazz.plus of <__main__.Clazz instance at 0xb7ef828c>>
obj1.value=1, obj2.value=0
obj1.value=2, obj2.value=0
pythonの場合は関数の参照自身がインスタンスの参照も保持しているから、いくらobj2.plusを上書きしてもobj2.valueが更新される訳じゃない。rubyなら
class Clazz
def initialize() @value = 0 end
def plus() @value += 1 end
attr_accessor :value
end
obj1 = Clazz::new
obj2 = Clazz::new
func_plus = Clazz.instance_method :plus
puts "func_plus=%s" % func_plus
func_plus.bind(obj1).call
printf("obj1.value=%d, obj2.value=%d\n", obj1.value, obj2.value)
func_plus.bind(obj2).call
printf("obj1.value=%d, obj2.value=%d\n", obj1.value, obj2.value)
こんな感じ?実行結果は
func_plus=#<UnboundMethod: Clazz#plus>
obj1.value=1, obj2.value=0
obj1.value=1, obj2.value=1
rubyの場合はperlぽいけど、UnboundMethodの呼び出しはまずインスタンスをbindしてから呼ぶ事になるので問題は発生しない。ちなみにobj1.plusを取得してobj2.plusに代入できないかやってみたけど、私の力足らずなのか出来なかった。luaなら
function Clazz()
return {
value = 0,
plus = function(self)
self.value = self.value + 1
end
}
end
local obj1 = Clazz()
local obj2 = Clazz()
local func_plus = obj1.plus
print("func_plus", func_plus)
func_plus(obj1)
func_plus(obj2)
print("obj1.value=", obj1.value)
print("obj2.value=", obj2.value)
こんな感じ?実行結果は
func_plus function: 0x8f36270
obj1.value= 1
obj2.value= 1
luaも結局selfを渡す事になるので、問題は派生しない。
ちなみにC++なら
#include <stdio.h>
class Clazz {
private:
int _value;
public:
Clazz() : _value(0) {}
void plus() { _value++; }
int value() { return _value; }
};
int
main(int argc, char* argv[])
{
Clazz* obj1 = new Clazz();
Clazz* obj2 = new Clazz();
typedef void (Clazz::*def_func_plus)();
def_func_plus func_plus = &Clazz::plus;
printf("func_plus=%p\n", func_plus);
(obj1->*func_plus)();
printf("obj1->value=%d, obj2->value=%d\n",
obj1->value(), obj2->value());
// obj2->plus = func_plus; # compile error
return 0;
}
こんな感じ?実行結果は
func_plus=0x8048574
obj1->value=1, obj2->value=0
まぁ、無茶すればobj2->plusも置き換えられない事はないけど、結果は見えてるからいいでしょ...つまり、著名な言語で問題が発生しているのはjavascriptだけって事か...
それって...
まずくない?

