2009/07/21


別にEditor's Warを起こそうって訳では無いです。
だたvimが弱々しく読める文章だったので補足させて頂きたい。
Emacs の人と Vim の人のキーストロークの数え方の違い。 - 日々、とんは語る。

Ctr キーは1ストロークには入りません!

普段 Emacs を使うとき、どう考えても「修飾キー + 文字キーの組み合わせは一発操作」という感覚でしかありません。

「Ctr + Alt + s」とか、修飾キーが複数であっても、同時押しであれば、僕の中では1ストロークです。

http://d.hatena.ne.jp/tomoya/20090715/1247590638
慣れればそうかもしれませんが、モディファイアキーを使うには両手、もしくは指が2本要ります。片手で済むならばもう片方の手で鼻をほじる事だって出来るんです。なんてすばらしい。

Emacs の人と Vim の人のキーストロークの数え方の違い。 - 日々、とんは語る。

一発で何んでもできるっていうところが重要で、とりあえず、気に入ったコマンドはキーバインドを割り当てます*1。これ常識。

http://d.hatena.ne.jp/tomoya/20090715/1247590638
vimもしますよ。人によってはストロークではなくてモディファイアキーを使った物にマップする人もいます。

Emacs の人と Vim の人のキーストロークの数え方の違い。 - 日々、とんは語る。

何ならキーバインド定義用のマイナーモードとか作って、オンオフを切り替えることで、キーバインドを自由に入れ替えて使う事もできます。

http://d.hatena.ne.jp/tomoya/20090715/1247590638
それもvimで出来ますし、無ければ作れます。

Emacs の人と Vim の人のキーストロークの数え方の違い。 - 日々、とんは語る。

そういった、キー操作カスタマイズの柔軟性が Emacs の利点であり、Vim の場合のアレコレする場合はコマンドを打ち込まないとアレコレできないところに、僕は不満を感じるのかもしれないなぁと、ふと思った。

http://d.hatena.ne.jp/tomoya/20090715/1247590638
vimも設定次第ではいくらでも出来ます。キー登録用のスクリプトもやろうと思えば出来ます。
emacsでも次回起動からも有効にしようと思えば .emacs に書くかと思いますが、間違ってますか?

ただしvimmerはしません。なぜなら...

コマンドを打ち込むのが好きだから。

自分だけのvimrcを作る為に、惜しげなく時間を費やす人達なのです。DropBoxなんかのストレージサービスやgithubなんかにvimrcを置いてしまう人達なんです。
ブログなんかでvimrcを晒しちゃう人達なんです。


えっそれemacsユーザも同じ?変態ですね!

mattn the vimmer!
Posted at by



2009/07/16


2009/07/16 追記
AWS認証制限に対応しました。本文中はそのままですが、デモには非公開キーを使用してアクセスするCGIに変更しています。


時代は便利になった物です。
MOONGIFT: » XMLをJSONにするXSLT「xml2json.xslt」:オープンソースを毎日紹介

xml2json.xsltを見ていたらma.la氏のAmazon最速検索を思い出した。あちらはAmazon AWS専用になるだろうが、xml2json.xsltはそれをもっと汎用的なものにしたと考えられるだろう。

http://www.moongift.jp/2009/04/xml2json-xslt/
javascriptとXSLTを使うならば、AWSサーバから見えるサーバを用意しないといけないのですがYahoo! YQLを使えばそれも要りません。
YQLといえばPipesに毛の生えた様な物だと思う方もいらっしゃるかもしれませんが、解析した結果をXMLやJSONで返す事ができJSONならばDOMツリーをJSONで表現してくれます。
例えばgithubで自分が公開したりforkしたりしているプロジェクトの一覧を作る場合、何を使って作りますか?Pipes?CGI?YQLならば簡単です。

続きを読む...

Posted at by



2009/07/15


amachangの記事glooxなんて物があるのを知った。
Gloox で XMPP を書いてみた - IT戦記

けっこうシンプルに書ける

http://d.hatena.ne.jp/amachang/20090601/1243852022

gloox - A portable high-level Jabber/XMPP library for C++

gloox is a rock-solid, full-featured Jabber/XMPP client library, written in C++. It makes writing spec-compliant clients easy and allows for hassle-free integration of Jabber/XMPP functionality into existing applications. gloox is released under the GNU GPL. Commercial licensing and support are available.

