2007/12/26

はてな
Powered by Vim 会社でちらりと覗いたデスクトップにvimを見つけました。少しずつですが何故か最近vimユーザが増えている気がしています。
vimは開発の場で見かけるとカッコよく映りますね。vimユーザでない方から見ると「何だか分かんない内にソースコードが出来上がって行く」と神懸り的な物に見えるようです。
今日はこれまでもvimを使って来たけどなかなか上達しない方、またはこれからvimを覚えようとされているvimビギナーの方に送る、vimの使い方を上達させる5つのオキテ。

キーボードは見るな

まずは基本。要はブラインドタッチしろという意味ですが、なぜvimのオキテなのかというと...
vimは頭で考えるテキストエディタです。ブラインドタッチが出来ていないと、vimに命令を与える際に思考を止めてしまい学習出来なくなります。以下のオキテをブラインドタッチよりも先に学習してしまう事は、ある意味無駄な学習ともなり得ます。

マウスを触るな

vimに限らずU*IX系のテキストエディタでは、マウスを使わず全ての編集が出来る様になっています。
マウスを探す事で思考を止めてしまい、せっかく思いついたかもしれない素晴らしいアイデアを自ら消し去ってしまうかも知れません。
海外の方がvimを触っている動画を幾らか見たことがありますが、彼らは常に喋るようにタイプしコタツの上にあるテレビのチャンネルを探す様な感覚でテキストを検索しています。
vimを上達させる為には見たかったテレビ番組の内容を喋りながらもチャンネルを変えられる...くらいの当たり前さをテキスト編集スキルとして身に着けなければなりません。

脳内で英文を作れ

vimは基本的にカウント、モーション、オブジェクトという3つの要素を用いてvimに命令することで編集を行います。
例えば行を3行消すのに、SHIFTキーを押しながら3回矢印キーを押してDELキーを押す...という通常のテキストエディタとは違い、「消す 3 下」と言った少し英語に似た脳内文章を自分で表現しvimに命令しなくてはなりません。この脳内文章を如何に効率良く作れるかがvim上達への近道となるのです。
現在のカーソル位置続く単語3つを消して別の物に置き換えたい場合、vim使いならば脳内で「変える 3 単語」という文章が出来上がり「c3w」とタイプされるのです。

短いショートカットキーを知れ

良く出来たテキストエディタでは、良く登場する入力方法を予め決められたキーボードショートカットとして割り当てられています。
例えばプログラムのソースコードを編集中に、カーソルがある次の行から新たな行として入力を開始したい場合、通常のテキストエディタならば<End>を押して行末まで移動し<Enter>を押して入力を開始しなければなりませんが、vimだとノーマルモードから「o」だけ。
この辺りの気配りさが如何にもコード書き専用エディタと言われる由縁なのかもしれません。

人のテクニックを盗め

これはテキストエディタに限らず、何にでも言える話ですがオープンソース界隈では自らの設定ファイルまでも公開したがる人がワンサカいます。
まぁ私もその一人ですが...
vimは一人で「:help」から勉強するには多すぎる程のノウハウが詰まったテキストエディタです。自分で思い付かなかった素晴らしいテクニックは、ありがたくら盗んでしまいましょう。

vimはどれ程使い込んでも満足する事が出来ないテキストエディタです。
どんなに上達しても時に人の設定ファイルや編集方法に驚かされたりします。
頭で考えるテキストエディタだからこそ、人それぞれの編集方法が生まれるのでしょうね。
vimを使い始めてみようと思われている方、このどっぷりと深い世界にのめり込んで見ませんか?

2007/12/21

はてな
コメント欄まだやってる...
佐藤秀の徒然\{?。?}/ワカリマシェン:小飼弾氏が赤木智弘氏を嗤える本当の理由
日本人にとってソフトウェアが日本語で使えるかどうかは、そのソフトウェア自身の価値を左右する尺度であり、商用ソフトウェアならば直接マーケティングにも影響する。
例えばソフトウェア自身でなくとも、ダウンロードページやチュートリアルが英語というだけでダウンロードを辞めてしまう事もある。
大手企業では日本法人や日本人社員にl10n化やi18n化を任せる場合もある。こういう点で言えばmiyagawaさんも言うように日本人にとってi18n化はJob Securityになり得る。
企業としての立ち位置ならば、それは完全な業務だろう。

最近はあまり活動してないですが、私もこれまで色んなソフトウェアのi18n patchをオフィシャルに提供して来た。もちろん無償で...

