目的
- 機能を持ったVimスクリプト(プラグイン)を徐々に作る様子を見て、書き方を学習してみよう
- 作るのはよくあるタイプのプラグイン
- Javaの単体テスト用クラスファイルを開く(作る)コマンドを作るよ
- 「ね、簡単でしょう(by ボブ)」と言ってみたい
まずは雛形
ひな形としてこんなスクリプトを作ります。
command! -nargs=0 UtestAppend call <SID>UtestAppend()
function! s:UtestAppend()
echo 'HERE'
endfunction " s:UtestAppend()
- UtestAppendというコマンドを追加
- UtestAppendコマンドいが実行されたら ‘HERE’ と表示する
ほら、すごく簡単ですね。
Javaだけに作用させる
以下はdiff形式で変更点だけ。
@@ -1,5 +1,17 @@
command! -nargs=0 UtestAppend call <SID>UtestAppend()
function! s:UtestAppend()
- echo 'HERE'
+ let target = s:GetTargetName()
+ if strlen(target) <= 0
+ echomsg 'Not test target file: ' . expand('%')
+ return 0
+ endif
endfunction " s:UtestAppend()
+
+function! s:GetTargetName()
+ if expand('%:e') ==# 'java'
+ return expand('%')
+ else
+ return ''
+ endif
+endfunction " s:GetTargetName()
バッファがJavaの時だけファイル名を返す関数GetTargetName()を作り、それ以外の時はエラーメッセージを表示して終了するようにしました。
テスト用クラスのファイルを開く
次にテスト用のクラスファイルを決定しバッファとして開いてみます。
@@ -6,6 +6,13 @@
echomsg 'Not test target file: ' . expand('%')
return 0
endif
+
+ let testfile = s:GetTestFileName(target)
+ if strlen(testfile) <= 0 || target ==# testfile
+ echomsg 'Cannot generate test file name: ' . target
+ endif
+
+ call s:OpenFile(testfile)
endfunction " s:UtestAppend()
function! s:GetTargetName()
@@ -15,3 +22,13 @@
return ''
endif
endfunction " s:GetTargetName()
+
+function! s:GetTestFileName(target)
+ let testfile = a:target
+ let testfile = substitute(testfile, '\.java$', 'Test&', '')
+ return testfile
+endfunction " s:GetTestFileName()
+
+function! s:OpenFile(filepath)
+ execute 'split ' . a:filepath
+endfunction " s:OpenFile()
- GetTestFileName関数を作成: クラスのファイル名からテスト用クラスのファイル名を生成する
- OpenFile関数を作成: 指定したファイルを開く
テスト用のクラスの名前は私の好みでまずは *Test.java という形式にだけ対応させました。つまりテスト対象クラスがFooBar.javaならばテスト用クラスはFooBarTest.javaとなります。これはあとで拡張します。
これで基本機能は完成です。思ったよりもずっと簡単でしょう。
ディレクトリに対応
最近のJavaはmavenの標準ディレクトリ構成に従っていることも多いので、それに対応してみましょう。
@@ -25,10 +25,16 @@
function! s:GetTestFileName(target)
let testfile = a:target
+ let testfile = substitute(testfile, '\<src/main/java/', 'src/test/java/', '')
let testfile = substitute(testfile, '\.java$', 'Test&', '')
return testfile
endfunction " s:GetTestFileName()
function! s:OpenFile(filepath)
execute 'split ' . a:filepath
+
+ let dir = expand('%:h')
+ if !isdirectory(dir)
+ call mkdir(dir, 'p')
+ endif
endfunction " s:OpenFile()
テスト対象クラスが src/main/java 下にあったらテスト用クラスを src/test/java 下に作るようにし、必要に応じてディレクトリを掘るようにしました。
これは本当に簡単ですね。
Test*.javaにも対応
私の好みで *Test.java だけに対応しましたが、既に Test*.java があるのならそちらを優先して開くようにしましょう。
@@ -16,7 +16,11 @@
endfunction " s:UtestAppend()
function! s:GetTargetName()
+ let curr = expand('%')
if expand('%:e') ==# 'java'
+ if curr =~# '\<src/test/java' || curr =~# 'Test.java$' || curr =~# 'Test\k\+.java$'
+ return ''
+ endif
return expand('%')
else
return ''
@@ -26,8 +30,13 @@
function! s:GetTestFileName(target)
let testfile = a:target
let testfile = substitute(testfile, '\<src/main/java/', 'src/test/java/', '')
- let testfile = substitute(testfile, '\.java$', 'Test&', '')
- return testfile
+ let testfile1 = substitute(testfile, '\.java$', 'Test&', '')
+ let testfile2 = substitute(testfile, '\k\+.java$', 'Test&', '')
+ if getfsize(testfile2) >= 0
+ return testfile2
+ else
+ return testfile1
+ endif
endfunction " s:GetTestFileName()
function! s:OpenFile(filepath)
ついでにテスト用クラスのテストは作らないようにしてみました。
最後に全体
最後に完成したファイルの全体を見てみましょう。
command! -nargs=0 UtestAppend call <SID>UtestAppend()
function! s:UtestAppend()
let target = s:GetTargetName()
if strlen(target) <= 0
echomsg 'Not test target file: ' . expand('%')
return 0
endif
let testfile = s:GetTestFileName(target)
if strlen(testfile) <= 0 || target ==# testfile
echomsg 'Cannot generate test file name: ' . target
endif
call s:OpenFile(testfile)
endfunction " s:UtestAppend()
function! s:GetTargetName()
let curr = expand('%')
if expand('%:e') ==# 'java'
if curr =~# '\<src/test/java' || curr =~# 'Test.java$' || curr =~# 'Test\k\+.java$'
return ''
endif
return expand('%')
else
return ''
endif
endfunction " s:GetTargetName()
function! s:GetTestFileName(target)
let testfile = a:target
let testfile = substitute(testfile, '\<src/main/java/', 'src/test/java/', '')
let testfile1 = substitute(testfile, '\.java$', 'Test&', '')
let testfile2 = substitute(testfile, '\k\+.java$', 'Test&', '')
if getfsize(testfile2) >= 0
return testfile2
else
return testfile1
endif
endfunction " s:GetTestFileName()
function! s:OpenFile(filepath)
execute 'split ' . a:filepath
let dir = expand('%:h')
if !isdirectory(dir)
call mkdir(dir, 'p')
endif
endfunction " s:OpenFile()
プラグインとして仕立てる、エラーハンドリングする、などなどの余地はかなりありますが、だいたい動くという意味ではこんな感じで良いのです。
「ね、簡単でしょう?」
(満面のドヤ顔で)
間違い訂正
2012/02/20 09:40
@kaoriya "バッファがJavaの時だけファイル名を返す関数GetTargetName()を作り"GetTargetName()がエラー時の処理だけでファイル名返してない気がします。 htn.to/6cPHha
— tyruさん (@tyru) 2012年2月19日
最後のファイル全体がなんかコピペ時にイロイロおかしくなってたみたいです。訂正しました。
2012/02/20 23:15
- diffが小さくなるようにしました
<, >, "
といった文字が正しく表示されていないのを訂正しました