2008/02/28

はてな
結構難しかった...
オリジナル作者はLDRizeやMinibufferを作られたsnj14さん。
初めてminibufferbookmarkcommandを使った時は「スゲー」と感動しました。その後ソースがCodeReposで管理される用になりプラガブルな仕組みに修正させて頂き、gooブックマークや、niftyクリップ、pookmark等のプラグインも動くようになりました。
ただFirefoxでは動くけど、Operaでは動かなかった。
Firefoxだけでしか使えないってのが擬かしい程、使い勝手はめちゃめちゃ良くて
「minibufferBookmarkcommandのボタン一発ブックマークが気軽すぎてタグ付けとかしなくなる」
とおっしゃる方もいる位。ポップアップも出ないし別画面に飛ばされる訳でもないから、記事を読んでる最中に「ぶくま!」と思ったら「b」一発。
タグやコメントが打ちたくなったら「B」。常用しだすと手放せなくなります。
で、この快感をOperaユーザにも伝えたい。そう思いました。
Operaでは通常の作りをしていてはドメインを越えた通信(JSON以外)は出来ないのですが、postMessageというAPIを使うことでコンテンツ間のメッセージングが行えるようになります。
これを使用して、GM_xmlhttpRequestもどきを実装しています。ただし困ったのがこのpostMessageに送り出す文字列(HTML)を取得する為にはオブジェクトをメインコンテンツに追加する必要がありかつ追加するという事はGET限定、つまりPOSTを実行させる為にはドメインを越えられる別のPOST実装が必要になるって事に。
で、結局やったのが動的にiframeを生成して、その中にformを作りポストするという方法。
いろいろやっている内に、DOM追加で動くGET版とiframeを使うPOST版を纏めたGM_xmlhttpRequestみたいな物がなんとなく出来上がりました。
(完全ではありません)

これで行ける!と思ったのですが今度はdel.icio.usのタグを取得する方法で困った。このpostMessageに送り出すにはDOMContentLoadedをフックするのだけれど、del.icio.usのAPIからXML形式のタグ一覧を読み込んだ時にはDOMContentLoadedが走らない。
悩んだ挙句、一度「http://del.icio.us/」にアクセスし、ユーザ名称を見つけ、「http://feeds.delicious.com/feeds/json/tags/XXXX」にアクセスし、JSONを取得するという方法で実装しました。
ようやく
が使えるminibufferbookmarkcommandが出来上がりました。ふぅ
Operaユーザの方で、SBMをお使いの方は一度試して見て下さい。
minibufferbookmarkcommand.js
なお作成にあたっては、Opera版のLDR Full Feedを作成されたos0xさんのコードをふんだんに参考にさせて頂いております。感謝。

2008/02/27

はてな
追記
都合上、キーを「g」から「z」に変更させて頂いています。
以下読み替えて頂く様お願い致します。

まぁ、お約束って事で。
しかしまぁLDRで全文取得表示するグリモン便利だなぁ。
OperaでLDR Full Feed - 0x集積蔵

id:Constellation さん作の、LDR Full Feed - Userscripts.orgをOperaに移植してみた。
移植早ぇぇぇぇぇ!!!

って事で、os0xさんのOpera版をベースにGoogle Reader版を作ってみました。
そんなに大きな変更してません。要はos0xさんのを参考に昨日のグリモンをOperaに対応させただけ。

またまた操作は同じく、[G]のアイコンが付いてたら「g」を押下で全文取得。
とりあえず、dankogai氏のサイトでチェックして問題なさげ。(またか!)

ライセンスはLDR Full Feedに委ねます。さらにOpera固有部に関してはos0xさんのLDR Full Feed Operaに委ねます。

ダウンロード:googlereaderfullfeed.js

追記
2008/02/28

2008/02/26

