2008/01/31


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を使い始めてみようと思われている方、このどっぷりと深い世界にのめり込んで見ませんか?
Posted at by




http://www.hsbt.org/diary/20071022.html#p02
だれか indent たのむ - HsbtDiary (2007-10-22)
頼まれた!
って訳ではないですが...

vimは数多くのファイルフォーマットに対応しており、通常扱うファイルであれば、ほぼ全てサポートしているんじゃないかという位、多くのファイルフォーマットに対応出来ています。
どれくらい凄いかと言うと...
gvimの「シンタックス(S)」メニューを展開すると画面がいっぱいになるくらいです。
vim_ff

さて、VBでのインデントですが、例えばVB6の以下の様なソース Private Sub Class_Initialize()
Debug.Print "あめんぼ赤いな"
        If Me.strValue = "" Then
    Debug.Print "エラー!"
End If
End Sub
Private Sub Class_Terminate()
Debug.Print "あいうえお"
End Sub
こんなに崩れたファイルでも、vimなら「gg=G」でおしまい。 Private Sub Class_Initialize()
    Debug.Print "あめんぼ赤いな"
    If Me.strValue = "" Then
        Debug.Print "エラー!"
    End If
End Sub
Private Sub Class_Terminate()
    Debug.Print "あいうえお"
End Sub
例えば、以下の様なJavaのソースファイルでも public class Test {
            public Test() {
                System.out.println("コンストラクタ");
            }
public void doPhpSpot() {
//ここでは何もしない
}
}
上のコマンドで public class Test {
    public Test() {
        System.out.println("コンストラクタ");
    }
    public void doPhpSpot() {
        //ここでは何もしない
    }
}
あらキレイ!
例えばファイル全体でなく、一部分だけインデントを修正したい場合にはビジュアル選択(V押下後にjk移動)した後で「=」とすれば、部分的にインデントし直されます。

どうですか!vim使いたくなりませんか!

mattn often say sales hype.
Posted at by




Googleが提供している開発用tagツールGoogle GTags(gtags)をWindowsで動かす手順です。
以下、パッチを上げてますが、接続タイムアウトのalarmを無効化しています。必要だと思われる人は、SIGALRMを別の方法で実装してください。
まず、サイトからsvnで最新ソースを取得します。
C:\TEMP> svn checkout http://google-gtags.googlecode.com/svn/trunk/ google-gtags 次に、以下のパッチを当てます。
Index: regexp.h
===================================================================
--- regexp.h    (revision 57)
+++ regexp.h    (working copy)
@@ -4,7 +4,9 @@
 #ifndef TOOLS_TAGS_REGEXP_H__
 #define TOOLS_TAGS_REGEXP_H__
 
+extern "C" {
 #include <regex.h>
+}
 #include "tagsutil.h"
 
 class RegExp {
Index: configure
===================================================================
--- configure   (revision 57)
+++ configure   (working copy)
@@ -10,7 +10,7 @@
 if [ ! -e "scons/scons.py" ]; then
     pushd scons > /dev/null
     echo "Unpacking scons..."
-    tar xzvf scons-local.tar.gz > /dev/null
+    gzip -dc scons-local.tar.gz | tar xv > /dev/null
     if [[ "$?" == 0 ]]; then
    echo "Done"
     else
Index: gtags.cc
===================================================================
--- gtags.cc    (revision 57)
+++ gtags.cc    (working copy)
@@ -49,6 +49,10 @@
 #include "tagsoptionparser.h"
 #include "tagsrequesthandler.h"
 
+#ifdef WIN32
+# include <winsock2.h>
+#endif
+
 DEFINE_STRING(tags_file, "", "The file containing the tags information.");
 
 
@@ -78,6 +82,11 @@
     return -1;
   }
 
+#ifdef _WIN32
+  WSAData wsadata;
+  WSAStartup(MAKEWORD(2,0), &wsadata);
+#endif
+
   logger = new StdErrLogger();
 
   tags_request_handler = new TagsRequestHandler(GET_FLAG(tags_file),
@@ -90,4 +99,9 @@
 
   delete tags_request_handler;
   delete logger;
+
+
+#ifdef _WIN32
+  WSACleanup();
+#endif
 }
Index: gtags.py
===================================================================
--- gtags.py    (revision 57)
+++ gtags.py    (working copy)
@@ -175,11 +175,11 @@
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      address = socket.getaddrinfo(host, port, socket.AF_INET,
                                socket.SOCK_STREAM)
