ここ数日、qvi に自動テスト機能を実装してて、本シリーズの執筆をさぼってた。
自動テストはある程度動きだしたんだけど、:test <テストスクリプトファイル名> というのも何度も手で入力するのが億劫になってきたので、
コマンドラインモードで 上下カーソルキーを押すと、過去のexコマンド履歴を呼び出し出来るようにした。
本稿はその解説である。
履歴を呼び出すには、まず履歴を保存しておかなくてはいけない。どのクラスが履歴情報を保持すべきは色々候補があるが、 とりあえずは素直に ViEngine が QStringList で履歴情報を保持することにする。
1: class ViEngine : public QObject
2: {
3: .....
4: public:
5: const QStringList &exCommands() const { return m_exCommands; }
6: .....
7: private:
8: QStringList m_exCommands; // 入力された ex-command 文字列
9: };
次は ex コマンドが確定した時点で m_exCommands を更新する。 無制限にテキストを保持するのはメモリ消費的にいかがなものかと考えられるので、とりあえず上限を100個にしておいた。
履歴情報は qvi を終了・再起動した時にも利用したいので、QSettings を使って(Windows ならばレジストリに)保存しておく。
1: void ViEngine::doExCommand(const QString &text)
2: {
3: if( text.isEmpty() ) return;
4: m_exCommands.removeOne(text); // 重複削除
5: m_exCommands.push_back(text);
6: if( m_exCommands.count() > 100 )
7: m_exCommands.pop_front();
8: QSettings settings;
9: settings.setValue("recentExCmdList", m_exCommands);
10: .....
11: }
保存したコマンド履歴は、以下のようにコンストラクタで復帰することにした。
1: ViEngine::ViEngine(QObject *parent)
2: : .....
3: {
4: QSettings settings;
5: m_exCommands = settings.value("recentExCmdList").toStringList();
6: }
次に、コマンドラインモードで上下カーソルキーが押された場合の処理。
1: bool MainWindow::eventFilter(QObject *obj, QEvent *event)
2: {
3: if( obj == m_cmdLineEdit && event->type() == QEvent::KeyPress &&
4: m_viEngine->mode() == CMDLINE )
5: {
6: QKeyEvent *keyEvent = static_cast(event);
7: .....
8: const QStringList cmds = m_viEngine->exCommands();
9: if( m_cmdLineEdit->text()[0] == ':' && !cmds.isEmpty() ) {
10: if( keyEvent->key() == Qt::Key_Up ) {
11: if( --m_exCmdsIx < 0 ) m_exCmdsIx = cmds.count() - 1;
12: m_cmdLineEdit->setText(":" + cmds[m_exCmdsIx]);
13: return true;
14: }
15: if( keyEvent->key() == Qt::Key_Down ) {
16: if( ++m_exCmdsIx >= cmds.count() ) m_exCmdsIx = 0;
17: m_cmdLineEdit->setText(":" + cmds[m_exCmdsIx]);
18: return true;
19: }
20: }
21: }
22: return false;
23: }