aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeautocompleter.cpp135
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeautocompleter.h58
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeeditor.cpp7
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeindenter.cpp140
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeindenter.h54
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro8
-rw-r--r--src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs6
7 files changed, 404 insertions, 4 deletions
diff --git a/src/plugins/cmakeprojectmanager/cmakeautocompleter.cpp b/src/plugins/cmakeprojectmanager/cmakeautocompleter.cpp
new file mode 100644
index 0000000000..c74befd95b
--- /dev/null
+++ b/src/plugins/cmakeprojectmanager/cmakeautocompleter.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Jan Dalheimer <jan@dalheimer.de>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "cmakeautocompleter.h"
+
+#include <QTextCursor>
+#include <QTextBlock>
+#include <QDebug>
+
+#include <texteditor/tabsettings.h>
+
+namespace CMakeProjectManager {
+namespace Internal {
+
+CMakeAutoCompleter::CMakeAutoCompleter()
+{
+ setAutoParenthesesEnabled(true);
+}
+
+bool CMakeAutoCompleter::isInComment(const QTextCursor &cursor) const
+{
+ // NOTE: This doesn't handle '#' inside quotes, nor multi-line comments
+ QTextCursor moved = cursor;
+ moved.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
+ if (moved.selectedText().contains(QLatin1Char('#')))
+ return true;
+ else
+ return false;
+}
+
+bool CMakeAutoCompleter::isInString(const QTextCursor &cursor) const
+{
+ // NOTE: multiline strings are currently not supported, since they rarely, if ever, seem to be used
+ QTextCursor moved = cursor;
+ moved.movePosition(QTextCursor::StartOfLine);
+ const int positionInLine = cursor.position() - moved.position();
+ moved.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
+ const QString line = moved.selectedText();
+
+ bool isEscaped = false;
+ bool inString = false;
+ for (int i = 0; i < positionInLine; ++i) {
+ const QChar c = line.at(i);
+ if (c == QLatin1Char('\\') && !isEscaped)
+ isEscaped = true;
+ else if (c == QLatin1Char('"') && !isEscaped)
+ inString = !inString;
+ else
+ isEscaped = false;
+ }
+ return inString;
+}
+
+QString CMakeAutoCompleter::insertMatchingBrace(const QTextCursor &cursor, const QString &text, QChar la, int *skippedChars) const
+{
+ Q_UNUSED(cursor)
+ Q_UNUSED(skippedChars);
+ if (text.isEmpty())
+ return QString();
+ const QChar current = text.at(0);
+ switch (current.unicode()) {
+ case '"':
+ if (la != current)
+ return QStringLiteral("\"");
+ ++*skippedChars;
+ break;
+
+ case '(':
+ return QStringLiteral(")");
+
+ case ')':
+ if (current == la)
+ ++*skippedChars;
+ break;
+
+ default:
+ break;
+ }
+
+ return QString();
+}
+
+int CMakeAutoCompleter::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor, const TextEditor::TabSettings &tabSettings)
+{
+ const QString line = cursor.block().text().trimmed();
+ if (line.contains(QRegExp(QStringLiteral("^(endfunction|endmacro|endif|endforeach|endwhile)\\w*\("))))
+ tabSettings.indentLine(cursor.block(), tabSettings.indentationColumn(cursor.block().text()));
+ return 0;
+}
+
+bool CMakeAutoCompleter::contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert) const
+{
+ if (textToInsert.isEmpty())
+ return false;
+
+ const QChar c = textToInsert.at(0);
+ if (c == QLatin1Char('"') || c == QLatin1Char('(') || c == QLatin1Char(')'))
+ return !isInComment(cursor);
+ return false;
+}
+
+bool CMakeAutoCompleter::contextAllowsElectricCharacters(const QTextCursor &cursor) const
+{
+ return !isInComment(cursor) && !isInString(cursor);
+}
+
+} // namespace Internal
+} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakeautocompleter.h b/src/plugins/cmakeprojectmanager/cmakeautocompleter.h
new file mode 100644
index 0000000000..25bfa93ac4
--- /dev/null
+++ b/src/plugins/cmakeprojectmanager/cmakeautocompleter.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Jan Dalheimer <jan@dalheimer.de>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CMAKEAUTOCOMPLETER_H
+#define CMAKEAUTOCOMPLETER_H
+
+#include "cmake_global.h"
+
+#include <texteditor/autocompleter.h>
+
+namespace CMakeProjectManager {
+namespace Internal {
+
+class CMAKE_EXPORT CMakeAutoCompleter : public TextEditor::AutoCompleter
+{
+public:
+ CMakeAutoCompleter();
+ virtual ~CMakeAutoCompleter() {}
+
+ bool isInComment(const QTextCursor &cursor) const override;
+ bool isInString(const QTextCursor &cursor) const override;
+ QString insertMatchingBrace(const QTextCursor &cursor, const QString &text, QChar la, int *skippedChars) const override;
+ int paragraphSeparatorAboutToBeInserted(QTextCursor &cursor, const TextEditor::TabSettings &tabSettings) override;
+ bool contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert) const override;
+ bool contextAllowsElectricCharacters(const QTextCursor &cursor) const override;
+};
+
+} // namespace Internal
+} // namespace CMakeProjectManager
+
+#endif // CMAKEAUTOCOMPLETER_H
diff --git a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
index 89990da317..3cdd1eccfc 100644
--- a/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeeditor.cpp
@@ -33,6 +33,8 @@
#include "cmakefilecompletionassist.h"
#include "cmakeprojectconstants.h"
#include "cmakeproject.h"
+#include "cmakeindenter.h"
+#include "cmakeautocompleter.h"
#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
@@ -274,14 +276,17 @@ CMakeEditorFactory::CMakeEditorFactory()
setEditorCreator([]() { return new CMakeEditor; });
setEditorWidgetCreator([]() { return new CMakeEditorWidget; });
setDocumentCreator([]() { return new CMakeDocument; });
+ setIndenterCreator([]() { return new CMakeIndenter; });
setUseGenericHighlighter(true);
setCommentStyle(Utils::CommentDefinition::HashStyle);
setCodeFoldingSupported(true);
setCompletionAssistProvider(new CMakeFileCompletionAssistProvider);
+ setAutoCompleterCreator([]() { return new CMakeAutoCompleter; });
setEditorActionHandlers(TextEditorActionHandler::UnCommentSelection
- | TextEditorActionHandler::JumpToFileUnderCursor);
+ | TextEditorActionHandler::JumpToFileUnderCursor
+ | TextEditorActionHandler::Format);
ActionContainer *contextMenu = ActionManager::createMenu(Constants::M_CONTEXT);
contextMenu->addAction(ActionManager::command(TextEditor::Constants::JUMP_TO_FILE_UNDER_CURSOR));
diff --git a/src/plugins/cmakeprojectmanager/cmakeindenter.cpp b/src/plugins/cmakeprojectmanager/cmakeindenter.cpp
new file mode 100644
index 0000000000..cb424dc17a
--- /dev/null
+++ b/src/plugins/cmakeprojectmanager/cmakeindenter.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Jan Dalheimer <jan@dalheimer.de>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "cmakeindenter.h"
+
+#include <QStack>
+#include <QDebug>
+
+#include <texteditor/tabsettings.h>
+#include <texteditor/textdocumentlayout.h>
+
+namespace CMakeProjectManager {
+namespace Internal {
+
+CMakeIndenter::CMakeIndenter()
+{
+}
+
+bool CMakeIndenter::isElectricCharacter(const QChar &ch) const
+{
+ return ch == QLatin1Char('(') || ch == QLatin1Char(')');
+}
+
+static bool lineContainsFunction(const QString &line, const QString &function)
+{
+ const int indexOfFunction = line.indexOf(function);
+ if (indexOfFunction == -1)
+ return false;
+ for (int i = 0; i < indexOfFunction; ++i) {
+ if (!line.at(i).isSpace())
+ return false;
+ }
+ for (int i = indexOfFunction + function.size(); i < line.size(); ++i) {
+ if (line.at(i) == QLatin1Char('('))
+ return true;
+ else if (!line.at(i).isSpace())
+ return false;
+ }
+ return false;
+}
+static bool lineStartsBlock(const QString &line)
+{
+ return lineContainsFunction(line, QStringLiteral("function")) ||
+ lineContainsFunction(line, QStringLiteral("macro")) ||
+ lineContainsFunction(line, QStringLiteral("foreach")) ||
+ lineContainsFunction(line, QStringLiteral("while")) ||
+ lineContainsFunction(line, QStringLiteral("if")) ||
+ lineContainsFunction(line, QStringLiteral("elseif")) ||
+ lineContainsFunction(line, QStringLiteral("else"));
+}
+static bool lineEndsBlock(const QString &line)
+{
+ return lineContainsFunction(line, QStringLiteral("endfunction")) ||
+ lineContainsFunction(line, QStringLiteral("endmacro")) ||
+ lineContainsFunction(line, QStringLiteral("endforeach")) ||
+ lineContainsFunction(line, QStringLiteral("endwhile")) ||
+ lineContainsFunction(line, QStringLiteral("endif")) ||
+ lineContainsFunction(line, QStringLiteral("elseif")) ||
+ lineContainsFunction(line, QStringLiteral("else"));
+}
+static bool lineIsEmpty(const QString &line)
+{
+ for (const QChar &c : line) {
+ if (!c.isSpace())
+ return false;
+ }
+ return true;
+}
+
+static int paranthesesLevel(const QString &line)
+{
+ const QStringRef beforeComment = line.midRef(0, line.indexOf(QLatin1Char('#')));
+ const int opening = beforeComment.count(QLatin1Char('('));
+ const int closing = beforeComment.count(QLatin1Char(')'));
+ if (opening == closing)
+ return 0;
+ else if (opening > closing)
+ return 1;
+ else
+ return -1;
+}
+
+void CMakeIndenter::indentBlock(QTextDocument *doc, const QTextBlock &block, const QChar &typedChar, const TextEditor::TabSettings &tabSettings)
+{
+ Q_UNUSED(doc)
+ Q_UNUSED(typedChar)
+
+ QTextBlock previousBlock = block.previous();
+ // find the next previous block that is non-empty (contains non-whitespace characters)
+ while (previousBlock.isValid() && lineIsEmpty(previousBlock.text()))
+ previousBlock = previousBlock.previous();
+ if (previousBlock.isValid()) {
+ const QString previousLine = previousBlock.text();
+ const QString currentLine = block.text();
+ int indentation = tabSettings.indentationColumn(previousLine);
+
+ if (lineStartsBlock(previousLine))
+ indentation += tabSettings.m_indentSize;
+ if (lineEndsBlock(currentLine))
+ indentation = qMax(0, indentation - tabSettings.m_indentSize);
+
+ // increase/decrease/keep the indentation level depending on if we have more opening or closing parantheses
+ indentation = qMax(0, indentation + tabSettings.m_indentSize * paranthesesLevel(previousLine));
+
+ tabSettings.indentLine(block, indentation);
+ } else {
+ // First line in whole document
+ tabSettings.indentLine(block, 0);
+ }
+}
+
+} // namespace Internal
+} // namespace CMakeProjectManager
diff --git a/src/plugins/cmakeprojectmanager/cmakeindenter.h b/src/plugins/cmakeprojectmanager/cmakeindenter.h
new file mode 100644
index 0000000000..0e8c03ce4b
--- /dev/null
+++ b/src/plugins/cmakeprojectmanager/cmakeindenter.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Jan Dalheimer <jan@dalheimer.de>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CMAKEINDENTER_H
+#define CMAKEINDENTER_H
+
+#include "cmake_global.h"
+
+#include <texteditor/indenter.h>
+
+namespace CMakeProjectManager {
+namespace Internal {
+
+class CMAKE_EXPORT CMakeIndenter : public TextEditor::Indenter
+{
+public:
+ CMakeIndenter();
+ virtual ~CMakeIndenter() {}
+
+ bool isElectricCharacter(const QChar &ch) const override;
+ void indentBlock(QTextDocument *doc, const QTextBlock &block, const QChar &typedChar, const TextEditor::TabSettings &tabSettings) override;
+};
+
+} // namespace Internal
+} // namespace CMakeProjectManager
+
+#endif // CMAKEINDENTER_H
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro
index 355f996643..a4d06cf713 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.pro
@@ -24,7 +24,9 @@ HEADERS = cmakebuildinfo.h \
cmakekitconfigwidget.h \
cmakecbpparser.h \
cmakefile.h \
- cmakebuildsettingswidget.h
+ cmakebuildsettingswidget.h \
+ cmakeindenter.h \
+ cmakeautocompleter.h
SOURCES = cmakeproject.cpp \
cmakeprojectplugin.cpp \
@@ -46,7 +48,9 @@ SOURCES = cmakeproject.cpp \
cmakekitconfigwidget.cpp \
cmakecbpparser.cpp \
cmakefile.cpp \
- cmakebuildsettingswidget.cpp
+ cmakebuildsettingswidget.cpp \
+ cmakeindenter.cpp \
+ cmakeautocompleter.cpp
RESOURCES += cmakeproject.qrc
diff --git a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs
index 7679217062..eddd1c5d7e 100644
--- a/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs
+++ b/src/plugins/cmakeprojectmanager/cmakeprojectmanager.qbs
@@ -62,6 +62,10 @@ QtcPlugin {
"cmakesettingspage.h",
"cmakesettingspage.cpp",
"generatorinfo.h",
- "generatorinfo.cpp"
+ "generatorinfo.cpp",
+ "cmakeindenter.h",
+ "cmakeindenter.cpp",
+ "cmakeautocompleter.h",
+ "cmakeautocompleter.cpp"
]
}