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




最近Plaggerにハマってるからって、やる事メチャメチャやな...

Plaggerのフィードをvimの「--remote-send」を使って転送するPlaggerプラグインを作りました。
vimには、リモートサーバと言う機能があり以下のオプション/コマンドで別に起動しているvimへコマンド/式/ファイルを送信する事が出来ます。

--remote [+{cmd}] {file} ...
別のサーバへファイルを送信します。
+{cmd}により開く際にコマンドを併用出来ます。
--remote-silent [+{cmd}] {file} ...
--remote と同等ですが、エラー等が発生してもメッセージ出力されません。
--remote-wait [+{cmd}] {file} ...
--remote と同等ですが、送信したvimが終了するまで待機します。
vimで編集した結果をどこかに送るシェルスクリプト等では使えるかもしれません。
--remote-wait-silent [+{cmd}] {file} ...
--remote-wait と同等ですが、エラー等が発生してもメッセージ出力されません。
--remote-tab [+{cmd}] {file} ...
--remote と似ていますが、指定されたファイルを全て別タブで開きます。
--remote-tab-silent [+{cmd}] {file} ...
--remote-tab と同等ですが、エラー等が発生してもメッセージ出力されません。
--remote-tab-wait [+{cmd}] {file} ...
--remote-tab と同等ですが、送信したvimが終了するまで待機します。
--remote-tab-wait-silent [+{cmd}] {file} ...
--remote-tab-wait と同等ですが、エラー等が発生してもメッセージ出力されません。
--servername {name}
リモートサーバを名称で指定します。リモートサーバ一覧を取得するには --serverlist を使用します。
--remote-send {keys}
リモートサーバにキーを送ります。基本的にnormalコマンドで与える引数と同等です。
--remote-expr {expr}
リモートサーバに式を送り、その結果を出力します。
--serverlist
リモートサーバ一覧を出力します。

その他、スクリプトから使える
remote_expr({server}, {string} [, {idvar}])
{server}に対して{string}という式を評価して貰います。
:echo remote_expr("gvim", "2+2") と書くと4が表示されます。
remote_foreground({server})
{server}をフォアグラウンドにします。 remote_expr({server}, "foreground()") と同等の機能ですね。
等がありますので、vimを起動しなくても色々な事が出来ます。

今日は、はてなブックマークから「vim」タグが付いているエントリをvimに転送するPlaggerプラグインを作りました。
確認はWindowsでしかしてませんが、X Windowが動いている環境や、Mac OS X等でも動くかと思います。
※あと、フィードタイトルにエスケープ文字や「<ESC>」等といったvimのキー識別ぽい物があると動かない可能性があります。 package Plagger::Plugin::Publish::Vim;
use strict;
use base qw( Plagger::Plugin );

our $VERSION = '0.01';

use Encode;

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'plugin.init' => \&initialize,
        'publish.entry' => \&add_entry,
    );
}

sub initialize {
    my($self,$context) = @_;

    $self->{vim} = $self->conf->{vim};
    $self->{vim} = "vim" if (!$self->{vim});
    $self->{server} = $self->conf->{server};
    if (!$self->{server}) {
        open(IN, "vim --serverlist|");
        $self->{server} = <IN>;
        close(IN);
        chomp $self->{server};
    }
    open(IN, sprintf("%s --servername %s --remote-expr \"&encoding\"|",
        $self->{vim}, $self->{server}));
    $self->{encoding} = <IN>;
    print $self->{encoding}."\n";
    close(IN);
    my $command = sprintf("%s --servername %s --remote-send \"<C-\\\><C-N>:new<CR>i\"",
        $self->{vim}, $self->{server});
    system($command);
}

sub add_entry {
    my($self, $context, $args) = @_;

    $context->log(info => $self->{server});
    my $command = sprintf("%s --servername %s --remote-send \"%s\n\t%s\n<C-W>\"",
        $self->{vim}, $self->{server},
        encode($self->{encoding} || 'utf8', $args->{entry}->{title}),
        encode($self->{encoding} || 'utf8', $args->{entry}->{link}),
    );
    system($command);
}

