From ffce4b96110fd2d94dffca05b61419a379590cc6 Mon Sep 17 00:00:00 2001 From: Le Tan Date: Sat, 17 Jun 2017 19:02:42 +0800 Subject: [PATCH] vim-mode: message for Vim mode --- src/resources/styles/default.mdhl | 6 +- src/utils/veditutils.cpp | 13 ++ src/utils/veditutils.h | 3 + src/utils/vvim.cpp | 312 +++++++----------------------- src/utils/vvim.h | 5 + src/vconfigmanager.cpp | 13 +- src/vedit.h | 3 + src/veditarea.cpp | 9 + src/veditarea.h | 6 + src/veditoperations.cpp | 2 + src/veditoperations.h | 4 + src/vedittab.h | 3 + src/veditwindow.cpp | 10 + src/veditwindow.h | 6 + src/vhtmltab.cpp | 2 + src/vmainwindow.cpp | 8 + src/vmainwindow.h | 3 + src/vmdedit.cpp | 3 + src/vmdtab.cpp | 2 + 19 files changed, 161 insertions(+), 252 deletions(-) diff --git a/src/resources/styles/default.mdhl b/src/resources/styles/default.mdhl index 7d2ae18b..3debaa5c 100644 --- a/src/resources/styles/default.mdhl +++ b/src/resources/styles/default.mdhl @@ -14,10 +14,10 @@ background: 005fff editor-current-line background: c5cae9 -vim-insert-background: c5cae9 +vim-insert-background: e1bee7 vim-normal-background: a5d6a7 -vim-visual-background: a5d6a7 -vim-replace-background: a5d6a7 +vim-visual-background: 90caf9 +vim-replace-background: f8bbd0 H1 foreground: 111111 diff --git a/src/utils/veditutils.cpp b/src/utils/veditutils.cpp index 663d2f12..51aa2ee5 100644 --- a/src/utils/veditutils.cpp +++ b/src/utils/veditutils.cpp @@ -251,3 +251,16 @@ repeat: p_cursor.setPosition(block.position() + idx, p_mode); return true; } + +int VEditUtils::selectedBlockCount(const QTextCursor &p_cursor) +{ + if (!p_cursor.hasSelection()) { + return 0; + } + + QTextDocument *doc = p_cursor.document(); + int sbNum = doc->findBlock(p_cursor.selectionStart()).blockNumber(); + int ebNum = doc->findBlock(p_cursor.selectionEnd()).blockNumber(); + + return ebNum - sbNum + 1; +} diff --git a/src/utils/veditutils.h b/src/utils/veditutils.h index 209d0b3e..2cb609c1 100644 --- a/src/utils/veditutils.h +++ b/src/utils/veditutils.h @@ -71,6 +71,9 @@ public: bool p_forward, bool p_inclusive); + // Get the count of blocks selected. + static int selectedBlockCount(const QTextCursor &p_cursor); + private: VEditUtils() {} }; diff --git a/src/utils/vvim.cpp b/src/utils/vvim.cpp index 6c63c997..a9c22998 100644 --- a/src/utils/vvim.cpp +++ b/src/utils/vvim.cpp @@ -2119,6 +2119,9 @@ void VVim::processDeleteAction(QList &p_tokens) VEditUtils::removeBlock(cursor); } + message(tr("%1 fewer %2").arg(repeat).arg(repeat > 1 ? tr("lines") + : tr("line"))); + qDebug() << "delete" << repeat << "lines"; break; } @@ -2181,18 +2184,6 @@ void VVim::processDeleteAction(QList &p_tokens) if (hasMoved) { bool clearEmptyBlock = false; switch (to.m_movement) { - case Movement::Left: - { - qDebug() << "delete backward" << repeat << "chars"; - break; - } - - case Movement::Right: - { - qDebug() << "delete forward" << repeat << "chars"; - break; - } - case Movement::Up: { expandSelectionToWholeLines(cursor); @@ -2209,24 +2200,6 @@ void VVim::processDeleteAction(QList &p_tokens) break; } - case Movement::VisualUp: - { - qDebug() << "delete visual up" << repeat << "lines"; - break; - } - - case Movement::VisualDown: - { - qDebug() << "delete visual down" << repeat << "lines"; - break; - } - - case Movement::StartOfLine: - { - qDebug() << "delete till start of line"; - break; - } - case Movement::EndOfLine: { // End of line (block). @@ -2238,12 +2211,6 @@ void VVim::processDeleteAction(QList &p_tokens) break; } - case Movement::FirstCharacter: - { - qDebug() << "delete till first non-space character"; - break; - } - case Movement::LineJump: { expandSelectionToWholeLines(cursor); @@ -2268,58 +2235,16 @@ void VVim::processDeleteAction(QList &p_tokens) break; } - case Movement::WordForward: - { - qDebug() << "delete" << repeat << "words forward"; - break; - } - - case Movement::WORDForward: - { - qDebug() << "delete" << repeat << "WORDs forward"; - break; - } - - case Movement::ForwardEndOfWord: - { - qDebug() << "delete" << repeat << "end of words forward"; - break; - } - - case Movement::ForwardEndOfWORD: - { - qDebug() << "delete" << repeat << "end of WORDs forward"; - break; - } - - case Movement::WordBackward: - { - qDebug() << "delete" << repeat << "words backward"; - break; - } - - case Movement::WORDBackward: - { - qDebug() << "delete" << repeat << "WORDs backward"; - break; - } - - case Movement::BackwardEndOfWord: - { - qDebug() << "delete" << repeat << "end of words backward"; - break; - } - - case Movement::BackwardEndOfWORD: - { - qDebug() << "delete" << repeat << "end of WORDs backward"; - break; - } - default: break; } + if (clearEmptyBlock) { + int nrBlock = VEditUtils::selectedBlockCount(cursor); + message(tr("%1 fewer %2").arg(nrBlock).arg(nrBlock > 1 ? tr("lines") + : tr("line"))); + } + deleteSelectedText(cursor, clearEmptyBlock); } @@ -2359,7 +2284,7 @@ void VVim::processCopyAction(QList &p_tokens) switch (to.m_range) { case Range::Line: { - // yy, delete current line. + // yy, copy current line. if (repeat == -1) { repeat = 1; } @@ -2370,6 +2295,9 @@ void VVim::processCopyAction(QList &p_tokens) saveToRegister("\n"); } + message(tr("%1 %2 yanked").arg(repeat).arg(repeat > 1 ? tr("lines") + : tr("line"))); + qDebug() << "copy" << repeat << "lines"; break; } @@ -2437,18 +2365,6 @@ void VVim::processCopyAction(QList &p_tokens) if (changed) { bool addNewLine = false; switch (to.m_movement) { - case Movement::Left: - { - qDebug() << "copy backward" << repeat << "chars"; - break; - } - - case Movement::Right: - { - qDebug() << "copy forward" << repeat << "chars"; - break; - } - case Movement::Up: { expandSelectionToWholeLines(cursor); @@ -2465,24 +2381,6 @@ void VVim::processCopyAction(QList &p_tokens) break; } - case Movement::VisualUp: - { - qDebug() << "copy visual up" << repeat << "lines"; - break; - } - - case Movement::VisualDown: - { - qDebug() << "copy visual down" << repeat << "lines"; - break; - } - - case Movement::StartOfLine: - { - qDebug() << "copy till start of line"; - break; - } - case Movement::EndOfLine: { // End of line (block). @@ -2491,12 +2389,6 @@ void VVim::processCopyAction(QList &p_tokens) break; } - case Movement::FirstCharacter: - { - qDebug() << "copy till first non-space character"; - break; - } - case Movement::LineJump: { expandSelectionToWholeLines(cursor); @@ -2521,58 +2413,16 @@ void VVim::processCopyAction(QList &p_tokens) break; } - case Movement::WordForward: - { - qDebug() << "copy" << repeat << "words forward"; - break; - } - - case Movement::WORDForward: - { - qDebug() << "copy" << repeat << "WORDs forward"; - break; - } - - case Movement::ForwardEndOfWord: - { - qDebug() << "copy" << repeat << "end of words forward"; - break; - } - - case Movement::ForwardEndOfWORD: - { - qDebug() << "copy" << repeat << "end of WORDs forward"; - break; - } - - case Movement::WordBackward: - { - qDebug() << "copy" << repeat << "words backward"; - break; - } - - case Movement::WORDBackward: - { - qDebug() << "copy" << repeat << "WORDs backward"; - break; - } - - case Movement::BackwardEndOfWord: - { - qDebug() << "copy" << repeat << "end of words backward"; - break; - } - - case Movement::BackwardEndOfWORD: - { - qDebug() << "copy" << repeat << "end of WORDs backward"; - break; - } - default: break; } + if (addNewLine) { + int nrBlock = VEditUtils::selectedBlockCount(cursor); + message(tr("%1 %2 yanked").arg(nrBlock).arg(nrBlock > 1 ? tr("lines") + : tr("line"))); + } + copySelectedText(cursor, addNewLine); if (cursor.position() != oriPos) { cursor.setPosition(oriPos); @@ -2626,6 +2476,12 @@ void VVim::processPasteAction(QList &p_tokens, bool p_pasteBefore) // inserBlock() already insert a new line, so eliminate one here. cursor.insertText(text.left(text.size() - 1)); + + int nrBlock = text.count('\n'); + if (nrBlock > 0) { + message(tr("%1 more %2").arg(nrBlock).arg(nrBlock > 1 ? tr("lines") + : tr("line"))); + } } else { if (!p_pasteBefore && !cursor.atBlockEnd()) { // Insert behind current cursor. @@ -2944,6 +2800,15 @@ void VVim::processIndentAction(QList &p_tokens, bool p_isIndent) cursor, m_editConfig->m_tabSpaces, p_isIndent); + + if (p_isIndent) { + message(tr("%1 %2 >ed 1 time").arg(repeat).arg(repeat > 1 ? tr("lines") + : tr("line"))); + } else { + message(tr("%1 %2 1 ? tr("lines") + : tr("line"))); + } + break; } @@ -2989,6 +2854,16 @@ void VVim::processIndentAction(QList &p_tokens, bool p_isIndent) QTextCursor::KeepAnchor, to, repeat); + + int nrBlock = VEditUtils::selectedBlockCount(cursor); + if (p_isIndent) { + message(tr("%1 %2 >ed 1 time").arg(nrBlock).arg(nrBlock > 1 ? tr("lines") + : tr("line"))); + } else { + message(tr("%1 %2 1 ? tr("lines") + : tr("line"))); + } + VEditUtils::indentSelectedBlocks(doc, cursor, m_editConfig->m_tabSpaces, @@ -3021,6 +2896,12 @@ void VVim::processToLowerAction(QList &p_tokens, bool p_toLower) if (changed) { oriPos = cursor.selectionStart(); convertCaseOfSelectedText(cursor, p_toLower); + + if (to.m_range == Range::Line) { + message(tr("%1 %2 changed").arg(repeat == -1 ? 1 : repeat) + .arg(repeat > 1 ? tr("lines") : tr("line"))); + } + cursor.setPosition(oriPos); } @@ -3054,117 +2935,54 @@ void VVim::processToLowerAction(QList &p_tokens, bool p_toLower) if (changed) { oriPos = cursor.selectionStart(); + bool isBlock = false; switch (to.m_movement) { - case Movement::Left: - { - break; - } - - case Movement::Right: - { - break; - } - case Movement::Up: { + isBlock = true; expandSelectionToWholeLines(cursor); break; } case Movement::Down: { + isBlock = true; expandSelectionToWholeLines(cursor); break; } - case Movement::VisualUp: - { - break; - } - - case Movement::VisualDown: - { - break; - } - - case Movement::StartOfLine: - { - break; - } - - case Movement::EndOfLine: - { - break; - } - - case Movement::FirstCharacter: - { - break; - } - case Movement::LineJump: { + isBlock = true; expandSelectionToWholeLines(cursor); break; } case Movement::StartOfDocument: { + isBlock = true; expandSelectionToWholeLines(cursor); break; } case Movement::EndOfDocument: { + isBlock = true; expandSelectionToWholeLines(cursor); break; } - case Movement::WordForward: - { - break; - } - - case Movement::WORDForward: - { - break; - } - - case Movement::ForwardEndOfWord: - { - break; - } - - case Movement::ForwardEndOfWORD: - { - break; - } - - case Movement::WordBackward: - { - break; - } - - case Movement::WORDBackward: - { - break; - } - - case Movement::BackwardEndOfWord: - { - break; - } - - case Movement::BackwardEndOfWORD: - { - break; - } - default: break; } + if (isBlock) { + int nrBlock = VEditUtils::selectedBlockCount(cursor); + message(tr("%1 %2 changed").arg(nrBlock).arg(nrBlock > 1 ? tr("lines") + : tr("line"))); + } + convertCaseOfSelectedText(cursor, p_toLower); cursor.setPosition(oriPos); @@ -3556,3 +3374,9 @@ void VVim::repeatLastFindMovement(bool p_reverse) addMovementToken(mm, key); processCommand(m_tokens); } + +void VVim::message(const QString &p_msg) +{ + qDebug() << "vim msg:" << p_msg; + emit vimMessage(p_msg); +} diff --git a/src/utils/vvim.h b/src/utils/vvim.h index fa50be1a..51537c0e 100644 --- a/src/utils/vvim.h +++ b/src/utils/vvim.h @@ -42,6 +42,9 @@ signals: // Emit when current mode has been changed. void modeChanged(VimMode p_mode); + // Emit when VVim want to display some messages. + void vimMessage(const QString &p_msg); + private slots: // When user use mouse to select texts in Normal mode, we should change to // Visual mode. @@ -452,6 +455,8 @@ private: // Repeat m_lastFindToken. void repeatLastFindMovement(bool p_reverse); + void message(const QString &p_str); + VEdit *m_editor; const VEditConfig *m_editConfig; VimMode m_mode; diff --git a/src/vconfigmanager.cpp b/src/vconfigmanager.cpp index 0f91dac0..a8f4ec1d 100644 --- a/src/vconfigmanager.cpp +++ b/src/vconfigmanager.cpp @@ -330,7 +330,10 @@ QString VConfigManager::getLogFilePath() void VConfigManager::updateMarkdownEditStyle() { static const QString defaultCurrentLineBackground = "#C5CAE9"; - static const QString defaultCurrentLineVimBackground = "#A5D6A7"; + static const QString defaultVimNormalBg = "#A5D6A7"; + static const QString defaultVimInsertBg = "#E1BEE7"; + static const QString defaultVimVisualBg = "#90CAF9"; + static const QString defaultVimReplaceBg = "#F8BBD0"; static const QString defaultTrailingSpaceBackground = "#FFEBEE"; // Read style file .mdhl @@ -351,10 +354,10 @@ void VConfigManager::updateMarkdownEditStyle() parser.fetchMarkdownEditorStyles(mdEditPalette, mdEditFont, styles); m_editorCurrentLineBg = defaultCurrentLineBackground; - m_editorVimInsertBg = defaultCurrentLineBackground; - m_editorVimNormalBg = defaultCurrentLineVimBackground; - m_editorVimVisualBg = m_editorVimNormalBg; - m_editorVimReplaceBg = m_editorVimNormalBg; + m_editorVimInsertBg = defaultVimInsertBg; + m_editorVimNormalBg = defaultVimNormalBg; + m_editorVimVisualBg = defaultVimVisualBg; + m_editorVimReplaceBg = defaultVimReplaceBg; auto editorCurrentLineIt = styles.find("editor-current-line"); if (editorCurrentLineIt != styles.end()) { auto backgroundIt = editorCurrentLineIt->find("background"); diff --git a/src/vedit.h b/src/vedit.h index 2c713771..b6b8f333 100644 --- a/src/vedit.h +++ b/src/vedit.h @@ -89,6 +89,9 @@ signals: // Emit when m_config has been updated. void configUpdated(); + // Emit when want to show message in status bar. + void statusMessage(const QString &p_msg); + public slots: virtual void highlightCurrentLine(); diff --git a/src/veditarea.cpp b/src/veditarea.cpp index 1234712e..3dd432af 100644 --- a/src/veditarea.cpp +++ b/src/veditarea.cpp @@ -79,6 +79,8 @@ void VEditArea::insertSplitWindow(int idx) this, &VEditArea::handleOutlineChanged); connect(win, &VEditWindow::curHeaderChanged, this, &VEditArea::handleCurHeaderChanged); + connect(win, &VEditWindow::statusMessage, + this, &VEditArea::handleWindowStatusMessage); } void VEditArea::handleEditWindowStatusChanged(const VFile *p_file, @@ -90,6 +92,13 @@ void VEditArea::handleEditWindowStatusChanged(const VFile *p_file, } } +void VEditArea::handleWindowStatusMessage(const QString &p_msg) +{ + if (splitter->widget(curWindowIndex) == sender()) { + emit statusMessage(p_msg); + } +} + void VEditArea::removeSplitWindow(VEditWindow *win) { if (!win) { diff --git a/src/veditarea.h b/src/veditarea.h index 1602d36e..ffdedfd6 100644 --- a/src/veditarea.h +++ b/src/veditarea.h @@ -63,6 +63,9 @@ signals: void outlineChanged(const VToc &toc); void curHeaderChanged(const VAnchor &anchor); + // Emit when want to show message in status bar. + void statusMessage(const QString &p_msg); + protected: void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; @@ -95,6 +98,9 @@ private slots: const VEditTab *p_editTab, bool p_editMode); + // Handle the statusMessage signal of VEditWindow. + void handleWindowStatusMessage(const QString &p_msg); + private: void setupUI(); QVector > findTabsByFile(const VFile *p_file); diff --git a/src/veditoperations.cpp b/src/veditoperations.cpp index f2279944..0dc2a047 100644 --- a/src/veditoperations.cpp +++ b/src/veditoperations.cpp @@ -18,6 +18,8 @@ VEditOperations::VEditOperations(VEdit *p_editor, VFile *p_file) this, &VEditOperations::handleEditConfigUpdated); connect(m_vim, &VVim::modeChanged, this, &VEditOperations::handleVimModeChanged); + connect(m_vim, &VVim::vimMessage, + this, &VEditOperations::statusMessage); } void VEditOperations::insertTextAtCurPos(const QString &p_text) diff --git a/src/veditoperations.h b/src/veditoperations.h index ca9a6a60..f01804fb 100644 --- a/src/veditoperations.h +++ b/src/veditoperations.h @@ -27,6 +27,10 @@ public: // processed. virtual bool handleKeyPressEvent(QKeyEvent *p_event) = 0; +signals: + // Want to display a template message in status bar. + void statusMessage(const QString &p_msg); + protected slots: // Handle the update of VEditConfig of the editor. virtual void handleEditConfigUpdated(); diff --git a/src/vedittab.h b/src/vedittab.h index 4c0fc319..9ab34f93 100644 --- a/src/vedittab.h +++ b/src/vedittab.h @@ -93,6 +93,9 @@ signals: void statusChanged(); + // Emit when want to show message in status bar. + void statusMessage(const QString &p_msg); + private slots: // Called when app focus changed. void handleFocusChanged(QWidget *p_old, QWidget *p_now); diff --git a/src/veditwindow.cpp b/src/veditwindow.cpp index d12f4881..d8f8ac41 100644 --- a/src/veditwindow.cpp +++ b/src/veditwindow.cpp @@ -268,6 +268,8 @@ int VEditWindow::openFileInTab(VFile *p_file, OpenFileMode p_mode) this, &VEditWindow::handleCurHeaderChanged); connect(editor, &VEditTab::statusChanged, this, &VEditWindow::handleTabStatusChanged); + connect(editor, &VEditTab::statusMessage, + this, &VEditWindow::handleTabStatusMessage); int idx = appendEditTab(p_file, editor); return idx; @@ -576,6 +578,14 @@ void VEditWindow::handleTabStatusChanged() } } +void VEditWindow::handleTabStatusMessage(const QString &p_msg) +{ + int idx = indexOf(dynamic_cast(sender())); + if (idx == currentIndex()) { + emit statusMessage(p_msg); + } +} + void VEditWindow::updateFileInfo(const VFile *p_file) { if (!p_file) { diff --git a/src/veditwindow.h b/src/veditwindow.h index 5a0a1ef3..db4ac331 100644 --- a/src/veditwindow.h +++ b/src/veditwindow.h @@ -68,6 +68,9 @@ signals: void outlineChanged(const VToc &toc); void curHeaderChanged(const VAnchor &anchor); + // Emit when want to show message in status bar. + void statusMessage(const QString &p_msg); + private slots: bool handleTabCloseRequest(int index); void splitWindow(); @@ -85,6 +88,9 @@ private slots: void handleMoveLeftAct(); void handleMoveRightAct(); + // Handle the statusMessage signal of VEditTab. + void handleTabStatusMessage(const QString &p_msg); + private: void initTabActions(); void setupCornerWidget(); diff --git a/src/vhtmltab.cpp b/src/vhtmltab.cpp index 04a53bf5..797dcfac 100644 --- a/src/vhtmltab.cpp +++ b/src/vhtmltab.cpp @@ -39,6 +39,8 @@ void VHtmlTab::setupUI() this, &VHtmlTab::discardAndRead); connect(m_editor, &VEdit::editNote, this, &VHtmlTab::editFile); + connect(m_editor, &VEdit::statusMessage, + this, &VEditTab::statusMessage); m_editor->reloadFile(); QVBoxLayout *mainLayout = new QVBoxLayout(); diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index bde4a31e..a01dd1a1 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -109,6 +109,8 @@ void VMainWindow::setupUI() editArea, &VEditArea::handleFileUpdated); connect(editArea, &VEditArea::curTabStatusChanged, this, &VMainWindow::handleCurTabStatusChanged); + connect(editArea, &VEditArea::statusMessage, + this, &VMainWindow::showStatusMessage); connect(m_findReplaceDialog, &VFindReplaceDialog::findTextChanged, this, &VMainWindow::handleFindDialogTextChanged); @@ -1488,3 +1490,9 @@ QAction *VMainWindow::newAction(const QIcon &p_icon, return new QAction(p_icon, p_text, p_parent); #endif } + +void VMainWindow::showStatusMessage(const QString &p_msg) +{ + const int timeout = 3000; + statusBar()->showMessage(p_msg, timeout); +} diff --git a/src/vmainwindow.h b/src/vmainwindow.h index 29bc862d..1e0c68bb 100644 --- a/src/vmainwindow.h +++ b/src/vmainwindow.h @@ -85,6 +85,9 @@ private slots: void printNote(); void exportAsPDF(); + // Show a temporary message in status bar. + void showStatusMessage(const QString &p_msg); + protected: void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE; diff --git a/src/vmdedit.cpp b/src/vmdedit.cpp index 80295259..97c67360 100644 --- a/src/vmdedit.cpp +++ b/src/vmdedit.cpp @@ -51,6 +51,9 @@ VMdEdit::VMdEdit(VFile *p_file, VDocument *p_vdoc, MarkdownConverterType p_type, m_editOps = new VMdEditOperations(this, m_file); + connect(m_editOps, &VEditOperations::statusMessage, + this, &VEdit::statusMessage); + connect(this, &VMdEdit::cursorPositionChanged, this, &VMdEdit::updateCurHeader); diff --git a/src/vmdtab.cpp b/src/vmdtab.cpp index e8d9345e..5c24b6ef 100644 --- a/src/vmdtab.cpp +++ b/src/vmdtab.cpp @@ -58,6 +58,8 @@ void VMdTab::setupUI() this, &VMdTab::saveAndRead); connect(m_editor, &VEdit::discardAndRead, this, &VMdTab::discardAndRead); + connect(m_editor, &VEdit::statusMessage, + this, &VEditTab::statusMessage); m_editor->reloadFile(); m_stacks->addWidget(m_editor);