2008/01/31


vimscriptの発祥から考えると、vimで扱えるオブジェクトはあくまで数値、文字列レベルの物でしかないと思われがちですが、Dictionaryとfunction()を使えば、それとなく継承ぽい事が出来ます。
まぁ、javascriptに近い言語仕様というのもありますからね。
以下のコードでは、簡単なクラスとオブジェクトを定義しています。
function! Class_Prototype() dict
  return self
endfunction

function! Class_Override(...) dict
  if a:0 == 0|throw "Invalid Parameter"|endif
  let class = copy(self)
  let class.__NAME__ = a:1
  if type(a:2) == type(class.New)
    let class.New = a:2
  else
    let class.New = self.New
  endif
  let class.Super = self
  return class
endfunction

function! Class_New(...) dict
  let instance = copy(self)
  call remove(instance, "New")
  call remove(instance, "Override")
  let instance.Super = self
  return instance
endfunction

function! Class_ToString() dict
    return self.__NAME__
endfunction

let Object = {
 \ "__NAME__" : "Object",
 \ "Prototype"function("Class_Prototype"),
 \ "Override"function("Class_Override"),
 \ "Super"{},
 \ "New"function("Class_New"),
 \ "ToString"function("Class_ToString")}
この状態で if exists("object")|unlet object|endif
let object = Object.New()
echo object.ToString() . ":..."
とすると Object:... と表示されます。

ここで function! Human_Sing() dict
  return self.perfix . "は" . self.name . "。" . self.title
endfunction
function! Human_New(...) dict
  let instance = copy(self)
  let instance.perfix = a:1
  let instance.name = a:2
  let instance.title = a:3
  let instance.Sing = function("Human_Sing")
  return instance
endfunction
let Human = Object.Override("Human", function("Human_New"))
とすると、Objectクラスを継承するHumanクラスを定義する事が出来ます。
さらにこの状態で if exists("human")|unlet human|endif
let human = Human.New("私", "人間", "一般人")
echo human.ToString() . ":" . human.Sing()
とすると Human:私は人間。一般人 と表示されます。
つまり、Newメソッドをオーバーライドし、Singメソッドを追加した事になります。ToStringメソッドはObjectクラスのメソッドとなります。
vimscriptはJavascriptのように、メンバを動的に生成出来ますので
function! Gian_Boxing(who) dict
  return a:who . "のくせに生意気だぞ!!!"
endfunction
let Gian = Human.Override("Gian", {})
let Gian.Boxing = function("Gian_Boxing")
if exists("gian")|unlet gian|endif
let gian = Gian.New("俺", "ジャイアン", "ガキ大将")
echo gian.ToString() . ":" . gian.Sing()
echo gian.Boxing("のび太")
とすると Gian:俺はジャイアン。ガキ大将
のび太のくせに生意気だぞ!!!
とジャイアンが生成出来ます。
意外とやれるもんですね。

ただ、せっかくローカルスコープ、スクリプトスコープ、グローバルスコープ等、名前空間は既にしっかり存在してるんだから、もう少し他のオブジェクト指向言語(JavaやJavaString、C#やVB.NET)のように既定メソッドとかデフォルトコンストラクタみたいな概念が欲しいなぁ...
あと関数名は先頭大文字強制ってのは痛い。
ま、その辺はまた今度...

mattn the vimscripter
Posted at by




vimを使っていらっしゃる半数以上は開発者の方かと思います。
今日は、そんな開発者の方に便利なtipsをご紹介。

Makefile編集中のファイル名補完

一般的なファイルシステムでは、ファイル名に「=」という文字を使うことが出来ます。ただ、実際に使っているかどうかといえば、めったに使われる事はありません。なのに TOP_DIR=/usr/inc
まで打って<c-x><c-f>とタイプしてもファイル名が補完されないのは、悲しかったりします。 こんなときには以下の設定をvimrcに入れておくと便利です。
autocmd FileType Makefile setlocal isfname-== isfname+=32
通常、フォルダ名やファイル名に「=」やスペースを使う事はまずありませんし、*unix系の開発を経験された事がある方ならば、スペースが混じってしまう事は一大事になる事もご存知かと思います。
この設定だと、Makefileにだけ適応されますし補完もサクサク出来ますね。
ちなみにWindowsで「C:/Program Files/hogehoge」を補完されたいならば TOP_DIR="C:/Progra
と「"」を先頭にしておく事で補完出来ます。
もしかすると、*unixな方は「I」や「L」もisfnameから消してしまう事で CFLAGS=-I/usr/inc
とか LDFLAGS=-L/usr/li
でも補完出来て幸せかもしれません。

長いブロックや複数ブロックがある言語の開発

jsp(JavaServerPages)やASP(ActiveServerPage)、php等で開発される場合には、開始タグで各言語の処理を開始します。例えばphpであれば <?php
$f = fopen("test.dat", "r");
と「<?php」が開始タグとなります。
vimでは各言語に合わせてシンタックスハイライト表示する機能を持っていますが、この開始/終了タグを辿って色付けをしています。この開始/終了タグの検索は、最悪ファイル全体を検索してしまい重たくなってしまう可能性がある為、vimでは閾値範囲内しか検索しないようになっています。
ただ、全ての言語でこの閾値が相応しいものとは限らず、まれに長いブロックが存在するとシンタックスハイライトが効かなくなってしまう事もあります。ここではこの閾値の変更方法を説明します。
閾値は、「syntax sync 」コマンドの「minlines」という値で設定でき、以下のようにautocmdで設定します。
autocmd FileType jsp,asp,php,xml,perl syntax sync minlines=500 maxlines=1000
私は上記の設定を使っています。

pythonのインデントをタブではなくスペースにする

これはvimユーザでpythonの開発をされる方であれば、これは必須ですね。
以下の設定はタブ幅4で、expandtabにしています。
autocmd FileType python setlocal ts=4 sw=4 sta et sts ai
ただ、まれにスペース2つの人とかもいますから、人のソースを修正する際には向かないかもしれませんね。

Emacsユーザに送るキーバインド

これはおまけ。
nmap <m-x> :
nmap <silent> <c-x>1 :only<cr>
nmap <silent> <c-x>2 :sp<cr>
nmap <c-x><c-w><c-w>
cmap <m-x> <nop>
もっとこだわりたい方は、vimacsの方をお勧めします。

追記1:リンクが間違ってました
追記2:KoRoN氏の指摘で「BufEnter」から「FileType」に修正(コピペ元がマズってました)
追記3:さらにKoRoN氏の指摘で「FileType」のpatternが間違ってるとの指摘で修正(もしかしたらBufEnter使ってたのは拡張子使いたいからだったのかな?覚えてないや)

mattn the Onsen Ikitai!
Posted at by




コマンドモードで :help! 結果↓ E478: 慌てないでください!
tipsというよりイースターエッグかな...
Posted at by