はてな
まぁ、ぶっちゃけ(なくても)「はてブちゃんねる」のパクリなんですが...
単純にwith_friendsのRSSをGoogle Ajax Feed API使ってパースしてるだけです。
コードはこんな感じ。
<script type="text/javascript" src="http://www.google.com/jsapi?key=ABQIAAAAS_2fKEdj-fsDOrnYqd4nthQCjALL2TOLFFIzEhjgebS4V6SjnhTxtlSoL0NJ-Fa6B7tsqLuiiPI9Pg"></script>
<style type="text/css">
.twitter-2ch {
    background-color: #efefef;
    width: 400px;
    color: #000000;
    font-family: 'MS PGothic',sans-serif;
    padding: 1.0em;
}
#twitter_2ch_container a:visited {
    color: #660099;
}
#twitter_2ch_container a:active {
    color: #ff0000;
}
.twitter-2ch-title {
    color: red;
}
</style>
<script type="text/javascript"><!--
function twitter_2ch() {
  var container = document.getElementById("twitter_2ch_container");
  container.innerHTML = "";
  var img = document.createElement('img');
  img.src='http://mattn.kaoriya.net/images/ajax-loader.gif';
  container.appendChild(img);

  var twitterId = document.getElementById("twitterId").value;
  var feed = new google.feeds.Feed('http://twitter.com/statuses/friends_timeline/' + twitterId + '.rss');
  feed.setNumEntries(10);
  setTimeout(function() {
    feed.load(function(result) {
      if (!result.error) {
        var html = "";
        for (var i = 0; i < result.feed.entries.length; i++) {
          var entry = result.feed.entries[i];
          var link = entry["link"];
          var pubDate = new Date(entry["publishedDate"]).toLocaleString();
          var content = entry["content"];
          var author = content.replace(/:.+$/, '');
          var status = content.replace(/^[^:]+: /, '');
        html += (i+1) + ':<a href="' + link + '">以下、名無しにかわりましてfollowerがお送りします。</a>:' + pubDate + ' ID:' + author + '<br />';
        html += '<blockquote>' + status + '</blockquote>';
        }
        container.innerHTML = html;
      }
    });
  }, 100);
}
google.load("feeds", "1");
--></script>
<div class="twitter-2ch">
<span class="twitter-2ch-title">今何してる?</span>
twitter id:<input type="text" id="twitterId" value="mattn_jp"/>
<input type="button" onclick="twitter_2ch();" value="twitter→2ch"/><br />
<br />
<div id="twitter_2ch_container"></div>
</div>
で、実行画面は以下の通り

続きを読む...


はてな
vimのオライリー本が出るようです。

Learning the VI and VIM Editors Learning the VI and VIM Editors
Arnold Robbins
Oreilly & Associates Inc / ¥ 4,267 (2008-07)
 
発送可能時間:近日発売 予約可


これまでに私が買ったvi/vim本は

viデスクトップリファレンス (UNIX text processing) viデスクトップリファレンス (UNIX text processing)
アーノルド ロビンス
オライリー・ジャパン / ¥ 840 (1999-06)
 
発送可能時間:通常24時間以内に発送


vi (Linux magazine books) vi (Linux magazine books)
金光 雅夫
アスキー / ¥ 1,575 (2000-09)
 
発送可能時間:通常24時間以内に発送


ViIMproved‐Vim完全バイブル ViIMproved‐Vim完全バイブル
Steve Oualline
技術評論社 / ¥ 3,549 (2004-05)
 
発送可能時間:通常24時間以内に発送


くらいかな。
誰か翻訳してくれ。

素のviって1冊もあれば基本は網羅出来てしまうんで、vim本には基本部分(viコンパチな部分)って書かなくてもいいよ。
特にvi/vimの歴史とか、もういらんし。

2008/02/25

はてな
追記
都合上、キーを「g」から「z」に変更させて頂いています。
以下読み替えて頂く様お願い致します。
LDRで全文取得表示するグリモン便利だなぁ。
LDR Full Feed 0.0.6
gをぺちって押してLDRで全部全文読んじゃおう。
「g」押すだけなんて!!!
でもLDR使ってない!!!

って事で、Google Readerにサクサクっと移植してみました。
そんなに大きな変更してません。SITEINFOも同じ場所を使っています。
オリジナル作者様、もし同じSITEINFOを見る事に問題があれば、ご連絡下さい。
即効でグリモン毎、削除させて頂きます。


操作は同じく、[G]のアイコンが付いてたら「g」を押下で全文取得。
とりあえず、dankogai氏のサイトでチェックして問題なさげ。

