diff --git a/CMakeLists.txt b/CMakeLists.txt index f6d0148..2b936cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,14 +20,13 @@ set(${bin}_sources # Required pkg-config packages set(${bin}_pkg_config_requires) -include(cmake/cxx17.cmake) include(cmake/library.cmake) include(cmake/qt.cmake) include(cmake/pkg-config.cmake) # Files with Q_OBJECT macros to pass to moc utility set(CMAKE_INCLUDE_CURRENT_DIR ON) -qt5_wrap_cpp(${bin}_mocced "fakevim/fakevimhandler.h") +qt6_wrap_cpp(${bin}_mocced "fakevim/fakevimhandler.h") target_sources(${bin} PRIVATE ${${bin}_mocced}) target_compile_definitions(${bin} PRIVATE @@ -40,7 +39,7 @@ option(BUILD_TESTS "Build tests") if (BUILD_TESTS) message(STATUS "Building tests") - find_package(Qt5Test REQUIRED) + find_package(Qt6Test REQUIRED) add_executable(fakevim_test tests/fakevim_test.cpp @@ -48,7 +47,7 @@ if (BUILD_TESTS) example/editor.cpp ) set_property(TARGET fakevim_test PROPERTY AUTOMOC ON) - target_link_libraries(fakevim_test fakevim Qt5::Widgets Qt5::Test) + target_link_libraries(fakevim_test fakevim Qt6::Widgets Qt6::Test) target_include_directories(fakevim_test PRIVATE ${CMAKE_SOURCE_DIR}/fakevim @@ -67,5 +66,5 @@ if (BUILD_EXAMPLE) set_property(TARGET fakevim_example PROPERTY AUTOMOC ON) target_link_libraries(fakevim_example fakevim) - target_link_libraries(fakevim_example Qt5::Widgets) + target_link_libraries(fakevim_example Qt6::Widgets) endif() diff --git a/cmake/cxx17.cmake b/cmake/cxx17.cmake deleted file mode 100644 index 345814d..0000000 --- a/cmake/cxx17.cmake +++ /dev/null @@ -1,5 +0,0 @@ -if (${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION} GREATER 3.1) - set(CMAKE_CXX_STANDARD 17) -else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") -endif() diff --git a/cmake/library.cmake b/cmake/library.cmake index 0fa9c47..c9e64a3 100644 --- a/cmake/library.cmake +++ b/cmake/library.cmake @@ -16,6 +16,7 @@ else() endif() add_library(${bin} ${libtype} ${${bin}_sources}) +target_compile_features(${bin} PUBLIC cxx_std_20) set_target_properties(${bin} PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} diff --git a/cmake/qt.cmake b/cmake/qt.cmake index d8e698d..bedf5f4 100644 --- a/cmake/qt.cmake +++ b/cmake/qt.cmake @@ -1,6 +1,6 @@ -find_package(Qt5Widgets REQUIRED) +find_package(Qt6Widgets REQUIRED) -include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) -target_link_libraries(${bin} Qt5::Widgets) +include_directories(${Qt6Gui_PRIVATE_INCLUDE_DIRS}) +target_link_libraries(${bin} Qt6::Widgets) -set(${bin}_pkg_config_requires ${${bin}_pkg_config_requires} Qt5Widgets) +set(${bin}_pkg_config_requires ${${bin}_pkg_config_requires} Qt6Widgets) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index c5adce1..2e2942f 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -2,14 +2,14 @@ cmake_minimum_required(VERSION 2.8.8) project(fakevim_example) find_package(fakevim REQUIRED) -find_package(Qt5Widgets REQUIRED) +find_package(Qt6Widgets REQUIRED) set(bin fakevim_example) add_executable(${bin} main.cpp editor.cpp) set(CMAKE_INCLUDE_CURRENT_DIR ON) -qt5_generate_moc("editor.cpp" "editor.moc") +qt6_generate_moc("editor.cpp" "editor.moc") target_sources(${bin} PRIVATE "editor.moc") target_link_libraries(${bin} fakevim) -target_link_libraries(${bin} Qt5::Widgets) +target_link_libraries(${bin} Qt6::Widgets) diff --git a/example/editor.cpp b/example/editor.cpp index 23575b8..59bf722 100644 --- a/example/editor.cpp +++ b/example/editor.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -149,35 +150,35 @@ Proxy *connectSignals(FakeVimHandler *handler, QMainWindow *mainWindow, QWidget Proxy *proxy = new Proxy(editor, mainWindow, handler); handler->commandBufferChanged - .connect([proxy](const QString &contents, int cursorPos, int /*anchorPos*/, int /*messageLevel*/) { + .set([proxy](const QString &contents, int cursorPos, int /*anchorPos*/, int /*messageLevel*/) { proxy->changeStatusMessage(contents, cursorPos); }); - handler->extraInformationChanged.connect([proxy](const QString &text) { + handler->extraInformationChanged.set([proxy](const QString &text) { proxy->changeExtraInformation(text); }); - handler->statusDataChanged.connect([proxy](const QString &text) { + handler->statusDataChanged.set([proxy](const QString &text) { proxy->changeStatusData(text); }); - handler->highlightMatches.connect([proxy](const QString &needle) { + handler->highlightMatches.set([proxy](const QString &needle) { proxy->highlightMatches(needle); }); - handler->handleExCommandRequested.connect([proxy](bool *handled, const ExCommand &cmd) { + handler->handleExCommandRequested.set([proxy](bool *handled, const ExCommand &cmd) { proxy->handleExCommand(handled, cmd); }); - handler->requestSetBlockSelection.connect([proxy](const QTextCursor &cursor) { + handler->requestSetBlockSelection.set([proxy](const QTextCursor &cursor) { proxy->requestSetBlockSelection(cursor); }); - handler->requestDisableBlockSelection.connect([proxy] { + handler->requestDisableBlockSelection.set([proxy] { proxy->requestDisableBlockSelection(); }); - handler->requestHasBlockSelection.connect([proxy](bool *on) { + handler->requestHasBlockSelection.set([proxy](bool *on) { proxy->requestHasBlockSelection(on); }); - handler->indentRegion.connect([proxy](int beginBlock, int endBlock, QChar typedChar) { + handler->indentRegion.set([proxy](int beginBlock, int endBlock, QChar typedChar) { proxy->indentRegion(beginBlock, endBlock, typedChar); }); - handler->checkForElectricCharacter.connect([proxy](bool *result, QChar c) { + handler->checkForElectricCharacter.set([proxy](bool *result, QChar c) { proxy->checkForElectricCharacter(result, c); }); @@ -222,7 +223,7 @@ void Proxy::highlightMatches(const QString &pattern) selection.format.setForeground(Qt::black); // Highlight matches. - QRegExp re(pattern); + QRegularExpression re(pattern); QTextCursor cur = doc->find(re); m_searchSelection.clear(); diff --git a/fakevim/fakevimactions.cpp b/fakevim/fakevimactions.cpp index f8eee8d..5f59987 100644 --- a/fakevim/fakevimactions.cpp +++ b/fakevim/fakevimactions.cpp @@ -1,8 +1,9 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "fakevimactions.h" #include "fakevimhandler.h" +#include "fakevimtr.h" // Please do not add any direct dependencies to other Qt Creator code here. // Instead emit signals and let the FakeVimPlugin channel the information to @@ -58,40 +59,40 @@ FakeVimSettings::FakeVimSettings() setAutoApply(false); #ifndef FAKEVIM_STANDALONE - setup(&useFakeVim, false, "UseFakeVim", {}, tr("Use FakeVim")); + setup(&useFakeVim, false, "UseFakeVim", {}, Tr::tr("Use FakeVim")); #endif // Specific FakeVim settings - setup(&readVimRc, false, "ReadVimRc", {}, tr("Read .vimrc from location:")); - setup(&vimRcPath, QString(), "VimRcPath", {}, {}); // tr("Path to .vimrc") - setup(&showMarks, false, "ShowMarks", "sm", tr("Show position of text marks")); - setup(&passControlKey, false, "PassControlKey", "pck", tr("Pass control keys")); - setup(&passKeys, true, "PassKeys", "pk", tr("Pass keys in insert mode")); + setup(&readVimRc, false, "ReadVimRc", {}, Tr::tr("Read .vimrc from location:")); + setup(&vimRcPath, QString(), "VimRcPath", {}, {}); // Tr::tr("Path to .vimrc") + setup(&showMarks, false, "ShowMarks", "sm", Tr::tr("Show position of text marks")); + setup(&passControlKey, false, "PassControlKey", "pck", Tr::tr("Pass control keys")); + setup(&passKeys, true, "PassKeys", "pk", Tr::tr("Pass keys in insert mode")); // Emulated Vsetting - setup(&startOfLine, true, "StartOfLine", "sol", tr("Start of line")); - setup(&tabStop, 8, "TabStop", "ts", tr("Tabulator size:")); - setup(&smartTab, false, "SmartTab", "sta", tr("Smart tabulators")); - setup(&hlSearch, true, "HlSearch", "hls", tr("Highlight search results")); - setup(&shiftWidth, 8, "ShiftWidth", "sw", tr("Shift width:")); - setup(&expandTab, false, "ExpandTab", "et", tr("Expand tabulators")); - setup(&autoIndent, false, "AutoIndent", "ai", tr("Automatic indentation")); - setup(&smartIndent, false, "SmartIndent", "si", tr("Smart indentation")); - setup(&incSearch, true, "IncSearch", "is", tr("Incremental search")); - setup(&useCoreSearch, false, "UseCoreSearch", "ucs", tr("Use search dialog")); - setup(&smartCase, false, "SmartCase", "scs", tr("Use smartcase")); - setup(&ignoreCase, false, "IgnoreCase", "ic", tr("Use ignorecase")); - setup(&wrapScan, true, "WrapScan", "ws", tr("Use wrapscan")); - setup(&tildeOp, false, "TildeOp", "top", tr("Use tildeop")); - setup(&showCmd, true, "ShowCmd", "sc", tr("Show partial command")); - setup(&relativeNumber, false, "RelativeNumber", "rnu", tr("Show line numbers relative to cursor")); - setup(&blinkingCursor, false, "BlinkingCursor", "bc", tr("Blinking cursor")); - setup(&scrollOff, 0, "ScrollOff", "so", tr("Scroll offset:")); + setup(&startOfLine, true, "StartOfLine", "sol", Tr::tr("Start of line")); + setup(&tabStop, 8, "TabStop", "ts", Tr::tr("Tabulator size:")); + setup(&smartTab, false, "SmartTab", "sta", Tr::tr("Smart tabulators")); + setup(&hlSearch, true, "HlSearch", "hls", Tr::tr("Highlight search results")); + setup(&shiftWidth, 8, "ShiftWidth", "sw", Tr::tr("Shift width:")); + setup(&expandTab, false, "ExpandTab", "et", Tr::tr("Expand tabulators")); + setup(&autoIndent, false, "AutoIndent", "ai", Tr::tr("Automatic indentation")); + setup(&smartIndent, false, "SmartIndent", "si", Tr::tr("Smart indentation")); + setup(&incSearch, true, "IncSearch", "is", Tr::tr("Incremental search")); + setup(&useCoreSearch, false, "UseCoreSearch", "ucs", Tr::tr("Use search dialog")); + setup(&smartCase, false, "SmartCase", "scs", Tr::tr("Use smartcase")); + setup(&ignoreCase, false, "IgnoreCase", "ic", Tr::tr("Use ignorecase")); + setup(&wrapScan, true, "WrapScan", "ws", Tr::tr("Use wrapscan")); + setup(&tildeOp, false, "TildeOp", "top", Tr::tr("Use tildeop")); + setup(&showCmd, true, "ShowCmd", "sc", Tr::tr("Show partial command")); + setup(&relativeNumber, false, "RelativeNumber", "rnu", Tr::tr("Show line numbers relative to cursor")); + setup(&blinkingCursor, false, "BlinkingCursor", "bc", Tr::tr("Blinking cursor")); + setup(&scrollOff, 0, "ScrollOff", "so", Tr::tr("Scroll offset:")); setup(&backspace, "indent,eol,start", - "Backspace", "bs", tr("Backspace:")); + "Backspace", "bs", Tr::tr("Backspace:")); setup(&isKeyword, "@,48-57,_,192-255,a-z,A-Z", - "IsKeyword", "isk", tr("Keyword characters:")); - setup(&clipboard, {}, "Clipboard", "cb", tr("")); - setup(&formatOptions, {}, "formatoptions", "fo", tr("")); + "IsKeyword", "isk", Tr::tr("Keyword characters:")); + setup(&clipboard, {}, "Clipboard", "cb", Tr::tr("")); + setup(&formatOptions, {}, "formatoptions", "fo", Tr::tr("")); // Emulated plugins setup(&emulateVimCommentary, false, "commentary", {}, "vim-commentary"); @@ -101,19 +102,19 @@ FakeVimSettings::FakeVimSettings() setup(&emulateSurround, false, "surround", {}, "vim-surround"); // Some polish - useFakeVim.setDisplayName(tr("Use Vim-style Editing")); + useFakeVim.setDisplayName(Tr::tr("Use Vim-style Editing")); - relativeNumber.setToolTip(tr("Displays line numbers relative to the line containing " + relativeNumber.setToolTip(Tr::tr("Displays line numbers relative to the line containing " "text cursor.")); - passControlKey.setToolTip(tr("Does not interpret key sequences like Ctrl-S in FakeVim " + passControlKey.setToolTip(Tr::tr("Does not interpret key sequences like Ctrl-S in FakeVim " "but handles them as regular shortcuts. This gives easier access to core functionality " "at the price of losing some features of FakeVim.")); - passKeys.setToolTip(tr("Does not interpret some key presses in insert mode so that " + passKeys.setToolTip(Tr::tr("Does not interpret some key presses in insert mode so that " "code can be properly completed and expanded.")); - tabStop.setToolTip(tr("Vim tabstop option.")); + tabStop.setToolTip(Tr::tr("Vim tabstop option.")); #ifndef FAKEVIM_STANDALONE backspace.setDisplayStyle(FvStringAspect::LineEditDisplay); @@ -121,15 +122,15 @@ FakeVimSettings::FakeVimSettings() const QString vimrcDefault = QLatin1String( #ifdef Q_OS_UNIX - "$HOME/.vimrc" + "$HOME/.vimrc" #else - "%USERPROFILE%\\_vimrc" + "%USERPROFILE%\\_vimrc" #endif - ) + ); vimRcPath.setExpectedKind(PathChooser::File); - vimRcPath.setToolTip(tr("Keep empty to use the default path, i.e. " + vimRcPath.setToolTip(Tr::tr("Keep empty to use the default path, i.e. " "%USERPROFILE%\\_vimrc on Windows, ~/.vimrc otherwise.")); - vimRcPath.setPlaceHolderText(tr("Default: %1").arg(vimrcDefault)); + vimRcPath.setPlaceHolderText(Tr::tr("Default: %1").arg(vimrcDefault)); vimRcPath.setDisplayStyle(FvStringAspect::PathChooserDisplay); #endif } @@ -145,10 +146,10 @@ QString FakeVimSettings::trySetValue(const QString &name, const QString &value) { FvBaseAspect *aspect = m_nameToAspect.value(name, nullptr); if (!aspect) - return tr("Unknown option: %1").arg(name); + return Tr::tr("Unknown option: %1").arg(name); if (aspect == &tabStop || aspect == &shiftWidth) { if (value.toInt() <= 0) - return tr("Argument must be positive: %1=%2") + return Tr::tr("Argument must be positive: %1=%2") .arg(name).arg(value); } aspect->setValue(value); diff --git a/fakevim/fakevimactions.h b/fakevim/fakevimactions.h index 802f448..5aead73 100644 --- a/fakevim/fakevimactions.h +++ b/fakevim/fakevimactions.h @@ -1,9 +1,11 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once +#ifndef FAKEVIM_STANDALONE #define FAKEVIM_STANDALONE +#endif #ifdef FAKEVIM_STANDALONE # include "private/fakevim_export.h" @@ -79,8 +81,6 @@ using FvStringAspect = Utils::StringAspect; class FAKEVIM_EXPORT FakeVimSettings final : public FvAspectContainer { - Q_DECLARE_TR_FUNCTIONS(FakeVim) - public: FakeVimSettings(); ~FakeVimSettings(); diff --git a/fakevim/fakevimhandler.cpp b/fakevim/fakevimhandler.cpp index ec00168..4fbab50 100644 --- a/fakevim/fakevimhandler.cpp +++ b/fakevim/fakevimhandler.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 // // ATTENTION: @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -832,45 +831,6 @@ static void setClipboardData(const QString &content, RangeMode mode, clipboard->setMimeData(data, clipboardMode); } -static QByteArray toLocalEncoding(const QString &text) -{ -#if defined(Q_OS_WIN) - return QString(text).replace("\n", "\r\n").toLocal8Bit(); -#else - return text.toLocal8Bit(); -#endif -} - -static QString fromLocalEncoding(const QByteArray &data) -{ -#if defined(Q_OS_WIN) - return QString::fromLocal8Bit(data).replace("\n", "\r\n"); -#else - return QString::fromLocal8Bit(data); -#endif -} - -static QString getProcessOutput(const QString &command, const QString &input) -{ - QProcess proc; -#if QT_VERSION >= QT_VERSION_CHECK(5,15,0) - QStringList arguments = QProcess::splitCommand(command); - QString executable = arguments.takeFirst(); - proc.start(executable, arguments); -#else - proc.start(command); -#endif - proc.waitForStarted(); - proc.write(toLocalEncoding(input)); - proc.closeWriteChannel(); - - // FIXME: Process should be interruptable by user. - // Solution is to create a QObject for each process and emit finished state. - proc.waitForFinished(); - - return fromLocalEncoding(proc.readAllStandardOutput()); -} - static const QMap &vimKeyNames() { static const QMap k = { @@ -1017,7 +977,7 @@ QDebug operator<<(QDebug ts, const ExCommand &cmd) QDebug operator<<(QDebug ts, const QList &sels) { - foreach (const QTextEdit::ExtraSelection &sel, sels) + for (const QTextEdit::ExtraSelection &sel : sels) ts << "SEL: " << sel.cursor.anchor() << sel.cursor.position(); return ts; } @@ -3064,7 +3024,7 @@ void FakeVimHandler::Private::clearPendingInput() void FakeVimHandler::Private::waitForMapping() { g.currentCommand.clear(); - foreach (const Input &input, g.currentMap.currentInputs()) + for (const Input &input : g.currentMap.currentInputs()) g.currentCommand.append(input.toString()); // wait for user to press any key or trigger complete mapping after interval @@ -5212,6 +5172,7 @@ void FakeVimHandler::Private::handleReplaceMode(const Input &input) moveDown(); } else if (input.isKey(Key_Insert)) { g.mode = InsertMode; + q->modeChanged(isInsertMode()); } else if (input.isControl('o')) { enterCommandMode(ReplaceMode); } else { @@ -5409,6 +5370,7 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input) removeText(range); } else if (input.isKey(Key_Insert)) { g.mode = ReplaceMode; + q->modeChanged(isInsertMode()); } else if (input.isKey(Key_Left)) { moveLeft(); } else if (input.isShift(Key_Left) || input.isControl(Key_Left)) { @@ -5472,16 +5434,18 @@ void FakeVimHandler::Private::handleInsertMode(const Input &input) } else if (input.isKey(Key_PageUp) || input.isControl('b')) { movePageUp(); } else if (input.isKey(Key_Tab)) { - m_buffer->insertState.insertingSpaces = true; - if (s.expandTab.value()) { - const int ts = s.tabStop.value(); - const int col = logicalCursorColumn(); - QString str = QString(ts - col % ts, ' '); - insertText(str); - } else { - insertInInsertMode(input.raw()); + if (q->tabPressedInInsertMode()) { + m_buffer->insertState.insertingSpaces = true; + if (s.expandTab.value()) { + const int ts = s.tabStop.value(); + const int col = logicalCursorColumn(); + QString str = QString(ts - col % ts, ' '); + insertText(str); + } else { + insertInInsertMode(input.raw()); + } + m_buffer->insertState.insertingSpaces = false; } - m_buffer->insertState.insertingSpaces = false; } else if (input.isControl('d')) { // remove one level of indentation from the current line const int shift = s.shiftWidth.value(); @@ -6085,13 +6049,13 @@ bool FakeVimHandler::Private::handleExMapCommand(const ExCommand &cmd0) // :map //qDebug() << "MAPPING: " << modes << lhs << rhs; switch (type) { case Unmap: - foreach (char c, modes) + for (char c : std::as_const(modes)) MappingsIterator(&g.mappings, c, key).remove(); break; case Map: Q_FALLTHROUGH(); case Noremap: { - Inputs inputs(rhs, type == Noremap, silent); - foreach (char c, modes) + const Inputs inputs(rhs, type == Noremap, silent); + for (char c : std::as_const(modes)) MappingsIterator(&g.mappings, c).setInputs(key, inputs, unique); break; } @@ -6109,7 +6073,7 @@ bool FakeVimHandler::Private::handleExHistoryCommand(const ExCommand &cmd) QString info; info += "# command history\n"; int i = 0; - foreach (const QString &item, g.commandBuffer.historyItems()) { + for (const QString &item : g.commandBuffer.historyItems()) { ++i; info += QString("%1 %2\n").arg(i, -8).arg(item); } @@ -6137,7 +6101,7 @@ bool FakeVimHandler::Private::handleExRegisterCommand(const ExCommand &cmd) } QString info; info += "--- Registers ---\n"; - for (char reg : qAsConst(regs)) { + for (char reg : std::as_const(regs)) { QString value = quoteUnprintable(registerContents(reg)); info += QString("\"%1 %2\n").arg(reg).arg(value); } @@ -6443,7 +6407,8 @@ bool FakeVimHandler::Private::handleExBangCommand(const ExCommand &cmd) // :! const QString command = QString(cmd.cmd.mid(1) + ' ' + cmd.args).trimmed(); const QString input = replaceText ? selectText(cmd.range) : QString(); - const QString result = getProcessOutput(command, input); + QString result; + q->processOutput(command, input, &result); if (replaceText) { setCurrentRange(cmd.range); @@ -6534,7 +6499,7 @@ bool FakeVimHandler::Private::handleExMultiRepeatCommand(const ExCommand &cmd) const Range range(pos, pos, RangeLineMode); const QString lineContents = selectText(range); const QRegularExpressionMatch match = re.match(lineContents); - if (match.hasMatch() ^ negates) { + if (match.hasMatch() != negates) { QTextCursor tc(document()); tc.setPosition(pos); matches.append(tc); @@ -6543,7 +6508,7 @@ bool FakeVimHandler::Private::handleExMultiRepeatCommand(const ExCommand &cmd) beginEditBlock(); - for (const QTextCursor &tc : qAsConst(matches)) { + for (const QTextCursor &tc : std::as_const(matches)) { setPosition(tc.position()); handleExCommand(innerCmd); } @@ -8590,6 +8555,8 @@ void FakeVimHandler::Private::enterInsertOrReplaceMode(Mode mode) g.returnToMode = mode; clearLastInsertion(); } + + q->modeChanged(isInsertMode()); } void FakeVimHandler::Private::enterVisualInsertMode(QChar command) @@ -8665,6 +8632,8 @@ void FakeVimHandler::Private::enterCommandMode(Mode returnToMode) g.returnToMode = returnToMode; m_positionPastEnd = false; m_anchorPastEnd = false; + + q->modeChanged(isInsertMode()); } void FakeVimHandler::Private::enterExMode(const QString &contents) @@ -8679,6 +8648,8 @@ void FakeVimHandler::Private::enterExMode(const QString &contents) g.submode = NoSubMode; g.subsubmode = NoSubSubMode; unfocus(); + + q->modeChanged(isInsertMode()); } void FakeVimHandler::Private::recordJump(int position) diff --git a/fakevim/fakevimhandler.h b/fakevim/fakevimhandler.h index cb3d839..6841b89 100644 --- a/fakevim/fakevimhandler.h +++ b/fakevim/fakevimhandler.h @@ -1,14 +1,14 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once +#ifndef FAKEVIM_STANDALONE #define FAKEVIM_STANDALONE - -#ifdef FAKEVIM_STANDALONE -# include "private/fakevim_export.h" #endif +#include "private/fakevim_export.h" + #include #include @@ -67,23 +67,30 @@ enum MessageLevel MessageShowCmd // partial command }; -template -class Signal +template +class Callback; + +template +class Callback { public: - using Callable = std::function; + static constexpr auto IsVoidReturnType = std::is_same_v; + using Function = std::function; + void set(const Function &callable) { m_callable = callable; } - void connect(const Callable &callable) { m_callables.push_back(callable); } - - template - void operator()(Args ...args) const + R operator()(Params... params) { - for (const Callable &callable : m_callables) - callable(args...); - } + if (!m_callable) + return R(); + + if constexpr (IsVoidReturnType) + m_callable(std::forward(params)...); + else + return m_callable(std::forward(params)...); + } private: - std::vector m_callables; + Function m_callable; }; class FAKEVIM_EXPORT FakeVimHandler : public QObject @@ -137,32 +144,36 @@ class FAKEVIM_EXPORT FakeVimHandler : public QObject bool eventFilter(QObject *ob, QEvent *ev) override; - Signal commandBufferChanged; - Signal statusDataChanged; - Signal extraInformationChanged; - Signal &selection)> selectionChanged; - Signal highlightMatches; - Signal moveToMatchingParenthesis; - Signal checkForElectricCharacter; - Signal indentRegion; - Signal simpleCompletionRequested; - Signal windowCommandRequested; - Signal findRequested; - Signal findNextRequested; - Signal handleExCommandRequested; - Signal requestDisableBlockSelection; - Signal requestSetBlockSelection; - Signal requestBlockSelection; - Signal requestHasBlockSelection; - Signal foldToggle; - Signal foldAll; - Signal fold; - Signal foldGoTo; - Signal requestJumpToLocalMark; - Signal requestJumpToGlobalMark; - Signal completionRequested; - Signal tabPreviousRequested; - Signal tabNextRequested; + Callback + commandBufferChanged; + Callback statusDataChanged; + Callback extraInformationChanged; + Callback &selection)> selectionChanged; + Callback highlightMatches; + Callback moveToMatchingParenthesis; + Callback checkForElectricCharacter; + Callback indentRegion; + Callback simpleCompletionRequested; + Callback windowCommandRequested; + Callback findRequested; + Callback findNextRequested; + Callback handleExCommandRequested; + Callback requestDisableBlockSelection; + Callback requestSetBlockSelection; + Callback requestBlockSelection; + Callback requestHasBlockSelection; + Callback foldToggle; + Callback foldAll; + Callback fold; + Callback foldGoTo; + Callback requestJumpToLocalMark; + Callback requestJumpToGlobalMark; + Callback completionRequested; + Callback tabPreviousRequested; + Callback tabNextRequested; + Callback modeChanged; + Callback tabPressedInInsertMode; + Callback processOutput; public: class Private; diff --git a/fakevim/fakevimtr.h b/fakevim/fakevimtr.h index ac83212..a32f8c9 100644 --- a/fakevim/fakevimtr.h +++ b/fakevim/fakevimtr.h @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once @@ -9,7 +9,7 @@ namespace FakeVim { struct Tr { - Q_DECLARE_TR_FUNCTIONS(FakeVim) + Q_DECLARE_TR_FUNCTIONS(QtC::FakeVim) }; } // namespace FakeVim diff --git a/utils/patches/add-patches-for-upstream.patch b/utils/patches/add-patches-for-upstream.patch index a1740ae..c0a49ed 100644 --- a/utils/patches/add-patches-for-upstream.patch +++ b/utils/patches/add-patches-for-upstream.patch @@ -1,20 +1,8 @@ -From abf9e46f65b1011d4b7e6feb13949744c90199d1 Mon Sep 17 00:00:00 2001 -From: Lukas Holecek -Date: Thu, 1 Sep 2022 19:17:50 +0200 -Subject: [PATCH] Add patches for upstream - ---- - fakevim/fakevimactions.cpp | 17 +++++++---------- - fakevim/fakevimactions.h | 14 +++++++++----- - fakevim/fakevimhandler.cpp | 29 ++++++++++++++++++++++------- - fakevim/fakevimhandler.h | 12 +++++++++--- - 4 files changed, 47 insertions(+), 25 deletions(-) - diff --git a/fakevim/fakevimactions.cpp b/fakevim/fakevimactions.cpp -index 2a91730..f8eee8d 100644 +index 7f7c44b..5f59987 100644 --- a/fakevim/fakevimactions.cpp +++ b/fakevim/fakevimactions.cpp -@@ -9,14 +9,6 @@ +@@ -10,14 +10,6 @@ // Qt Creator. The idea is to keep this file here in a "clean" state that // allows easy reuse with any QTextEdit or QPlainTextEdit derived class. @@ -29,7 +17,7 @@ index 2a91730..f8eee8d 100644 namespace FakeVim { namespace Internal { -@@ -127,8 +119,13 @@ FakeVimSettings::FakeVimSettings() +@@ -128,8 +120,13 @@ FakeVimSettings::FakeVimSettings() backspace.setDisplayStyle(FvStringAspect::LineEditDisplay); isKeyword.setDisplayStyle(FvStringAspect::LineEditDisplay); @@ -37,25 +25,25 @@ index 2a91730..f8eee8d 100644 - ? "$HOME/.vimrc" : "%USERPROFILE%\\_vimrc"); + const QString vimrcDefault = QLatin1String( +#ifdef Q_OS_UNIX -+ "$HOME/.vimrc" ++ "$HOME/.vimrc" +#else -+ "%USERPROFILE%\\_vimrc" ++ "%USERPROFILE%\\_vimrc" +#endif -+ ) ++ ); vimRcPath.setExpectedKind(PathChooser::File); - vimRcPath.setToolTip(tr("Keep empty to use the default path, i.e. " + vimRcPath.setToolTip(Tr::tr("Keep empty to use the default path, i.e. " "%USERPROFILE%\\_vimrc on Windows, ~/.vimrc otherwise.")); diff --git a/fakevim/fakevimactions.h b/fakevim/fakevimactions.h -index afe5a68..802f448 100644 +index 6f7e303..5aead73 100644 --- a/fakevim/fakevimactions.h +++ b/fakevim/fakevimactions.h -@@ -3,8 +3,12 @@ - +@@ -4,7 +4,13 @@ #pragma once --#ifndef FAKEVIM_STANDALONE + #ifndef FAKEVIM_STANDALONE -# include +#define FAKEVIM_STANDALONE ++#endif + +#ifdef FAKEVIM_STANDALONE +# include "private/fakevim_export.h" @@ -64,7 +52,7 @@ index afe5a68..802f448 100644 #endif #include -@@ -17,7 +21,7 @@ namespace FakeVim { +@@ -17,7 +23,7 @@ namespace FakeVim { namespace Internal { #ifdef FAKEVIM_STANDALONE @@ -73,16 +61,16 @@ index afe5a68..802f448 100644 { public: FvBaseAspect(); -@@ -73,7 +77,7 @@ using FvStringAspect = Utils::StringAspect; +@@ -73,7 +79,7 @@ using FvStringAspect = Utils::StringAspect; #endif -class FakeVimSettings final : public FvAspectContainer +class FAKEVIM_EXPORT FakeVimSettings final : public FvAspectContainer { - Q_DECLARE_TR_FUNCTIONS(FakeVim) - -@@ -144,7 +148,7 @@ class FakeVimSettings final : public FvAspectContainer + public: + FakeVimSettings(); +@@ -142,7 +148,7 @@ private: QHash m_aspectToName; }; @@ -91,76 +79,19 @@ index afe5a68..802f448 100644 } // namespace Internal } // namespace FakeVim -diff --git a/fakevim/fakevimhandler.cpp b/fakevim/fakevimhandler.cpp -index fa52d2a..ec00168 100644 ---- a/fakevim/fakevimhandler.cpp -+++ b/fakevim/fakevimhandler.cpp -@@ -36,11 +36,10 @@ - #include "fakevimactions.h" - #include "fakevimtr.h" - --#include -- - #include - #include - #include -+#include - #include - #include - #include -@@ -842,18 +841,34 @@ static QByteArray toLocalEncoding(const QString &text) - #endif - } - -+static QString fromLocalEncoding(const QByteArray &data) -+{ -+#if defined(Q_OS_WIN) -+ return QString::fromLocal8Bit(data).replace("\n", "\r\n"); -+#else -+ return QString::fromLocal8Bit(data); -+#endif -+} -+ - static QString getProcessOutput(const QString &command, const QString &input) - { -- Utils::QtcProcess proc; -- proc.setCommand(Utils::CommandLine::fromUserInput(command)); -- proc.setWriteData(toLocalEncoding(input)); -- proc.start(); -+ QProcess proc; -+#if QT_VERSION >= QT_VERSION_CHECK(5,15,0) -+ QStringList arguments = QProcess::splitCommand(command); -+ QString executable = arguments.takeFirst(); -+ proc.start(executable, arguments); -+#else -+ proc.start(command); -+#endif -+ proc.waitForStarted(); -+ proc.write(toLocalEncoding(input)); -+ proc.closeWriteChannel(); - - // FIXME: Process should be interruptable by user. - // Solution is to create a QObject for each process and emit finished state. - proc.waitForFinished(); - -- return proc.cleanedStdOut(); -+ return fromLocalEncoding(proc.readAllStandardOutput()); - } - - static const QMap &vimKeyNames() diff --git a/fakevim/fakevimhandler.h b/fakevim/fakevimhandler.h -index eff6c57..cb3d839 100644 +index 7c0ceca..6841b89 100644 --- a/fakevim/fakevimhandler.h +++ b/fakevim/fakevimhandler.h @@ -3,6 +3,12 @@ #pragma once ++#ifndef FAKEVIM_STANDALONE +#define FAKEVIM_STANDALONE -+ -+#ifdef FAKEVIM_STANDALONE -+# include "private/fakevim_export.h" +#endif ++ ++#include "private/fakevim_export.h" + #include #include @@ -183,8 +114,8 @@ index eff6c57..cb3d839 100644 { ExCommand() = default; ExCommand(const QString &cmd, const QString &args = QString(), -@@ -80,7 +86,7 @@ class Signal - std::vector m_callables; +@@ -87,7 +93,7 @@ private: + Function m_callable; }; -class FakeVimHandler : public QObject @@ -192,6 +123,3 @@ index eff6c57..cb3d839 100644 { Q_OBJECT --- -2.37.2 - diff --git a/utils/update_from_qtc.ps1 b/utils/update_from_qtc.ps1 new file mode 100644 index 0000000..5aa82f7 --- /dev/null +++ b/utils/update_from_qtc.ps1 @@ -0,0 +1,58 @@ +Param( + [Parameter(HelpMessage="Synchronizes the Qt-Creator repository")] + [switch]$Update = $false, + + [Parameter(Mandatory = $true, HelpMessage="Path to the Qt-Creator repository")] + [string]$QtCreatorPath +) + +if (!(Test-Path -Path $QtCreatorPath)) +{ + Write-Output "Folder \"$($args[0])\" does not exist!" + Exit(1) +} + +$qtc_home = (Get-Item $QtCreatorPath) +$script_dir = $PSScriptRoot +$base_dir = (Get-Item $PSScriptRoot).Parent.FullName + + +Push-Location $qtc_home + +if ($Update) +{ + Write-Output "--- Fetching latest development code for Qt Creator" + git fetch origin master +} + +git checkout origin/master +$commit = git rev-parse --short HEAD +Write-Output $commit + +Pop-Location + +Write-Output "--- Updating source files" +Push-Location "$base_dir/fakevim" + +$files_to_update = @( + 'fakevimactions.cpp', + 'fakevimactions.h', + 'fakevimhandler.cpp', + 'fakevimhandler.h', + 'fakevimtr.h' +) + +foreach ($file in $files_to_update) +{ + Write-Output "-- $file" + Copy-Item "$qtc_home/src/plugins/fakevim/$file" $file + git add -- $file +} + +Write-Output "--- Patching source files and creating commit" +git commit -m "Update from Qt Creator (commit $commit)" +git apply -- "$script_dir/patches/add-patches-for-upstream.patch" +git add -- $($files_to_update -join " ") +git commit --amend --no-edit --allow-empty + +Pop-Location