ひとつ難しいバグを見つけた。
ex コマンド [cci]wq[/cci] は、write-and-quit の略であり、まさにそのように動作する。これは実質的に [cci]write|quit[/cci] のシノニムであり、全く同じ働きをする。同じ働きというのは、エラー処理も含まれる。つまりこのとき、もし [cci]write[/cci] が何らかのエラーを返したなら、後続の [cci]quit[/cci] コマンドは実行されない。また、保存に失敗したわけなので、もし保存前にダーティフラグが立っていたならば、それは変化しない。ダーティーフラグというのは、最後に保存したテキストの状態から編集が行われているかということを示すものであり、今回のバグの主役はそれだ。
一方で、wasavi での [cci]write[/cci] コマンドの実装は若干特殊である。というのは、write コマンドで直接対象に書き込むわけではなくバッファリングを行うだけで処理を終えるからだ。そういうわけで write の実行結果は必ずしも書き込みが成功したかを示すようにはなってない。が、前述の通り wq は本来 write の実行結果に依存した処理を行わなければならないので、現状だと write エラーの場合に正しく動作していない。現状ではバッファリングが成功した時点でダーティフラグも降ろしているが、本来なら保存処理が完全に成功したことを確認した後じゃないといけない。
ここで、じゃあバッファリングしなければいいじゃんというふうにはならない。特に dropbox などの外部ストレージサービスに書き込む場合にその処理が完了するまではけっこうな間がある。つまりバッファリングが必要な場合としてはいけない場合があるということだ。具体的には ex コマンド列の最後の要素が write コマンドの場合のみバッファリングを許可し、そうではない場合は即書き込み動作に入ってその結果を待つようにしないといけない。
そういうわけで、状況によって細かい場合分けをする必要がある。
write | wq | xit | ||
---|---|---|---|---|
write 動作 | コマンド列の最後 | バッファリングする | 即書き込み、完了を待つ | 編集済みであれば、即書き込み、完了を待つ |
最後ではない | 即書き込み、完了を待つ | |||
quit 動作 | 編集済み | – | write 完了後、write エラーでなければ quit | write 完了後、write エラーでなければ quit |
編集済みでない | xit コマンドのコンテキスト内で即 quit |
ところであんまり関係ないんだけど、ex コマンド xit って使ったことない。位置づけとしては、タイムスタンプを不必要に更新しない wq ということなのだが。その機能ってむしろ write が標準で持っていてもいいと思うのです。write で更新されてる時だけ書き込み、write! なら常に書き込み動作みたいな。