http://camaya.net/
確かに簡単そう。って事でWindowsだけれど試した。ソース見ると、なんと既にWindows対応出来ている。すばらしい。ただVisual Studio用のプロジェクトファイルが付いているだけだったので、mingw32からビルドする際には少し小細工が必要。
以下、その手順。
# wget http://camaya.net/download/gloox-1.0-beta7.tar.bz2
# tar xjvf gloox-1.0-beta7.tar.bz2
# cd gloox-1.0-beta7
# vim config.h.win

comment out HAVE_WINDNS_H
// #define HAVE_WINDNS_H 1

# cd src
# gcc -I. -c *.cpp
# ar cr libgloox.a *.o
これでmingw32用のlibgloox.aが出来上がる。そしてソース。glooxを使っておしゃべりするプログラムなので鶏っぽく"glookoo"(ぐるっくー)と名づけた。
必要な物はreadlineとpthread。readlineは出回っている物には--enable-multibyte付きでコンパイルされた物が見当たらなかったので、rubyのmingw32バイナリ等でも使われているココから使わせて頂く。
またpthreadはココからダウンロードして # make clean GCE-inlined
でビルドした物を使う。以下コード。
#include <gloox/client.h>
#include <gloox/connectionlistener.h>
#include <gloox/messagesessionhandler.h>
#include <gloox/messageeventhandler.h>
#include <gloox/messagehandler.h>
#include <gloox/message.h>
#include <gloox/messagesession.h>
#include <pthread.h>
#include <readline/readline.h>

#ifdef _WIN32
#include <windows.h>
#endif

static char* str_to_utf8_alloc(const char* str) {
#ifdef _WIN32
    size_t in_len = strlen(str);
    wchar_t* wcsdata;
    char* mbsdata;
    size_t mbssize, wcssize;

    wcssize = MultiByteToWideChar(GetACP(), 0, str, in_len,  NULL, 0);
    wcsdata = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
    wcssize = MultiByteToWideChar(GetACP(), 0, str, in_len, wcsdata, wcssize + 1);
    wcsdata[wcssize] = 0;

    mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsdata, -1, NULL, 0, NULL, NULL);
    mbsdata = (char*) malloc((mbssize + 1));
    mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsdata, -1, mbsdata, mbssize, NULL, NULL);
    mbsdata[mbssize] = 0;
    free(wcsdata);
    return mbsdata;
#else
    return strdup(str);
#endif
}

static char* utf8_to_str_alloc(const char* utf8) {
#ifdef _WIN32
    size_t in_len = strlen(utf8);
    wchar_t* wcsdata;
    char* mbsdata;
    size_t mbssize, wcssize;

    wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, in_len,  NULL, 0);
    wcsdata = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
    wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, in_len, wcsdata, wcssize + 1);
    wcsdata[wcssize] = 0;

    mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsdata, -1, NULL, 0, NULL, NULL);
    mbsdata = (char*) malloc((mbssize + 1));
    mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsdata, -1, mbsdata, mbssize, NULL, NULL);
    mbsdata[mbssize] = 0;
    free(wcsdata);
    return mbsdata;
#else
    return strdup(utf8);
#endif
}

class Glookoo : public gloox::ConnectionListener, gloox::MessageHandler
{
public:
    Glookoo(const char* server, const char* jid, const char* passwd, const char* user)
            : server_(server), jid_(jid), passwd_(passwd), user_(user) {
        client_ = NULL;
        session_ = NULL;
    }

    virtual ~Glookoo() {
        delete client_;
    }

    virtual void onConnect() {
        displayMessage("=== connected ===");
        session_ = new gloox::MessageSession(client_, gloox::JID(user_));
        session_->registerMessageHandler(this);
    }

    virtual void handleMessage(const gloox::Message& msg, gloox::MessageSession *session) {
        char* message = utf8_to_str_alloc(msg.body().c_str());
        displayMessage(message);
        free(message);
    }

    virtual void onDisconnect(gloox::ConnectionError reason) {
        displayMessage("=== disconnected ===");
        delete session_;
        session_ = NULL;
    }

    virtual bool onTLSConnect(const gloox::CertInfo &info) {
        return true;
    }