ライセンスはLDR Full Feedに委ねます。

ダウンロード:googlereaderfullfeed.user.js

googlereaderfullfeed
dankogai氏のサイトの全文です。dankogai氏問題があればご連絡下さい。
キャプチャを削除させて頂きます。

はてな
私の場合、xargsの引数がオーバーする程のファイルを扱う時は、少し怖いので一度別のディレクトリに移動してから削除するなりをやってます。
また、数十個の場合ならばfindだけでやってしまいますね。その方が思考が止まらないし...。
ただ、findとxargsの組み合わせで結構多いのが
  • さらにその中から間引きたい
  • 実行は並び替えた結果で行いたい
といった場合が少なからずあるのです。
例えばYYYYMMDD等といった日付形式のファイル名で散乱しているファイルを日付通りに処理したい。
と言った場合、やはりsortやgrepのお世話になるのが楽ですよね。
sortやgrepを使う場合、findで-print0した結果ではフィルタフィルタ実行する事が出来ません。
こんな場合には、findでは-print0せずに
find . -name "*.txt" | grep '/[0-9]¥{8¥}¥.txt' | sort -n | tr ¥¥n ¥¥0 | xargs -0 ...
といった感じにxargsに渡す寸前でtrを使って改行コードを¥0に置き換えてやる。

もう少し手間になってきたらawkとか使うけど、ちょっとしたものならこれでもOK。例が良く無いか...

2008/02/22

はてな
最近は、Shift_JIS(Windowsでいうならcp932)には2バイト目に「¥」(0x5C)が混じった文字がある事すら知らない人が居るようで...
すこしカルチャーショックを受けたオジサンmattnです。
職場でUNIXからWindowsに移植したソースコードでコンパイルが通らない!と悩んでいらっしゃる。
そしてその原因がオリジナルを書いた人のコードが悪いと...
まぁ確かにソースコード内に日本語書いてた人が悪いのかもしれませんが...
今日はみんな知ってそうな話。知らなかったら知っといてねくらいの話。

そんなに珍しい話じゃないんですよね。ソースコード内に埋め込みの日本語って。まぁ理由はポータビリティだったり、ソースコードを簡潔に書く為だったり、単純に面倒臭かっただけだったりと(爆)...

昔は結構あったんですよ。ソースコードがeuc-JPなソースとか。

ただそれは、昔は普通にあった話で開発者なら知っておきたい事かな。
まぁここでボヤいても、その担当者には伝わらないんだろうけど。

euc-JPとは違い、Shift_JISには後続するバイトとして0x5Cが来る事があります。
例えば、「ソ」「表」「噂」「貼」など。あと「―」(DASH)もそうですね。
ソースコードの中で罫線などを書く場合によく埋め込みでDASHが書かれたソースコードってのもありました。

で、これが何故問題になるか。もうわかりますね。
C言語等のソースコードでは「¥」(0x5C)はエスケープ文字のリーダとして働くからです。
コンパイラは通常、そのソースがeuc-JPなのかShift_JISなのかUTF-8なのか知りません。javac(gcj)等では「--encoding」なんてオプションで入力ソースのエンコーディングを指定出来たりもしますが、通常のCコンパイラではそうは行きません。
Microsoft Visual C++(日本語版)のコンパイラはShift_JIS(もしくはUnicode)を特例として許しているだけです。
ソースコードは世界の誰がコンパイルしても同じモジュールを作ることが出来るべきであって、日本製のコンパイラでしかビルド出来ないソースってのは異端児もいいところかと。
まぁソースコードに生マルチバイト書くなんて...ってのが本筋ですが。

今日は、古き良き(?)時代のジョークプログラムをWindowsに移植する時の注意点を示してみます。

