[cci]insertSurrounding()[/cci] の中身を埋める。
まず文字単位の場合。包囲文字列を挿入する方法として、2 つのアプローチが考えられる。まず、包囲文字列が挿入される左端と右端それぞれで囲まれた領域を選択し、包囲文字列を連結した文字列で上書きするというもの。こちらの方が undo クラスタのサイズが小さく、またコードもシンプルだ。
もう 1 つは、挿入される左端の位置にカーソルを移動させ、包囲文字列(左)を挿入。右端にカーソルを移動させ、包囲文字列(右)を挿入。最期に包囲文字列(左)の先頭へカーソルを戻す…というもの。コードは第 1 アプローチに比べるとやや冗長になる。
どちらを選択するのかといえば、第 2 アプローチになる。なぜなら選択領域内にマークが設定してある場合、第 1 アプローチだと選択領域を一旦削除した段階でマークが折りたたまれてしまうからだ。
次に行単位の場合。これが面倒。行単位の包囲文字列の挿入は、例えば
....abc
....def
....ghi....
のような状態([cci].[/cci] は U+0020 を表す)で 1行目にカーソルがある時 [cci]ySG”[/cci] すると
...."
........abc
........def
........ghi
...."....
という感じになる。
- 左の包囲文字列を挿入する位置は、選択範囲の左端点のある行の、最初の非空白文字の直前
- 右の包囲文字列を挿入する位置は、選択範囲の右端点のある行の、最後の非空白文字の直後
- 包囲される領域の内容は、左の包囲文字列のインデントレベルからさらに 1 つインデントさせる
- 右の包囲文字列の直前位置には、左の包囲文字列のインデントレベルと同じだけの空白文字を挿入する
くらいが気をつける点だ。前述の通り、本来は 3. については [cci]=[/cci] コマンドによって再インデントさせなければならないのだが、wasavi はそれをまだ実装していないので、代替として単に shift させることになる。
というわけでそういうふうに組んだ。マーク位置を壊さないために冗長なアプローチを選択する必要があるのは文字志向の場合と同じ。
* * *
レジスタの内容についてなのだけど、surround.vim の s:dosurround() で [cci]”[/cci] レジスタの退避と復帰をやっている。つまり番号付きレジスタや [cci]-[/cci] レジスタが更新されるのは考慮から漏れてるだけで、基本的にはレジスタの内容は包囲文字列の挿入によって変化させないという方向性なのかもしれない。
というわけでそういうふうにした。つまり一切レジスタの内容は更新しないようにした。