例えばvim。私がvimのオフィシャルにpatchを送り始めたのはvimのバージョンが5.6だった頃。それまではMLで英語に苦労しながらvim/cvsheadの追っかけをやってました。それまでのvimは各文字コード毎に実装を個別に対応した処理になっており、今から考えるとそれはひどいコードでした。
私が最初に送ったpatchは「set guifont」で設定したフォントをIMEキャレットにも設定するといった物。Bram Moolenaar氏は適当な英語にも快く答えてくれ、extra patchながら取り込んでくれました。ぜんぜん大したpatchでは無いがftpサーバに「5.6.004」というファイルで置かれたパッチを見た時は飛び跳ねる程嬉しかった。
それからvimには数多くのi18n patchが適応され、現在では内部でutf-8を処理出来る素晴らしいエディタとなった。1文字毎をメモリに持つのではなく全てバイト列で処理すると言った方法の為、他のアプリケーションとは違うi18n化の方法であり特殊ではあるが、逆に言えばvimは壊れたutf-8でも編集出来る様になっている。
最近はBram Moolenaar氏自身が何か新しい機能を取り込む際、マルチバイト文字列に非常に気を使っていてくれて、私がpatchを送る事は殆ど無くなった。でもそれが私の望んだ事だった。

私は、forkが嫌いだ。
私はl10nやi18n化した物をforkとして公開する形が好きではない。出来る事ならばオフィシャルに統合させるべきだと思っている。これはvimのcontribute authorでもあるKoRoN氏も同じ考え。私はl10n化やi18n化はオフィシャルを説得して取り込ませるべきものであって、そうでなければ公開する価値はあまり意味のない物だと信じている。
軽量GUIライブラリ、FLTKには以前、fltk version1をベースととしたfltk-utf8というforkがあったが、私はその頃まだベータ版であったfltk2をutf-8化するpatchを書いて送った。
fltk-utf8の作者には少し申し訳ない気もしたが、このpatchにより現在では当たり前かのようにfltk2で日本語が表示/入力出来る様になった。
良いものは良いものとして後押しするのがベターだと思った。
fltkに限らず多くのソフトウェアがボランティアで作成されており、素晴らしい事だと思う。その多くのエンジニアは見返り等求めない方であって、それをネタに自分のJobを生み出そうなんだ思ってもいない。
dankogai氏のEncodeもperlを後押しする為の物。例えばdankogai氏がperlに手を加えforkとしてEncode対応のperlをリリースしたならば、反論を受ける対象となり得るかもしれない。
しかしそれどころかEncodeはCodeReposにオープン開発という意味で公開されている。つまりdankogai氏はEncodeを独り占めしようとは思っていないと言う事だ。
外国人プログラマがEncodeにpatchを送ったならば、dankogai氏はきっとwelcomeメールを送るだろう。

私のようなちっぽけな開発者にはperlでEncode程のライブラリを作ってオフィシャルからforkさせられる程の実力は無いので大した事は言えないが、ボランティアでpatchや拡張を作っておられる方々に対して"「日本語」という最大最強の非関税障壁に守られた既得権益者"という言葉をあびせるのは明らかに間違っている。

もし「dankogai氏はEncodeをネタに名声を売っている」と言いたかったならば、それは貴方も「dankogai氏をネタに名声を売ろうとした」事になるのではないかな...。


2007/12/18

はてな
はてなハイクが面白すぎる。
もう、いままでの様に「はてなスターは気に入った記事にしか付けない」なんて考えの人は、一度行ってみるべき。
スピード感、一発ネタ、五臓六腑に染み渡るダジャレ。
どれもこれもたまりません。
あと、手前味噌ですが昨日作った「LDRizeでpin付けたノードにMinibufferから「はてなスター」を付けるグリモン」がめちゃ便利。
LDRizeとMinibufferがあれば「j/k」で上下移動し「H S」で、はてなスターを付けられます。
※pinを付けて無くてもスターを打てる様に改良してあります。
見てるだけでも面白いですよ。

2007/12/17

はてな
ちょ!!www
まだそれ出来てないすから!!!
http://h.hatena.ne.jp/noreply/9236556151112331479
id:noreply
ldrizeでpしたハイクにスターを打つminibufferコマンド欲しい
http://h.hatena.ne.jp/otsune/9236538558961639940
id:otsune
それ id:mattn で
週末時点ではアカウント取れてたしotsuneさんからのidコールには気付いていたけど週末は予定ぎっしりで、結局出来ませんでした。
とりあえず動くようになったので公開...
:pinned-node | Hatena::addStar
でピンを付けたノードに「はてなスター」を付けられます。
動作には、LDRizeとMinibufferと、mattnへの愛情が必要です。

