前へ 次へ
技術文章qvi

本稿では、I a A コマンドを実装する。

最初に i コマンドで挿入モードに遷移するようにしたが、挿入モードに遷移するコマンドは i だけではない。 様々に移動しつつ挿入モードに遷移することができる。
a はカーソルをひとつ進めて挿入モードに遷移する。I は現在行の最初の非空白文字位置に移動して挿入モードに遷移する。 A は改行位置に移動して挿入モードに遷移する。わざわざカーソル移動してから挿入モードに遷移する必要がないので、打鍵回数が減る。

 1:     printf("hello, world.\n");

例えば上記の行にカーソルがあれば、どの文字にカーソルがあっても、I を押すと print の前に、A を押せば ; の直後に文字を挿入することができる。

実装

vi 独自の移動コマンドにはすべてシンボルを割り当てることにする。

 1: namespace ViMoveOperation {
 2:     enum {
 3:         Left = 100,             //  h
 4:         Down,                   //  j
 5:         Up,                     //  k
 6:         Right,                  //  l
 7:         RightForA,              //  a
 8:         FirstNonBlankChar,      //  ^
 9:         LastChar,               //  $
10:         NextLine,               //  + Enter
11:         PrevLine,               //  -
12:     };
13: }
 1: bool ViEngine::cmdModeKeyPressEvent(QKeyEvent *event)
 2: {
 3:     .....
 4:     case 'a':
 5:         m_editor->moveCursor(ViMoveOperation::RightForA);
 6:         //  下にスルー
 7:     case 'i':
 8:         setMode(INSERT);    //  i が押されたら挿入モードへ
 9:         break;
10:     case 'A':
11:         m_editor->moveCursor(QTextCursor::EndOfBlock);
12:         setMode(INSERT);
13:         break;
14:     case 'I':
15:         m_editor->moveCursor(ViMoveOperation::FirstNonBlankChar);
16:         setMode(INSERT);
17:         break;
18:     .....
19: }
 1: bool ViEngine::cmdModeKeyPressEvent(QKeyEvent *event)
 2: {
 3:     .....
 4:     switch( mv ) {
 5:     case ViMoveOperation::Up:
 6:         mv = QTextCursor::Up;
 7:         break;
 8:     case ViMoveOperation::Down:
 9:         mv = QTextCursor::Down;
10:         break;
11:     case ViMoveOperation::Left:
12:         n = qMin(n, pos - blockPos);
13:         mv = QTextCursor::Left;
14:         break;
15:     case ViMoveOperation::Right: {
16:         if( blockText.isEmpty() ) return;       //  改行 or EOF オンリー行の場合
17:         const int endpos = blockPos + blockText.length() - 1;
18:         if( pos >= endpos ) return;
19:         n = qMin(n, endpos - pos);
20:         mv = QTextCursor::Right;
21:         break;
22:     }
23:     case ViMoveOperation::RightForA:            //  右移動 for a コマンド
24:         if( blockText.isEmpty() ) return;       //  改行 or EOF オンリー行の場合
25:         if( pos >= blockPos + blockText.length() ) return;
26:         cur.setPosition(pos + 1);
27:         moved = true;
28:         break;
29:     .....
30:     }
31:     .....
32: }

Tweet


前へ 次へ
技術文章qvi