- < Newer
- Older >
Bookmarklet: deliciousのブックマークページに飛ぶ
javascript:void(location.href="http://delicious.com/url?url="+location.href);
既出かもしれない。
http://delicious.com/help/bookmarkletsに書いてあった。
コメント一覧のJSONはhttp://feeds.delicious.com/v2/json/url?count=100&url=${url}から取得できるみたいだけど書いてない。
countはhttp://delicious.com/help/feedsにあるようにデフォルト15で最大値100。
jsonをrssにすればRSS 2.0で取得できる。
JSONだとユーザ名が取れないのでRSS 2.0をみたほうが良さげ。
ginc
Google Ajax Search APIでインクリメンタル検索。
上部の検索ボックスに入力したあと500msで検索します。
IE、Opera9.2では動きません。
まあ、ただインクリメンタル検索を作ってみたかっただけ……
Bookmarklet: HTMLエスケープするリンク(+引用)生成
javascript:(function(l,t,s){var h=function(s){return s.replace(/[&<>"']/g,function(m){return ({"&":"&","<":"<",">":">",'"':""","'":"'"})[m];});},r='<a href="'+h(l)+'">'+h(t)+'</a>'+(s?'<blockquote cite="'+h(l)+'" title="'+h(t)+'"><p>'+h(s).replace(/(\r\n|\r|\n)+/g,'<br>')+'</p></blockquote>':'');prompt(r,r);})(location.href,document.title,String(getSelection()));
<a href="${url}">${title}</a><blockquote cite="${url}" title="${title}"><p>${selection}</p></blockquote>
こんな感じのHTMLタグを作るブックマークレット(選択範囲が空ならa要素のみ)。
文字数的にもwindow.getSelection的にも多分Firefox限定。
各文字列をHTMLエスケープするところがポイント。
Copy URL+でもできるっぽいけど、なんかもうめんどくさいのでブックマークレットにした。
blockquote要素の内容モデルは
- HTML 4.01 Strict
(%block;|SCRIPT)+- HTML 4.01 Transitional
(%flow;)*- HTML 5(ドラフト)
- Flow content
- XHTML 1.0 Strict
%Block;- XHTML 1.0 Transitional
%Flow;- XHTML 1.1
(Heading | Block | List)*- XHTML 2.0(ドラフト)
(PCDATA | Text | Heading | Structural | List)*
とかいう感じになっているらしいので、p要素つき。
feedgen.appjet.net
URLと正規表現からRSS 2.0を作るサービス。
たとえばこのブログなら(フィードあるから意味ないけど)
- url
- http://mayokara.info/note/
- re
- <h2 class="entrytitle entry-title"><a[^>]+>([\s\S]+?)</a></h2>\s*<div class="entrybody entry-content">([\s\S]+?)</div>(?=\s*<ul class="entryinfo">)
- title
- 1
- description
- 2
で
こんな感じ。
改行を含む全ての文字[\s\S]や、最小マッチ*?・+?、先読み(?=...)を使うのがコツ。
optionalなパラメータは
- html要素の(xml:)lang属性
- title要素
- meta要素(めんどくさいのでcontent属性が後ろに書かれているもののみ)
から補完します。
charsetも元のHTTPヘッダとmeta要素を調べて、見つかれば送信します。
MIME Typeはapplication/rss+xml。
追記
頂いたパッチ(とほぼ同等のコード)を適用しました。ありがとうございます。
- Date、Last-Modifiedが送られてこなかったとき、エラーになっていたのを修正
- title、descriptionの自由度向上
- 1 hoge 2 fuga 3が$1hoge$2fuga$3になる(前後のスペースは除去)
コードはこちら。
JavaScript: ビット反転とString#indexOf
if(~block.innerHTML.indexOf(this._key))
return;
hatebu - ’ellaneous
これは使える。
// 含むとき
if (~str.indexOf("http://")) {}
// 含まないとき
if (!~str.indexOf("http://")) {}
+1だと後者に括弧が1組増えるとか、含む含まないの判定なのに+1?みたいな違和感があるけど、これだとけっこうすっきりする。
慣れがいるかもだけど。
1px透過GIF・PNGの最小base64表現
透過GIF 1px・Base64 - 8時40分が超えられない - subtech
縮めてみた。多分最小。
1px透過GIF 39bytes
R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7
data:image/gif;base64,R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7
1px透過PNG 68bytes
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQI12NgYAAAAAMAASDVlMcAAAAASUVORK5CYII=
使用例
#!/usr/bin/perl
use strict;
use warnings;
use CGI qw/:cgi/;
use MIME::Base64 qw(decode_base64);
print header('image/gif');
print decode_base64('R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7');
exit;
とか
<?php
header('Content-Type: image/gif');
echo base64_decode('R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7');
exit;
?>
とか。
文字列化
Array.map(atob("R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7"), function(v){ return "\\x"+("0"+v.charCodeAt(0).toString(16)).slice(-2).toUpperCase(); }).join("");
// -> "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x60\x00\x00\x21\xF9\x04\x01\x0A\x00\xFF\x00\x2C\x00\x00\x00\x00\x01\x00\x01\x00\x00\x08\x04\x00\xFF\x05\x04\x00\x3B"
Array.map(atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQI12NgYAAAAAMAASDVlMcAAAAASUVORK5CYII="), function(v){ return "\\x"+("0"+v.charCodeAt(0).toString(16)).slice(-2).toUpperCase(); }).join("");
// -> "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x01\x00\x00\x00\x01\x08\x04\x00\x00\x00\xB5\x1C\x0C\x02\x00\x00\x00\x0B\x49\x44\x41\x54\x08\xD7\x63\x60\x60\x00\x00\x00\x03\x00\x01\x20\xD5\x94\xC7\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"
こっちはそのままprint/echoすればOK。
JavaScript: Iterator関数をhasOwnProperty代わりに使う
いちいちhasOwnPropertyを使わなくてよくする(ジェネレータの使いかた) - 素人がプログラミングを勉強するブログ
多分Firefox2/3限定。JavaScript1.7相当。
Iterator関数を噛ませる方法もあります。
Object.prototype.extend = function(){};
var o = {a:1,b:2,c:3};
for (var i in o) console.log(i);
/* ->
a
b
c
extend
*/
for (var i in Iterator(o)) console.log(i);
/* ->
["a", 1]
["b", 2]
["c", 3]
*/
for each (var i in Iterator(o)) console.log(i);
/* ->
["a", 1]
["b", 2]
["c", 3]
*/
こんな具合になってるので
for (var [i,v] in Iterator(o)) console.log(i); /* -> a b c */ for (var [i,v] in Iterator(o)) console.log(v); /* -> 1 2 3 */ [p[0] for (p in Iterator(o))] // -> ["a", "b", "c"] keys [p[1] for (p in Iterator(o))] // -> [1, 2, 3] values
とか。
微妙に形が変わるのが微妙といえば微妙。
yieldもletも使ってないので、Firefox2のFirebugコンソールでも使えるあたりが強み。
あとArrayでも順序が保証されている(はず)なのでbreakの効くforEachとしても使える。
関連リソース
Iterators and Generators - MDC
One advantage of using Iterator() to access the contents of an object is that custom properties that have been added to Object.prototype will not be included in the sequence.
Iterator() can be used with arrays as well:
Greasemonkey: tish.user.js
注意
- Minibuffer(+LDRize)との併用不可
- ショートカットキーが競合
- &にしようかと思ったけどSHIFT同時押しが使いづらいのでやめた
- コマンドの移植度が微妙
- 実装したもの:cat cd clear cut date echo exit expr find go google grep hatena head inspect jot logout ls maketoc open parse printf prompt pwd rm save sed seq settimer sort tac tail tee tr uniq up wc wget xargs
- seqが自然数でしか使えなかったり、sedがエディタになってなかったり、いろいろ
起動方法など
:かALT+xで起動。
clearコマンドもしくはCTRL+Lでクリア。
TAB2回で候補表示。候補が1つだけのときはTAB1回で補完。
ファイルシステムもどき
$ pwd http://mayokara.info/note/ $ cat links|head > outfile $ cat outfile http://mayokara.info/note/ http://mayokara.info/note/1 http://mayokara.info/note/view/325 http://mayokara.info/note/view/257 http://mayokara.info/note/search/tag/個人的メモ http://mayokara.info/note/search/tag/JavaScript http://mayokara.info/ http://mayokara.info/note/view/325 http://mayokara.info/note/view/325#comment http://mayokara.info/note/view/325#trackback $ cat feeds http://mayokara.info/note/rss2 $ cat //h2/a/@href http://mayokara.info/note/view/325 http://mayokara.info/note/view/324 http://mayokara.info/note/view/323 http://mayokara.info/note/view/322 http://mayokara.info/note/view/321 http://mayokara.info/note/view/320 http://mayokara.info/note/view/319 http://mayokara.info/note/view/318 http://mayokara.info/note/view/317 http://mayokara.info/note/view/316
text,links,images,stext,slinks,simages,feeds,next,prevなどは読み込み専用で、現在のページ/選択範囲に対するさまざまな情報を返す。
スラッシュを含む指定はXPathとみなされる。
書き出したファイルはコマンド履歴とは異なり、そのタブを開いている間しか参照できない。
wget & parse
$ cat feeds http://mayokara.info/note/rss2 $ cat feeds|wget -i -|parse //item/link wget: waiting for response... http://mayokara.info/note/rss2 wget: HTTP/1.x 200 OK wget: Date: Sat, 23 Aug 2008 11:38:15 GMT wget: Server: Apache wget: Last-Modified: Sat, 23 Aug 2008 11:33:34 GMT wget: Content-Type: text/xml;charset=UTF-8 wget: Content-Encoding: gzip wget: Content-Length: 13016 http://mayokara.info/note/view/325 http://mayokara.info/note/view/324 http://mayokara.info/note/view/323 http://mayokara.info/note/view/322 http://mayokara.info/note/view/321 http://mayokara.info/note/view/320 http://mayokara.info/note/view/319 http://mayokara.info/note/view/318 http://mayokara.info/note/view/317 http://mayokara.info/note/view/316 http://mayokara.info/note/view/315 http://mayokara.info/note/view/314 http://mayokara.info/note/view/313 http://mayokara.info/note/view/312 http://mayokara.info/note/view/311
wgetでresponseTextを取得し、parseでXPathを用いて抽出。
wget -i - -l3とすれば、標準入力の3行目を読み込む。
parse -jで入力をJSONとみなし、DOMツリーに変換する。
tako3.comからデータを取得
$ echo http://tako3.com/json/likely/ `pwd`|tr -d " "|wget -i -|parse -j //jsonarray|tee tako3|cat -n
wget: waiting for response... http://tako3.com/json/likely/http://mayokara.info/note/
wget: HTTP/1.x 200 OK
wget: Date: Sat, 23 Aug 2008 11:43:25 GMT
wget: Server: Apache
wget: Content-Type: text/plain
wget: Transfer-Encoding: chunked
1 http://mayokara.info/blog/
2 http://mayokara.info/
3 http://d.hatena.ne.jp/mayokara384/
4 http://mayokara.info/note/
$ open tako3 -l3
現在のロケーションに関する情報をtako3.comから取得する。
番号を振る前のデータをtako3というファイルにtee。
open tako3 -l3で3行目を開く。
echo ...|tr -d " "の代わりにprintf "%s%s" http://tako3.com/json/likely/ `pwd`でも可。
しょぼいカレンダーから直近の番組データを取得
$ wget "http://cal.syoboi.jp/rss.php?titlefmt=$(StTime) $(ChName) $(Title)"|parse //x:item/x:title|head wget: waiting for response... http://cal.syoboi.jp/rss.php?titlefmt=$(StTime)%20$(ChName)%20$(Title) wget: HTTP/1.x 200 OK wget: Date: Sat, 23 Aug 2008 11:44:53 GMT wget: Server: Apache/2.2.3 (Unix) PHP/5.2.5 wget: X-Powered-By: PHP/5.2.5 wget: Cache-Control: no-cache, must-revalidate wget: Expires: Mon, 26 Jul 1997 05:00:00 GMT wget: Content-Type: text/xml; charset=UTF-8 wget: Transfer-Encoding: chunked 08/23 21:00 文化放送(1134) A&G超RADIO SHOW~アニスパ!~ 08/23 22:30 TOKYO MX 鉄腕バーディー DECODE 08/23 22:30 キッズステーション NARUTO -ナルト- 疾風伝 08/23 23:00 BS11デジタル 鉄腕バーディー DECODE 08/23 23:00 文化放送(1134) A&Gメディアステーション こむちゃっとカウントダウン 08/23 23:30 BS11デジタル ウルトラヴァイオレット コード044 08/24 00:00 tvk アニメTV 08/24 00:00 BS11デジタル 真ゲッターロボ 世界最後の日 08/24 00:30 tvk 薬師寺涼子の怪奇事件簿 08/24 01:00 tvk 狂乱家族日記
RSS1.0ではデフォルト名前空間があるのでXPathにx:が必要。
Twitterの「フォロー中」にリストされているユーザIDを取得
$ pwd
http://twitter.com/XXXXXX
$ inspect
inspect: 'id("friends")/span[@class="vcard"][1]/a[@class="url"][1]'
$ cat id("friends")//a/@href|cut -d / -f 4
XXXXXX
XXXXXX
XXXXXX
...
inspectでXPathを調べる。左/右クリックで終了。
@href、@srcはAbsolute URLに変換して返される(場当たり的対応)。
外部ファイルによる操作
// ==UserScript==
// @name dot_tishrc
// @namespace http://mayokara.info/
// @description .tishrc
// @include http://*
// ==/UserScript==
(function(){
var Shell = window.Tish;
if (!Shell) return;
Shell.addAlias('tako3', 'printf "%s%s" http://tako3.com/json/likely/ `pwd`|wget -i -|parse -j //jsonarray|tee tako3|cat -n');
Shell.addCommand("hitori-goto", function(STDIN, ARGV, $0){
if (ARGV.length > 0) {
var callback = function(res){
Shell.println($0 + ": " + res.status + " " + res.statusText);
};
GM_xmlhttpRequest({
method: "POST",
url: "http://hitori-goto.appspot.com/say",
data: "comment=" + encodeURIComponent(ARGV.join(" ")),
headers: { "Content-Type": "application/x-www-form-urlencoded" },
onload: callback,
onerror: callback,
});
Shell.println($0 + ": waiting for response...");
} else {
return Shell.exec("wget http://hitori-goto.appspot.com/rss2|parse //item/title", "");
}
});
})();
エイリアスやコマンドを追加できる。
cd、go/open
cdは引数のURLを開く。go/openは標準入力あるいはファイル内のURLを開く。
googleとかhatenaとか
$ google --code printf http://www.google.com/codesearch?q=printf $ hatena id:mayokara384 http://d.hatena.ne.jp/mayokara384/ $ hatena b:id:mayokara384 http://b.hatena.ne.jp/mayokara384/
URLを作って返すだけ。
JavaScript: defer関数でいろいろ
JavaScript: 普通に同期処理 - mayokara note
var defer = function(/* f1, f2, ... */){
var self = this, fn = Array.prototype.slice.call(arguments);
(function(/* arg2, arg3, ... */){
var args = Array.prototype.slice.call(arguments);
(fn.shift()).apply(self, [arguments.callee].concat(args));
})();
};
この関数の説明をきちんと書いてなかったので補足。
bind
deferのthisが、引数に与えた関数すべてのthisになる。
defer.call(this, F1, F2, F3);
のように呼ぶことで、F1、F2、F3すべてにbind(this)(Prototype.js)するのと同じ効果が得られる。
wait(あるいはsleep、pause)
1秒のwaitを置く例。
defer(function(next){
alert("1000ms wait");
window.setTimeout(function(){ next("finished"); }, 1000);
}, function(next, str){
alert(str); // -> (alert "finished")
});
deferもnextも、いくつでも引数を取れる。
nextに与えた第n引数は次の関数の第n+1引数になる。
第1引数はnext(次の関数を呼ぶ関数)で固定。
各関数の返り値は意味を持たない。defer自身も値を返さない。
setTimeoutの代わりに(GM_)XMLHttpRequestを入れれば、onloadが呼ばれるまで次の関数の実行を遅延できる。
loop
defer(function loop(next, i){
i = i || 0;
if (!(i < 5)) return next();
console.log("count " + i);
window.setTimeout(function(){ loop(next, i+1); }, 1000);
}, function(next){
console.log("5 times loop finished");
});
count 0 count 1 count 2 count 3 count 4 5 times loop finished
nextをきちんと引き継げばloopもできる。
setTimeoutに与えた関数の中ではarguments.calleeが使えないので、ループさせる関数にloopという名前をつけ、それを使う。
前述のdefer.callでthisをbindしている場合は、それに合わせてloopにthisをセットする必要がある。
defer(function(next){
next(0);
}, function loop(next, i){
if (!(i < 5)) return next();
console.log("count " + i);
window.setTimeout(function(){ loop(next, i+1); }, 1000);
}, function(next){
console.log("5 times loop finished");
});
毎回i = i || 0;を実行するのが無駄に感じる場合はこうする。
同様にして、特定の条件を満たすまで次の関数の実行を引き伸ばしたりできる。
parallel
defer(function(next){
var obj = {},
stock = function(key, value){
obj[key] = value;
// 全部揃ったらnextを呼ぶ
if (obj.a && obj.b && obj.c) next(obj.a, obj.b, obj.c);
};
window.setTimeout(function(){ stock("a", "AAAAA"); }, 3000);
window.setTimeout(function(){ stock("b", "BBBBB"); }, 2000);
window.setTimeout(function(){ stock("c", "CCCCC"); }, 5000);
}, function(next, a, b, c){
alert(a + b + c); // (alert "AAAAABBBBBCCCCC")
});
setTimeoutの代わりに、(GM_)XMLHttpRequestなどが入る。
objそのものを引き渡しても良い。
- < Newer
- Older >