動かなかったら...そんとき対応します。
別にはてなハイクで無くてもLDRizeが動いて、はてなスターが付けられる所だったら動くかもしれません。
※とりあえず、はてなハイクでは確認出来ています。

インストール:minibuffer.hatena.addStar.user.js
追記
pinを付けてキー「H S」でも動きます。

mattn the Haiku Haiker Haikest!

2007/12/12

はてな
こりゃすげ。
URLを渡すとページの内容(htmlソース)をJSONPとかで取得できるAPIをYahoo! Pipesで作った(管理人日記) - むぅもぉ.jp
Yahoo! PipesにFetch Pageモジュールが追加されたので、さっそく作ってみた。
これで色んなことが出来るようになるし、グリースモンキーに頼っていたクロスドメインな処理がJSONだけで出来るようになる。
これまでにも同様の事が出来るサービスはあったけど、Yahoo! Pipesがサポートしたってのは強い。
試しにYahoo! JapanのHTMLをレンダリングするサンプルを作ってみた。
以下コード
<script type="text/javascript"><!--
function on_load_document(data) {
    document.getElementById('yahoo_html').innerHTML = data.value.items[0].description;
}
function load_document() {
    var url = 'http://www.yahoo.co.jp/';
    var s = document.createElement('script');
    s.charset = 'utf-8';
    s.src = 'http://pipes.yahoo.com/poolmmjp/page_loader?url=' + encodeURIComponent(url) + '&_render=json&_callback=on_load_document';
    document.body.appendChild(s);
}
--></script>

<input type="button" onclick="load_document()" value="Yahoo! Japanを表示">
<div id="yahoo_html"></div>
実行結果は↓

続きを読む...


2007/12/10

はてな
こちらを参考に...
MinibufferベースのTwitter Post&Favorites Command Greasemonkey - 0x集積蔵
Jaiku版作ってみました。
以下ダウンロードURLがあります。

ただ、Jaikuの場合twitterと違ってBasic Authのダイアログを出す訳には行きません。Jaikuの場合にはAPIキーが必要となります。
グリモンをインストールした後
グリモンの設定ボタンを押してスクリプト編集に移り、「JaikuUser」と「JaikuApiKey」を修正します。
minibuffer-jaiku
個々のユーザに対するAPIキーはJaikuのAPIドキュメントに書いてあります。(黄色くおねしょしたみたいになっている部分です)
あとはtwitter版と同じ使い方になります。キーバインドとして「J T」および「J R」が追加されます。

なお、先ほどJaiku用のLDRize SITEINFOも書いておきましたので、pinからreplyする事も出来ます。

後は適当に...
minibufferjaikucommand.user.js

mattn the jaiku jaiker jaikest!.

2007/12/07

はてな
色んな人のvimrcを見ていて意外とmapされていないのがこの技。
元はと言うとKoRoNさんから教えて貰った技で、先日公開した私のvimrcにも入っています。
" expand path
cmap <c-x> <c-r>=expand('%:p:h')<cr>/
" expand file (not ext)
cmap <c-z> <c-r>=expand('%:p:r')<cr>
これを使って例えば
# vi /path/to/file/file.txt
type some text...
:pwd
/path/to/file
な状態で、ファイルのある場所にカレントディレクトリを移したいならば
:cd <C-X>  <= Ctrl押しながらX
とコマンドモードで<C-X>をタイプすれば
:cd /path/to/file/
と補完されます。あとはENTERで移動。
結構便利だったりします。またコマンドモードで<C-Z>とすれば編集中のファイルへの絶対パスに補完されますので、例えば編集中のHTMLファイルをFirefoxで確認したいならば
:!firefox-remote <C-Z>ENTER
で簡単に確認出来ます。書きはじめたjavascriptを試すにはいいですね。
※Windowsの場合はvimrcで「set shellslash」してあり、かつfirefoxまでのパスが通っている状態ならば「:!firefox <C-Z>」で行けるかもしれません。(確認してません)

応用として、例えばまだインストールしていないGreaseMonkeyスクリプトをvimで閲覧/編集中に「:!firefox <C-Z>」すれば簡単にインストール出来てしまいます。UN*XユーザでいちいちファイラからFirefoxにjsファイルをドロップ...なんてメンドクサイですよね。特にcoderepos等のCVS/SVNリポジトリでグリースモンキーを見つけ中身をvimで確認してすぐさまインストールしたい!なんて時には大活躍です。
おそらく他にも使い道は沢山あるかと思います。
皆さんもvimrcに加えてみては如何でしょうか。