    void run() {
        client_ = new gloox::Client(gloox::JID(jid_), passwd_);
        client_->registerConnectionListener(this);
        client_->setServer(server_);
        client_->connect();
    }

    void sendMessage(const char* message) {
        if (session_) {
            char* send_message = str_to_utf8_alloc(message);
            session_->send(send_message, "");
            free(send_message);
        }
    }
    
    void displayMessage(const char* message) {
        int point = rl_point;
        rl_beg_of_line(0, 0);
        rl_redisplay();
        printf("%s\n", message);
        rl_point = point;
        rl_refresh_line(0, 0);
    }

private:
    gloox::Client* client_;
    gloox::MessageSession* session_;
    const char* server_;
    const char* jid_;
    const char* passwd_;
    const char* user_;
};

Glookoo* glookoo = NULL;

void* input_func(void* arg) {
    pthread_detach(pthread_self());
    while (true) {
        rl_callback_read_char();
    }
    return 0;
}

void* gloox_func(void* arg) {
    glookoo->run();
}

void input_handler(void) {
    char* message = rl_copy_text(0, rl_end);
    if (glookoo) glookoo->sendMessage(message);
    free(message);
}

int  opterr = 1;
int  optind = 1;
int  optopt;
char *optarg;
 
int getopt(int argc, char** argv, char* opts) {
    static int sp = 1;
    register int c;
    register char *cp;

    if(sp == 1) {
        if(optind >= argc ||
                argv[optind][0] != '-' || argv[optind][1] == '\0')
            return(EOF);
        else if(strcmp(argv[optind], "--") == 0) {
            optind++;
            return(EOF);
        }
    }
    optopt = c = argv[optind][sp];
    if(c == ':' || (cp=strchr(opts, c)) == NULL) {
        if(argv[optind][++sp] == '\0') {
            optind++;
            sp = 1;
        }
        return('?');
    }
    if(*++cp == ':') {
        if(argv[optind][sp+1] != '\0')
            optarg = &argv[optind++][sp+1];
        else if(++optind >= argc) {
            sp = 1;
            return('?');
        } else
            optarg = argv[optind++];
        sp = 1;
    } else {
        if(argv[optind][++sp] == '\0') {
            sp = 1;
            optind++;
        }
        optarg = NULL;
    }
    return(c);
}

int main(int argc, char* argv[]) {
    pthread_t pt_input, pt_gloox;
    char* server = "talk.google.com";
    char* jid = NULL;
    char* passwd = NULL;
    char* user = "wassr-bot@wassr.jp";
    int c;

    opterr = 0;
    while ((c = getopt(argc, argv, "j:p:s:u:") != -1)) {
        switch (optopt) {
        case 'j': jid = optarg; break;
        case 'p': passwd = optarg; break;
        case 's': server = optarg; break;
        case 'u': user = optarg; break;
        case '?': break;
        default:
            argc = 0;
            break;
        }
        optarg = NULL;
    }
    
    if (!jid || !passwd) {
        fprintf (stderr, "Usage: glookoo [-s server] [-j jid] [-p passwd] [-u user]\n");
        exit (1);
    }
    
    rl_callback_handler_install("#> ", (void(*)(char*))input_handler);

    glookoo = new Glookoo(server, jid, passwd, user);
    pthread_create(&pt_input, NULL, &input_func, glookoo);
    pthread_create(&pt_gloox, NULL, &gloox_func, glookoo);
    pthread_join(pt_gloox, NULL);
    pthread_join(pt_input, NULL);
    rl_deprep_terminal();
    return 0;
}
相変わらずコメントもなく適当ですね。
mingw32でのビルド手順は以下の通り。
gcc -Ic:/mingw/include/pthread -o glookoo.exe -I. glookoo.cxx libgloox.a c:/mingw/lib/readline.lib -lstdc++ -lws2_32 -lcrypt32 -lsecur32 -lpthreadGCE2
使い方はこんな感じ
Usage: glookoo [-s server] [-j jid] [-p passwd] [-u user]
デフォルトでサーバはGoogle Talk、ユーザはワッサーのボットになっています。
glookoo
マルチスレッドで入力とGlooxを処理していて入力途中の文字列を消されないようにしてあります。
今回はバイナリも置いておきます。
glookoo-0.0.1.tar.gz
よろしければどうぞ。ソースは後でgithubにでも上げておきます。
Posted at by