昔、UNIXで「ls」を「sl」とタイプミスした時に、端末上にSLが突っ走るジョークプログラムがありました。
私も気に入って入れたりもしました。
「sl」も気に入っていたのですが、改変版の「quit」がさらに好きでした。
さすがにshellをsqlplusなんかと間違う事は無かったので本気でshellに「quit」と打ち込むことは無かったですが、「もう来ねぇよ!」と端末を走るAAが気が和んで楽しかったです。
で、そのquitですが私が確認した所
福地さんののページにある
ショートショートプログラムの部屋
にバージョン1.2aとして置いてありました。
さっそくダウンロードし解凍。
まずeuc-JPで書かれているソースをShift_JISに変換するのですが、ここで問題が起きます。
上でも述べた様に、Shift_JISには後続するバイトに「¥」(0x5C)を持つ物があるのですが、このquitのソースに記述されている「―」(DASH)は、Shift_JISで表すと「0x81 0x5C」というバイト列。つまりうかつに変換してしまうとC言語のエスケープ文字を自ら作ってしまう事になるのです。
案の定、以下の様にnkfで変換したソースはそのままコンパイルする事が出来ません。
C:¥temp¥quit-1.2a>nkf -g *
Makefile:ASCII (LF)
quit.1:EUC-JP (LF)
quit.c:EUC-JP (LF)
quit.h:EUC-JP (LF)
quit.txt:ASCII (LF)
README:EUC-JP (LF)

C:¥temp¥quit-1.2a>mkdir tmp

C:¥temp¥quit-1.2a>copy quit.c + quit.h tmp
quit.c
quit.h
        1 個のファイルをコピーしました。

C:¥temp¥quit-1.2a>nkf -EsX quit.c > sjis_quit.c

C:¥temp¥quit-1.2a>nkf -EsX quit.h > sjis_quit.h

C:¥temp¥quit-1.2a>del quit.c quit.h

C:¥temp¥quit-1.2a>rename sjis_quit.* quit.*

C:¥temp¥quit-1.2a>mingw32-make CC=gcc CFLAGS="-O -DJAPANESE=1"
gcc -O -DJAPANESE=1 -o quit quit.c -lncurses
quit.c:47:49: warning: unknown escape sequence '¥|'
quit.c:47:49: warning: unknown escape sequence '¥|'
quit.c:47:49: warning: unknown escape sequence: '¥201'
quit.c:47:49: warning: unknown escape sequence '¥|'
quit.c:238: error: stray '¥26' in program
quit.c:238:2: warning: no newline at end of file
mingw32-make: *** [quit] Error 1
※ギコ猫版をビルドするには「-DJAPANESE=1」が必要です。
※コンパイルはMinGWで行っています。(pdcursesも必要)

で、これを修正するには「0x5C」が後続する文字の後に「¥」を付けてコンパイラがエスケープ開始文字と混同しないように教えてあげます。
例えば「―」(DASH)であれば「―¥」となります。
コンパイル結果から、一つずつ直していっても良いのですが、実はこれコンパイルエラーとなっていない場合もあります。
例えば「―t」という表示があった場合、コンパイラは変な1文字と「¥t」(タブ文字)があるかの様に振るいます。
実際の例で言えば
#include <stdio.h>
#include <string.h>

    int
main(int argc, char* argv[]) {
    const char* s = "―t";
    printf("'%s' = %d\n", s, strlen(s));
    return 0;
}
のソース(Shift_JIS保存)は、Microsoft Visual C++では「―」の2バイトと「t」の1バイトで計3バイトという結果が返りますがMinGWでは「0x81」の1バイトと「¥t」の1バイトで計2バイトの結果となります。

まぁ、MSVCでコンパイルするからいいや...という方はこのままでも良いのですが、今回扱うquitはUNIX流のソース。ヘッダに「unistd.h」もincludeしてますからそのままのソースコードではビルド出来ません。
mingwならば例えば以下の様なフィルタプログラムを使うのが良いでしょう。
#include <stdio.h>
#include <string.h>

    int
main(argc, argv)
    int    argc;
    char   **argv;
{
    char buffer[BUFSIZ];
    char *p;

    while (fgets(buffer, BUFSIZ, stdin) != NULL) {
        for (p = buffer; *p != 0; p++) {
            if (*p & 0x80) {
                putchar(*p++);
                if (*p == '\\') putchar(*p);
            }
            putchar(*p);
        }
    }
    return 0;
}
このソース、実はvimのpoディレクトリにあるsjiscorr.cからパクってます。
(とは言ってもsjiscorr.cも元はと言えば私がbram氏に送ったソースですが...)

