タグ「個人的メモ」による検索結果 144

Search Form

Bookmarklet: deliciousのブックマークページに飛ぶ

javascript:void(location.href="http://delicious.com/url?url="+location.href);

delicious表示

既出かもしれない。

http://delicious.com/help/bookmarkletsに書いてあった。


コメント一覧のJSONはhttp://feeds.delicious.com/v2/json/url?count=100&url=${url}から取得できるみたいだけど書いてない。

counthttp://delicious.com/help/feedsにあるようにデフォルト15で最大値100。

jsonrssにすればRSS 2.0で取得できる。

JSONだとユーザ名が取れないのでRSS 2.0をみたほうが良さげ。

ginc

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 ({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[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()));

makelink


<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

http://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

http://feedgen.appjet.net/?url=http%3A%2F%2Fmayokara.info%2Fnote%2F&re=%3Ch2+class%3D%22entrytitle+entry-title%22%3E%3Ca%5B%5E%3E%5D%2B%3E%28%5B%5Cs%5CS%5D%2B%3F%29%3C%2Fa%3E%3C%2Fh2%3E%5Cs%2A%3Cdiv+class%3D%22entrybody+entry-content%22%3E%28%5B%5Cs%5CS%5D%2B%3F%29%3C%2Fdiv%3E%28%3F%3D%5Cs%2A%3Cul+class%3D%22entryinfo%22%3E%29&title=1&description=2

こんな感じ。

改行を含む全ての文字[\s\S]や、最小マッチ*?+?、先読み(?=...)を使うのがコツ。


optionalなパラメータは

  • html要素の(xml:)lang属性
  • title要素
  • meta要素(めんどくさいのでcontent属性が後ろに書かれているもののみ)

から補完します。

charsetも元のHTTPヘッダとmeta要素を調べて、見つかれば送信します。

MIME Typeはapplication/rss+xml。

追記

RRRS - ’ellaneous

頂いたパッチ(とほぼ同等のコード)を適用しました。ありがとうございます。

  • DateLast-Modifiedが送られてこなかったとき、エラーになっていたのを修正
  • title、descriptionの自由度向上
    • 1 hoge 2 fuga 3$1hoge$2fuga$3になる(前後のスペースは除去)

コードはこちら。

http://appjet.com/app/971183202/source

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表現

1px透過GIF 39bytes

R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7

data:image/gif;base64,R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7

1px透過PNG 68bytes

iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQI12NgYAAAAAMAASDVlMcAAAAASUVORK5CYII=

data:image/png;base64,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:

JavaScript 1.8 では配列が自動的に Iterator に変換されなくなった? - やんばるもじら

Greasemonkey: tish.user.js

tako3.comからJSONを取得の図

tish.user.js

tinyshell.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そのものを引き渡しても良い。