diff options
author | David Schulz <david.schulz@qt.io> | 2019-07-15 12:50:29 +0200 |
---|---|---|
committer | David Schulz <david.schulz@qt.io> | 2019-07-17 06:21:23 +0000 |
commit | 3213e12ce7411efd05a544645aaa1ecd74e533a2 (patch) | |
tree | ae7187904453f530d4660832ff834371905cefaf /src/plugins/python/pythonindenter.cpp | |
parent | 2778a5adab13a16f4a6b3cda0980fa3b4f2b3a5e (diff) | |
download | qt-creator-3213e12ce7411efd05a544645aaa1ecd74e533a2.tar.gz |
rename PythonEditor plugin to Python
The plugin does not only contain a pure editor, but all kind of support
for a programming language like project and run support.
Change-Id: I1251367c8db2e7a54986415ffc5b860cb210de3c
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Diffstat (limited to 'src/plugins/python/pythonindenter.cpp')
-rw-r--r-- | src/plugins/python/pythonindenter.cpp | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/src/plugins/python/pythonindenter.cpp b/src/plugins/python/pythonindenter.cpp new file mode 100644 index 0000000000..dff38907ee --- /dev/null +++ b/src/plugins/python/pythonindenter.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "pythonindenter.h" +#include "pythonscanner.h" + +#include <texteditor/tabsettings.h> + +#include <algorithm> + +namespace Python { + +static bool isEmptyLine(const QString &t) +{ + return std::all_of(t.cbegin(), t.cend(), [] (QChar c) { return c.isSpace(); }); +} + +static inline bool isEmptyLine(const QTextBlock &block) +{ + return isEmptyLine(block.text()); +} + +static QTextBlock previousNonEmptyBlock(const QTextBlock &block) +{ + QTextBlock result = block; + while (result.isValid() && isEmptyLine(result)) + result = result.previous(); + return result; +} + +PythonIndenter::PythonIndenter(QTextDocument *doc) + : TextEditor::TextIndenter(doc) +{} + +/** + * @brief Does given character change indentation level? + * @param ch Any value + * @return True if character increases indentation level at the next line + */ +bool PythonIndenter::isElectricCharacter(const QChar &ch) const +{ + return ch == ':'; +} + +int PythonIndenter::indentFor(const QTextBlock &block, + const TextEditor::TabSettings &tabSettings, + int /*cursorPositionInEditor*/) +{ + QTextBlock previousBlock = block.previous(); + if (!previousBlock.isValid()) + return 0; + + // When pasting in actual code, try to skip back past empty lines to an + // actual code line to find a suitable indentation. This prevents code from + // not being indented when pasting below an empty line. + if (!isEmptyLine(block)) { + const QTextBlock previousNonEmpty = previousNonEmptyBlock(previousBlock); + if (previousNonEmpty.isValid()) + previousBlock = previousNonEmpty; + } + + QString previousLine = previousBlock.text(); + int indentation = tabSettings.indentationColumn(previousLine); + + if (isElectricLine(previousLine)) + indentation += tabSettings.m_indentSize; + else + indentation = qMax<int>(0, indentation + getIndentDiff(previousLine, tabSettings)); + + return indentation; +} + +/// @return True if electric character is last non-space character at given string +bool PythonIndenter::isElectricLine(const QString &line) const +{ + if (line.isEmpty()) + return false; + + // trim spaces in 'if True: ' + int index = line.length() - 1; + while (index > 0 && line[index].isSpace()) + --index; + + return isElectricCharacter(line[index]); +} + +/// @return negative indent diff if previous line breaks control flow branch +int PythonIndenter::getIndentDiff(const QString &previousLine, + const TextEditor::TabSettings &tabSettings) const +{ + static const QStringList jumpKeywords = { + "return", "yield", "break", "continue", "raise", "pass" }; + + Internal::Scanner sc(previousLine.constData(), previousLine.length()); + forever { + Internal::FormatToken tk = sc.read(); + if (tk.format() == Internal::Format_Keyword && jumpKeywords.contains(sc.value(tk))) + return -tabSettings.m_indentSize; + if (tk.format() != Internal::Format_Whitespace) + break; + } + return 0; +} + +} // namespace Python |