前へ 次へ
技術文章qvi

お次は空行へジャンプするコマンド } { を実装してみよう。

} は文書末尾方向に、{ は文書先頭方向に空行を検索する。空行が存在しない場合は最後の行・最初の行にカーソル移動する。
数値を前置した場合は、その数だけ空行を検索する。

実装

ViMoveOperation にシンボルを追加し、doViCommand() で '}'、'{' を見つけたら、moveCursor() をコールするだけだ。 moveCursor() の中では switch 文で処理を分け、実際にカーソル移動する関数 gotoBlankLine() をコールしている。

ViEngine::doViCommand() から直接 gotoBlankLine() をコールした方が、余計な中間管理が入らずいいような気もする。 後で要検討。

 1: namespace ViMoveOperation {
 2:     enum {
 3:         Left = 100,             //  h
 4:         .....
 5:         NextBlankLine,          //  }
 6:         PrevBlankLine,          //  {
 7:     };
 8: }
 1: bool ViEngine::doViCommand(const QChar &qch)
 2: {
 3:     .....
 4:     switch( ch ) {
 5:         .....
 6:     case '}':
 7:         cursorMoved = moveCursor(cur, ViMoveOperation::NextBlankLine, repeatCount());
 8:         break;
 9:     case '{':
10:         cursorMoved = moveCursor(cur, ViMoveOperation::PrevBlankLine, repeatCount());
11:         break;
12:     }
13:     .....
14: }
 1: bool moveCursor(QTextCursor &cur, int mv, int n)
 2: {
 3:     .....
 4:     switch( mv ) {
 5:         .....
 6:     case ViMoveOperation::NextBlankLine:
 7:         return gotoBlankLine(cur, /*forward=*/true, n);
 8:     case ViMoveOperation::PrevBlankLine:
 9:         return gotoBlankLine(cur, /*forward=*/false, n);
10:     }
11:     .....
12: }

実際に空行を探す関数は以下の様になる。 テキストブロックから文字列を取り出し、その長さをチェックすることで空行かどうかを判定している。

 1: bool gotoBlankLine(QTextCursor &cur, bool forward, int n)
 2: {
 3:     QTextBlock block = cur.block();
 4:     if( !block.isValid() ) return false;
 5:     int lastPos = block.position();
 6:     while( --n >= 0 ) {
 7:         //  空行を読み飛ばす
 8:         while( block.text().length() == 0 ) {
 9:             block = forward ? block.next() : block.previous();
10:             if( !block.isValid() ) {
11:                 cur.setPosition(lastPos);
12:                 return true;
13:             }
14:             lastPos = block.position();
15:         }
16:         //  空行まで読み飛ばす
17:         while( block.text().length() != 0 ) {
18:             block = forward ? block.next() : block.previous();
19:             if( !block.isValid() ) {
20:                 cur.setPosition(lastPos);
21:                 return true;
22:             }
23:             lastPos = block.position();
24:         }
25:     }
26:     cur.setPosition(lastPos);
27:     return true;
28: }

Tweet


前へ 次へ
技術文章qvi