summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Aumueller <aumuell@reserv.at>2008-12-26 10:36:40 +0100
committerhjk <qtc-committer@nokia.com>2009-01-13 11:14:03 +0100
commitd2c031d481e42cecaa94c0b21352ffc13b4bc709 (patch)
tree2100b69fa1ccf4478a6891c78e53ea4a817a0228 /src
parentb9a6f48151c3b2cc05c4028f163978e724600cf5 (diff)
downloadqt-creator-d2c031d481e42cecaa94c0b21352ffc13b4bc709.tar.gz
fakevim: implement automatic indenting and '=' for reindenting
Diffstat (limited to 'src')
-rw-r--r--src/plugins/fakevim/fakevim.pro3
-rw-r--r--src/plugins/fakevim/fakevimhandler.cpp124
2 files changed, 122 insertions, 5 deletions
diff --git a/src/plugins/fakevim/fakevim.pro b/src/plugins/fakevim/fakevim.pro
index 2165ffed20..2c85f8c50b 100644
--- a/src/plugins/fakevim/fakevim.pro
+++ b/src/plugins/fakevim/fakevim.pro
@@ -2,10 +2,13 @@ TEMPLATE = lib
TARGET = FakeVim
# CONFIG += single
+include(../../libs/cplusplus/cplusplus.pri)
include(../../qworkbenchplugin.pri)
include(../../plugins/projectexplorer/projectexplorer.pri)
include(../../plugins/coreplugin/coreplugin.pri)
include(../../plugins/texteditor/texteditor.pri)
+include(../../plugins/texteditor/cppeditor.pri)
+include(../../../shared/indenter/indenter.pri)
# DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII
QT += gui
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 9754adb253..b93bacb823 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -53,6 +53,11 @@
#include <QtGui/QTextDocumentFragment>
#include <QtGui/QTextEdit>
+#include <texteditor/basetexteditor.h>
+#include <texteditor/textblockiterator.h>
+#include <cppeditor/cppeditor.h>
+
+#include <indenter.h>
using namespace FakeVim::Internal;
using namespace FakeVim::Constants;
@@ -99,6 +104,7 @@ enum SubMode
FilterSubMode,
ReplaceSubMode,
YankSubMode,
+ IndentSubMode,
ZSubMode,
};
@@ -181,6 +187,13 @@ private:
int linesInDocument() const;
void scrollToLineInDocument(int line);
+ // helper functions for indenting
+ bool isElectricCharacter(QChar c) const { return (c == '{' || c == '}' || c == '#'); }
+ int indentDist() const;
+ void insertIndent();
+ void indentRegion(QTextBlock first, QTextBlock last, QChar typedChar=0);
+ void indentCurrentLine(QChar typedChar);
+
void moveToFirstNonBlankOnLine();
void moveToDesiredColumn();
void moveToNextWord(bool simple);
@@ -204,6 +217,7 @@ private:
public:
QTextEdit *m_textedit;
QPlainTextEdit *m_plaintextedit;
+ TextEditor::BaseTextEditor *m_texteditor;
bool m_wasReadOnly; // saves read-only state of document
FakeVimHandler *q;
@@ -285,6 +299,7 @@ FakeVimHandler::Private::Private(FakeVimHandler *parent)
m_gflag = false;
m_textedit = 0;
m_plaintextedit = 0;
+ m_texteditor = 0;
m_visualMode = NoVisualMode;
m_desiredColumn = 0;
@@ -390,6 +405,17 @@ void FakeVimHandler::Private::finishMovement(const QString &dotCommand)
m_submode = NoSubMode;
} else if (m_submode == ReplaceSubMode) {
m_submode = NoSubMode;
+ } else if (m_submode == IndentSubMode) {
+ QTextDocument *doc = EDITOR(document());
+ int start = m_tc.selectionStart();
+ int end = m_tc.selectionEnd();
+ if (start > end)
+ std::swap(start, end);
+ QTextBlock startBlock = doc->findBlock(start);
+ indentRegion(doc->findBlock(start), doc->findBlock(end).next());
+ m_tc.setPosition(startBlock.position());
+ moveToFirstNonBlankOnLine();
+ m_submode = NoSubMode;
}
m_mvcount.clear();
m_opcount.clear();
@@ -547,6 +573,8 @@ bool FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
else
m_tc.deleteChar();
m_tc.insertText(text);
+ } else if (m_submode == IndentSubMode && key == '=') {
+ indentRegion(m_tc.block(), m_tc.block().next());
finishMovement();
} else if (m_submode == ZSubMode) {
if (key == Key_Return) {
@@ -639,6 +667,8 @@ bool FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
for (int i = count(); --i >= 0; )
foreach (QChar c, m_dotCommand)
handleKey(c.unicode(), QString(c));
+ } else if (key == '=') {
+ m_submode = IndentSubMode;
} else if (key == 'a') {
m_mode = InsertMode;
m_lastInsertion.clear();
@@ -769,15 +799,21 @@ bool FakeVimHandler::Private::handleCommandMode(int key, const QString &text)
search(lastSearchString(), m_lastSearchForward);
} else if (key == 'N') {
search(lastSearchString(), !m_lastSearchForward);
- } else if (key == 'o') {
+ } else if (key == 'o' || key == 'O') {
enterInsertMode();
+ moveToFirstNonBlankOnLine();
+ int numSpaces = leftDist();
+ m_tc.movePosition(Up, MoveAnchor, 1);
+ if (key == 'o')
+ m_tc.movePosition(Down, MoveAnchor, 1);
m_tc.movePosition(EndOfLine, MoveAnchor);
m_tc.insertText("\n");
- } else if (key == 'O') {
- enterInsertMode();
m_tc.movePosition(StartOfLine, MoveAnchor);
- m_tc.movePosition(Left, MoveAnchor, 1);
- m_tc.insertText("\n");
+ if (m_texteditor && m_texteditor->tabSettings().m_autoIndent) {
+ insertIndent();
+ } else {
+ m_tc.insertText(QString(numSpaces, ' '));
+ }
} else if (key == 'p' || key == 'P') {
QString text = m_registers[m_register];
int n = text.count(QChar(ParagraphSeparator));
@@ -907,6 +943,7 @@ bool FakeVimHandler::Private::handleInsertMode(int key, const QString &text)
m_submode = NoSubMode;
m_tc.insertBlock();
m_lastInsertion += "\n";
+ indentRegion(m_tc.block(), m_tc.block().next());
} else if (key == Key_Backspace || key == control('h')) {
m_tc.deletePreviousChar();
m_lastInsertion = m_lastInsertion.left(m_lastInsertion.size() - 1);
@@ -932,6 +969,24 @@ bool FakeVimHandler::Private::handleInsertMode(int key, const QString &text)
m_tc.deleteChar();
}
m_tc.insertText(text);
+ if (m_texteditor && m_texteditor->tabSettings().m_autoIndent && isElectricCharacter(text.at(0))) {
+ const QString leftText = m_tc.block().text()
+ .left(m_tc.position() - 1 - m_tc.block().position());
+ if (leftText.simplified().isEmpty())
+ {
+ if (m_tc.hasSelection())
+ {
+ QTextDocument *doc = EDITOR(document());
+ QTextBlock block = doc->findBlock(qMin(m_tc.selectionStart(),
+ m_tc.selectionEnd()));
+ const QTextBlock end = doc->findBlock(qMax(m_tc.selectionStart(),
+ m_tc.selectionEnd())).next();
+ indentRegion(block, end, text.at(0));
+ }
+ else
+ indentCurrentLine(text.at(0));
+ }
+ }
} else {
return false;
}
@@ -1255,6 +1310,65 @@ void FakeVimHandler::Private::moveToFirstNonBlankOnLine()
}
}
+int FakeVimHandler::Private::indentDist() const
+{
+ if (!m_texteditor)
+ return 0;
+
+ TextEditor::TabSettings ts = m_texteditor->tabSettings();
+ typedef SharedTools::Indenter<TextEditor::TextBlockIterator> Indenter;
+ Indenter &indenter = Indenter::instance();
+ indenter.setIndentSize(ts.m_indentSize);
+ indenter.setTabSize(ts.m_tabSize);
+
+ QTextDocument *doc = EDITOR(document());
+ const TextEditor::TextBlockIterator current(m_tc.block());
+ const TextEditor::TextBlockIterator begin(doc->begin());
+ const TextEditor::TextBlockIterator end(m_tc.block().next());
+ return indenter.indentForBottomLine(current, begin, end, QChar(' '));
+}
+
+void FakeVimHandler::Private::insertIndent()
+{
+ const int indent = indentDist();
+ QString text;
+ for(int i = 0; i < indent; ++i)
+ text += ' ';
+ m_tc.insertText(text);
+}
+
+void FakeVimHandler::Private::indentRegion(QTextBlock begin, QTextBlock end, QChar typedChar)
+{
+ if (!m_texteditor)
+ return;
+
+ TextEditor::TabSettings ts = m_texteditor->tabSettings();
+ typedef SharedTools::Indenter<TextEditor::TextBlockIterator> Indenter;
+ Indenter &indenter = Indenter::instance();
+ indenter.setIndentSize(ts.m_indentSize);
+ indenter.setTabSize(ts.m_tabSize);
+
+ QTextDocument *doc = EDITOR(document());
+ const TextEditor::TextBlockIterator docStart(doc->begin());
+ for(QTextBlock cur = begin; cur != end; cur = cur.next()) {
+ if (typedChar != 0 && cur.text().simplified().isEmpty()) {
+ m_tc.setPosition(cur.position(), KeepAnchor);
+ while (!m_tc.atBlockEnd())
+ m_tc.deleteChar();
+ } else {
+ const TextEditor::TextBlockIterator current(cur);
+ const TextEditor::TextBlockIterator next(cur.next());
+ const int indent = indenter.indentForBottomLine(current, docStart, next, typedChar);
+ ts.indentLine(cur, indent);
+ }
+ }
+}
+
+void FakeVimHandler::Private::indentCurrentLine(QChar typedChar)
+{
+ indentRegion(m_tc.block(), m_tc.block().next(), typedChar);
+}
+
void FakeVimHandler::Private::moveToDesiredColumn()
{
if (m_desiredColumn == -1 || m_tc.block().length() <= m_desiredColumn) {