-     signal.signal(signal.SIGALRM, alarm_handler)
-     signal.alarm(CONNECT_TIMEOUT)
+     #signal.signal(signal.SIGALRM, alarm_handler)
+     #signal.alarm(CONNECT_TIMEOUT)
      s.connect(address[0][4])
-     signal.alarm(0)
-     signal.alarm(DATA_TIMEOUT)
+     #signal.alarm(0)
+     #signal.alarm(DATA_TIMEOUT)
 
      # need \r\n to match telnet protocol
      s.sendall(command + '\r\n')
@@ -191,7 +191,7 @@
      while data:
        buf.write(data)
        data = s.recv(1024)
-     signal.alarm(0)
+     #signal.alarm(0)
      return buf.getvalue()
 
 # Instance of connection_manager that forwards client requests to gtags server
Index: tags_logger.h
===================================================================
--- tags_logger.h   (revision 57)
+++ tags_logger.h   (working copy)
@@ -67,6 +67,7 @@
   }
 };
 
+#undef ERROR
 const int INFO = 0, WARNING = 1, ERROR = 2, FATAL = 3, NUM_SEVERITIES = 4;
 
 // uncomment out the standard google logger
Index: socket_server.cc
===================================================================
--- socket_server.cc    (revision 57)
+++ socket_server.cc    (working copy)
@@ -18,10 +18,14 @@
 
 #include <assert.h>
 #include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
+#ifdef WIN32
+# include <winsock2.h>
+#else
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <unistd.h>
+#endif
 #include <string>
 
 #include "tagsprofiler.h"
@@ -29,6 +33,12 @@
 #include "tagsrequesthandler.h"
 #include "socket_server.h"
 
+#ifdef WIN32
+typedef int socklen_t;
+#define write(x, y, z) send(x, y, z, 0)
+#define close(x) closesocket(x)
+#endif
+
 extern GtagsLogger* logger;
 
 DEFINE_INT32(tags_port, 2222, "port to tags server");
次にgoogle-gtagsのソースルートにregex for win32を解凍します。これで、gnu_regex_distというフォルダが出来ます。
zsh for win32等をお持ちの方ならば、そのまま sh configure
お持ちでない方でもconfigureの中身を見ると大体検討が付きます。
Makefile.w32は以下の通り。mingw32-makeでビルドします。
all: gtags.exe

gtags.exe : filename.cc gtags.cc sexpression.cc strutil.cc symboltable.cc tagsoptionparser.cc tagsprofiler.cc tagsrequesthandler.cc tagstable.cc socket_server.cc gnu_regex_dist/regex.c
    gcc -DHAVE_STRING_H -c -I. gnu_regex_dist/regex.c
    gcc -I. -Ignu_regex_dist -o gtags.exe filename.cc gtags.cc sexpression.cc strutil.cc symboltable.cc tagsoptionparser.cc tagsprofiler.cc tagsrequesthandler.cc tagstable.cc socket_server.cc regex.o -lstdc++ -lws2_32
あとはspiritlooseのはてなダイアリー - [Vim]Google Tags(GTags)を試してみた(with Vim)を参考に lang_call_to_server = {
  "c++" : { "definition" : [("localhost", 2222)],
            "callgraph" : [] },
  "java" : { "definition" : [],
             "callgraph" : [] },
  "python" : { "definition" : [],
               "callgraph" : [] } }
等と設定して、vimrcに exec "set runtimepath+=".escape(globpath(&runtimepath, 'gtags'), ' ')
nmap <C-]> :call Gtag(expand('<cword>'))<CR>
を追加します。
これで設定はOKです。次に以下の手順でソースツリーでtagsファイルを生成します。
python c:/temp/google-gtags/gentags.py --etags=c:/emacs/bin/etags.exe --rtags=c:/temp/google-gtags/rtags.py --etags_to_tags=c:/temp/google-gtags/etags_to_tags.py ここではetagsとしてemacsに含まれるバイナリを使用しましたが、ctags.exeをetags.exeにリネームしても同様に使えます。
これで「cpp.tags.gz」というファイルが生成されますので、あとはサーバを起動します。
c:/temp/gtags.exe --tags_file ./cpp.tags.gz --tags_port 2222 --gunzip 起動したらvim(gvim)を起動して、タグジャンプしたい部分でC-]します。
spiritlooseさんの言うように確かに速いですね。共同開発等では便利かもしれませんね。

オフトピですが、このライブラリに含まれるSconsというビルドツールについて今度調べてみようかと思います。
Posted at by