これを
C:¥temp¥quit-1.2a>type quit.c | sjiscorr > esc_quit.c

C:¥temp¥quit-1.2a>type quit.h | sjiscorr > esc_quit.h

C:¥temp¥quit-1.2a>del quit.c quit.h

C:¥temp¥quit-1.2a>rename esc_quit.* quit.*
の様にすればOK。一連の流れを一回でやるならば
C:\temp\quit-1.2a>nkf -EsX quit.c | sjiscorr > sjis_quit.c

C:\temp\quit-1.2a>nkf -EsX quit.h | sjiscorr > sjis_quit.h

C:\temp\quit-1.2a>del quit.c quit.h

C:\temp\quit-1.2a>rename sjis_quit.* quit.*
ってやった方が速いですね。

あとはビルド。GNUWin32にあるPDCursesのページにある「Developer files」、「Binaries」をダウンロードしてMinGW環境に入れた後、Makefile内にある「-lncurses」を「-lcurses」に修正し
C:\temp\quit-1.2a>mingw32-make CC=gcc CFLAGS="-O -DJAPANESE=1"
とすれば出来上がり。
かと思いきや、usleepがリンクエラー。こればっかりは仕方ありませんね。
--- quit.c.orig Fri Feb 22 12:14:24 2008
+++ quit.c  Fri Feb 22 12:14:53 2008
@@ -6,6 +6,10 @@
 #include <ncurses.h>
 #include <signal.h>
 #include <unistd.h>
+#ifdef _WIN32
+# include <windows.h>
+# define usleep(x) Sleep(x/1000)
+#endif
 
 #include "quit.h"
 
こんなパッチでusleepをSleep(1000分の1)で誤魔化してビルド。
見事以下の様にquitがネイティブ実行出来る様になりましたとさ。
※但しcurses2.dllは実行PATH環境に必要

quit-win32

で、何の話でしたっけ...

追記
いわたさんからご意見頂きました。
いわた @mattn_jp -finput-charset=cp932 -fexec-charset=cp932 への言及もおながいします。
って事でコンパイルを、いわたさんの言う様に「--finput-charset」指定でする事も重要ですね。特に「¥uXXXX」な文字列や「L"XXX"」なんかは上の方法では変換出来ませんしね。
また最近のUNIX環境ではオリジナルソースのまま「--finput-charset=euc-JP」、「--fexec-charset=utf-8」指定で(setlocaleもいるかな?)コンパイルする事が出来ますね。

今回の上の方は他の(MSVC以外の)Windows用コンパイラで有用だ...って事で。

2008/02/21

はてな
はてなスクリーンショットに微笑むblosxomプラグイン作りました。
普段は微笑みませんが、はてなスクリーンショットに「ハイ!ポーズ!」と言われるとスマイルを振りまくのです。

以下証拠写真
はてなスクリーンショット - http://mattn.kaoriya.net
で、blosxomプラグインのソース
package hatenascreenshot;
use strict;

use vars qw($smile);
my $photo = '<img src="お好きな画像">';

sub start {
  $smile = $photo if ($ENV{'HTTP_USER_AGENT'} =~ /HatenaScreenshot/);
}

1;
あとはフレーバに$hatenascreenshot::smileを入れるだけ。
お好きな画像で微笑んでみてはどうでしょうか?

決してウンコとかは辞めましょう。
※まぁネタですから...

2008/02/18

はてな
実はこのサイトは昔、私専用のローカル環境に用意した非公開なウェブサイトでした。
そして、そのサイトは今と同じくblosxomというブログツールで構築されていました。
私はその頃、今の様にvimで直接HTMLを書くのではなく、emacs環境から生まれた
howm: 一人お手軽 Wiki もどき
というメモ取り環境のvimクローン、「howm_mode.vim」を使い、その書き込みをblosxomに食わせる(拡張子をtxtでなくhowmにする)という方法で使用していました。