2007/12/06

はてな

その1 3桁ごとに区切る - PleasureDelayerDiary はてなブックマーク数


Number.prototype.split3_1 = function() {
    var r = ""; 
    var s = this.toString().split("").reverse();
    for(var i = 0; i < s.length; i++) {
        if(i % 3 == 0 && i != 0 && s[i] != "-") {
            r = s[i] + "," + r
        } else {
            r = s[i] + r;
        }
    }  
    return r;
}

その2 iandeth. - javascriptで数値をカンマ区切り文字列に変換する関数メモ はてなブックマーク数


Number.prototype.split3_2 = function () {
    var to = String(this);
    var tmp = "";
    while (to != (tmp = to.replace(/^([+-]?\d+)(\d\d\d)/,"$1,$2"))){
        to = tmp;
    }
    return to;
}

その3 JavaScriptで数値を3桁ごとに区切る - 0x集積蔵 はてなブックマーク数


Number.prototype.split3_3 = function() {
    var m = (this &lt; 0) ? -1 : 1;
    var str = String(this*m).split('.');
    var arr = String(str[0]).split(''), len = Math.ceil(arr.length/3), res = [];
    for (var i =0;i&lt;len;++i) res.push(arr.splice(-3,3).join(''));
    return (m == -1 ? '-' : '') + res.reverse().join(',') + (str[1] ? '.' + str[1] : '');
};

その4 [JavaScript]数値を3桁ごとに区切る はてなブックマーク数


Number.prototype.split3_ore = function() {
  ('' + this).match(/(-?)([0-9]+)(\.[0-9]*)?/);
  var sp = [RegExp.$1, RegExp.$2, RegExp.$3];
  var x = Math.floor(sp[1].length / 3) * 3;
  var len = sp[1].length;
  return sp[0] + (sp[1].substr(0, len - x)) + (len - x == 0 ? '' : ',') +
         (sp[1].substr(len - x, x).match(/[0-9]{3}/g).join(',')) + sp[2];
}
私ならこう書く。
Number.prototype.split3 = function() {
  var r = "", s = this.toString().split("").reverse().join("").replace(/\d{3}/g,
    function(v){r+=v+',';return ''});
  return (r + s).split("").reverse().join("");
}
alert((1000000).split3()) // 1,000,000
文字列を逆にして、replaceに指定した関数で3桁毎にカンマを入れた結果と、空で置換したsubstituteの結果(あまった結果)を足す。その後文字列を逆にして戻す。
マイナスもたぶんOK。


追記1
しまった。チェック甘すぎ。
Number.prototype.split3 = function() {
  var r = "", s = this.toString().split("").reverse().join("").replace(/\d{3}/g,
    function(v){r+=v+',';return ''});
  if (!s.match(/\d/)) r = r.substr(0, r.length-1);
  return (r + s).split("").reverse().join("");
}
計測してみる!
mattnおそ!www
関数呼び出しコストか?
追記2
うむ。小数か...
Number.prototype.split3_mattn2 = function() {
  var r = '', s = this.toString();
  s.match(/(-?)([0-9]+)(\.[0-9]*)?/);
  var sp = [RegExp.$1, s = parseInt(RegExp.$2), RegExp.$3];
  while(s >= 1000) {
    r = ',' + (s%1000) + r;
    s = parseInt(s/1000);
  }
  return sp[0] + s + r + sp[2];
}
-12345678.2356を3桁ごとに区切るテスト

タイム測定



うむ。それでも遅い。

2007/12/05

はてな
iTunesのライブラリ情報XMLファイルをアップロードする事で自分に合ったアーティスト情報を教えてくれるサービス、「veena!」の検索ボックスを使って、指定のアーティストに関連する
  • YouTube動画
  • Yahooオークション情報
をWeb::Scraperでスクレイピングしてみようと思います。
ソースはそれ程難しくもなく
#!/usr/bin/perl

use strict;
use warnings;

use URI;
use URI::Escape qw(uri_escape_utf8 uri_unescape);
use Web::Scraper;
use YAML::Syck;

my $artist = shift || 'Ozzy Ozbourne';
my $uri = URI->new('http://www.veena.jp/srch_artist.php?artist_name='
    . uri_escape_utf8($artist));

my $youtube_list = scraper {
    process '//table[@class="info_tbl"]/tr/td',
        'video[]' => scraper {
            process '//a[1]', url => sub {
                my $url = shift->attr('href');
                $url =~ s/^.*\?url=(.*)$/$1/;
                uri_unescape($url);
            };
          &nbs