1;
で、YAMLはこんな感じ
global:
  assets_path: /home/user/plagger/assets
  timezone: Asia/Tokyo
  log:
    level: info

plugins:
  - module: Subscription::Config
    config:
      feed:
        - http://b.hatena.ne.jp/t/vim?mode=rss

  - module: Filter::BreakEntriesToFeeds
    config:
      use_entry_title: 1

  - module: Publish::Vim
    config:
      #vim: vim7
      #server: GVIM1
実行結果は
vim_plagger

またくだらんもん作ってしもた...
Posted at by




vimにはexplore.vimというスクリプト(現在はnetrw.vimに統合)が付属しており # vim /usr/include 等と実行すると、vimがファイラとして起動します。同様にコマンドラインから :e /usr/include と実行しても同じ結果になります。コマンド単体としてもExploreとして起動出来ます。
このExplore実は結構よく出来ていて、以前ご紹介した「男は黙ってvimでリモート編集」の応用として :e ftp://ftp.vim.org/pub/vim/
Enter username: anonymous
Enter Password: *********
でフォルダ閲覧出来ます。(*********はanonymous) " ============================================================================
" Netrw Directory Listing                                        (netrw v109)
"   ftp://ftp.vim.org/pub/vim/
"   Sorted by      name
"   Sort sequence: [\/]$,\.h$,\.c$,\.cpp$,\.[a-np-z]$,*,\.info$,\.swp$,\.o$\.obj
"   Quick Help: <F1>:help  -:go up dir  D:delete  R:rename  s:sort-by  x:exec
" ============================================================================
../
./
MIRRORS
README
amiga
atari
be
beanie.gif
doc
extra
faq.html
farsi
green_ball.gif
index.html
ftp://ftp.vim.org/pub/vim/ [RO]                                       1,1     2%

また、Exploreではファイル名にカーソルを合わせて「x」をタイプすると拡張子に合わせてアプリケーションが起動します。
例えばWindowsでファイル名が「勤務表.xls」であればExcelが起動します。

この「x」で外部アプリケーションが起動する機能、現状はWindows、GNOME、KDEをサポートしています。
ちょっとソースを見たところ、netrw.vimには元となったexplore.vimに昔々に私が入れ込んだ「explFileHandler」が別名「netrwFileHandlers」として取り込まれてました。
ただ、「netrwFileHandlers」は私が元々想定していた単一のユーザ関数ではなく「netrwFileHandlers#Invoke」という関数でファイル種別毎に分別され、ファイル種別毎のスクリプト関数が実装されていました。
これをグローバルで宣言すれば自分独自の設定も出来るという仕組みです。 let g:netrw_browsex_viewer='-'
" エディタであるvimから秀丸起動して、何やってんだか...
function! NFH_txt(file)
    " netrwFileHandlers.vimの不具合回避?
    let f = substitute(a:file, '^\([A-Z]\)COLON', '\1:', '')

    exe "silent !start c:/progra~1/hidemaru/hidemaru.exe \"".f."\""
    return 1
endfunction

こんな感じのユーザ関数を作れば例えば.plや.shでperlやbashを起動したりする事も出来ます。
コード内にある「netrw_browsex_viewer」ですが、"-"に設定すると上記のようなユーザ/スクリプト関数を呼び出す機能として動作しますが、実行可能なコマンドを設定するとそのまま起動してくれるようにもなっています。
これを使用すれば、現状Windows、GNOME、KDEしかサポートしていないnetrw.vimでも、Mac OS Xに対応する事が出来ます。
私はMac OS Xを持っていないので確認出来ませんが、MacWiki - OSXの固有コマンドを見ると、Mac OS Xではコマンドラインからファイルを開く「open」コマンドがあるらしいので let g:netrw_browsex_viewer = 'open'
とvimrcに設定しておけば、Exploreから「x」をタイプする事でファイル種別に応じたアプリケーションが起動出来るかと思います。
※どなたか動作報告頂ければ、オフィシャルにマージして貰えるかもしれません。

その他、netrw.vimが使用するftp/sshのコマンドライン等の設定は :NetrwSettings
とすれば、設定画面が表示されますので、色々カスタマイズして見ると面白いかもしれませんね。

mattn the vim explorer
Posted at by