最近はhowm_mode.vimを使わなくなったのですが、先日howm_mode.vimを改造しておられる方を見つけ、ひっそりとウォッチしていました。
で、本日どうやら公開された様です。
48 howm-mode.vim (2-25) パッチの公開とそのあてかた
以前からぐずぐず言ってたパッチを公開。ついでに Windows 環境でのパッチのあてかたを書いた。
試しに本体をhowm_vimのサイトから、パッチをパッチ作者殿のページから落とし当ててみました。

始めは動きませんでしたが、少し弄った所すこぶる快適に動き出しました。
日本語での検索や、migemo/cmigemoを使った検索、空白を含んだhowm_dirディレクトリでも問題なく動作しました。
ありがとうございます。またしばらくはメモ取りとしてhowmを使ってみようかなぁ...って思いました。

で、今回修正したパッチはmatchendを使ってディレクトリを掘る部分。
matchendの第2引数は正規表現が入力可能なので、以下の様にescapeしました。
diff -cr howm_vim.orig\plugin\howm-mode.vim howm_vim\plugin\howm-mode.vim
*** howm_vim.orig\plugin\howm-mode.vim  Mon Feb 18 16:41:24 2008
--- howm_vim\plugin\howm-mode.vim   Mon Feb 18 16:15:40 2008
***************
*** 440,446 ****
  
    if editing != filepath
      let howm_dir = s:HowmExpand(g:howm_dir)
!     let idx = matchend(filepath, howm_dir)
      if idx != -1
        " 存在しないディレクトリ下のファイルを指定されたら,ディレクトリを作る
        call s:MakeDirectory(substitute(strpart(filepath, idx), '[^/]*$', '', ''))
--- 440,447 ----
  
    if editing != filepath
      let howm_dir = s:HowmExpand(g:howm_dir)
!     let g:hoge = howm_dir
!     let idx = matchend(filepath, escape(howm_dir, ' \~'))
      if idx != -1
        " 存在しないディレクトリ下のファイルを指定されたら,ディレクトリを作る
        call s:MakeDirectory(substitute(strpart(filepath, idx), '[^/]*$', '', ''))
注意:このパッチは、オリジナルからパッチ作者殿のパッチを当てた物からの差分です。

皆さんもメモ取り環境としてhowm_mode.vimを使ってみられてはどうでしょうか。
ちなみに、以前私が使っていた頃のtips。私はmigemoでなくcmigemoを使っているので
let howm_migemoprg='cmigemo'
let howm_migemoopt=' -q -d "'.globpath(&runtimepath,'dict/migemo-dict').'" | nkf -Ew'
としています。
また検索で全部出て欲しい場合もあったので、「¥,A」で検索かつ<c-n>,<c-p>で移動、さらに「o」で開ける様
nmap <silent> <leader>,A <leader>,g^=.*<cr>
autocmd BufEnter howm\ Search\ result nmap <buffer> <c-p> kp
autocmd BufEnter howm\ Search\ result nmap <buffer> <c-n> jp
autocmd BufEnter howm\ Search\ result nmap <buffer> o :exec "sp " . b:file{line('.')}<cr>
と設定しています。
vimぽいmapleaderや、GNUWin32ツールなんかを組み合わせていますので、howm関連だと全体で
let g:howm_mapleader='\'
if has('win32')
  let howm_grepprg='grep'
  let howm_findprg='find'
  let howm_html2txtcmd='c:/cygwin/bin/w3m -dump -cols 78 %s'
endif
let howm_migemoprg='cmigemo'
let howm_migemoopt=' -q -d "'.globpath(&runtimepath,'dict/migemo-dict').'" | nkf -Ew'
let howm_quotemark='> '
nmap <silent> <leader>,A <leader>,g^=.*<cr>
autocmd BufEnter howm\ Search\ result nmap <buffer> <c-p> kp
autocmd BufEnter howm\ Search\ result nmap <buffer> <c-n> jp
autocmd BufEnter howm\ Search\ result nmap <buffer> o :exec "sp " . b:file{line('.')}<cr>
こんな感じに設定しています。(私はcygwinにはパスを通さない派です)
使い始めると、意外とやみつきになりますよ。

追記
パッチ作成者殿へのリンクが間違っていました。
Posted at 17:31 in ソフトウェア::vim | WriteBacks (3)
Tagged as: howm, howm_vim, vim
Bookmarks: