diff --git a/NEWS.md b/NEWS.md
index 2d363ba5..b2f1c7d4 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -29,6 +29,7 @@ Red Panda C++ Version 2.12
- enhancement: Syntax highlight and basic code completion for lua.
- enhancement: Basic code completion for xmake.lua.
- enhancement: Parser not correctly released if save a c file to non-c file.
+ - enhancement: Improve auto indent for embedding no-brace statements like for-for-if.
Red Panda C++ Version 2.11
diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro
index b63a3f48..91be6768 100644
--- a/RedPandaIDE/RedPandaIDE.pro
+++ b/RedPandaIDE/RedPandaIDE.pro
@@ -87,6 +87,7 @@ SOURCES += \
compiler/compilerinfo.cpp \
compiler/ojproblemcasesrunner.cpp \
compiler/projectcompiler.cpp \
+ compiler/xmakecompiler.cpp \
compiler/runner.cpp \
customfileiconprovider.cpp \
gdbmiresultparser.cpp \
@@ -225,6 +226,7 @@ HEADERS += \
compiler/compilermanager.h \
compiler/executablerunner.h \
compiler/filecompiler.h \
+ compiler/xmakecompiler.h \
compiler/ojproblemcasesrunner.h \
compiler/projectcompiler.h \
compiler/runner.h \
diff --git a/RedPandaIDE/compiler/xmakecompiler.cpp b/RedPandaIDE/compiler/xmakecompiler.cpp
new file mode 100644
index 00000000..fecbc09e
--- /dev/null
+++ b/RedPandaIDE/compiler/xmakecompiler.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#include "xmakecompiler.h"
+#include "../project.h"
+#include "compilermanager.h"
+#include "../systemconsts.h"
+#include "qt_utils/charsetinfo.h"
+#include "../editor.h"
+
+#include
+
+XMakeCompiler::XMakeCompiler(std::shared_ptr project, bool silent, bool onlyCheckSyntax):
+ Compiler("",silent,onlyCheckSyntax),
+ mOnlyClean(false)
+{
+ setProject(project);
+}
+
+void XMakeCompiler::buildXMakeFile()
+{
+ //we are using custom make file, don't overwrite it
+ if (mProject->options().useCustomMakefile && !mProject->options().customMakefile.isEmpty())
+ return;
+
+ QFile file(mProject->makeFileName());
+ newXMakeFile(file);
+
+}
+
+void XMakeCompiler::newXMakeFile(QFile& file)
+{
+ // Create OBJ output directory
+ if (!mProject->options().objectOutput.isEmpty()) {
+ QDir(mProject->directory()).mkpath(mProject->options().objectOutput);
+ }
+
+ // Write more information to the log file than before
+ log(tr("Building xmake.lua file..."));
+ log("--------");
+ log(tr("- Filename: %1").arg(mProject->xmakeFileName()));
+
+ // Create the actual file
+ if (!file.open(QFile::WriteOnly | QFile::Truncate))
+ throw CompileError(tr("Can't open '%1' for write!").arg(mProject->xmakeFileName()));
+
+ writeln(file,"-- Project: " + mProject->name());
+ writeln(file,QString("-- xmake.lua created by Red Panda C++ ") + REDPANDA_CPP_VERSION);
+ writeln(file);
+
+ writeln(file, QString("target(\"%1\")").arg(mProject->name()));
+ switch(mProject->options().type) {
+ case ProjectType::StaticLib:
+ writeln(file,"\tset_kind(\"static\")");
+ break;
+ case ProjectType::DynamicLib:
+ writeln(file,"\tset_kind(\"shared\")");
+ break;
+ default:
+ writeln(file,"\tset_kind(\"binary\")");
+ }
+ // add files to compile
+ foreach(const PProjectUnit &unit, mProject->unitList()) {
+ if (!unit->compile() && !unit->link())
+ continue;
+
+ // Only process source files
+ QString relativeName = extractRelativePath(mProject->directory(), unit->fileName());
+ FileType fileType = getFileType(relativeName);
+ if (fileType==FileType::ASM && !compilerSet()->canAssemble())
+ continue;
+
+ if (fileType == FileType::CHeader || fileType == FileType::CppHeader) {
+ writeln(file,QString("\tadd_headerfiles(\"%1\")").arg(relativeName));
+ } else if (fileType == FileType::CSource || fileType == FileType::CppSource
+ || fileType == FileType::ASM || fileType==FileType::GAS || fileType==FileType::WindowsResourceSource) {
+ writeln(file,QString("\tadd_files(\"%1\")").arg(relativeName));
+ }
+ }
+
+ // Get windres file
+#ifdef Q_OS_WIN
+ if (!mProject->options().privateResource.isEmpty()) {
+ QString relativeName = extractRelativePath(mProject->directory(), mProject->options().privateResource);
+ writeln(file,QString("\tadd_files(\"%1\")").arg(relativeName));
+ }
+#endif
+
+ // Get list of applicable flags
+ QString cCompileArguments = getCCompileArguments(mOnlyCheckSyntax);
+ QString cppCompileArguments = getCppCompileArguments(mOnlyCheckSyntax);
+ QString libraryArguments = getLibraryArguments(FileType::Project);
+ QString cIncludeArguments = getCIncludeArguments() + " " + getProjectIncludeArguments();
+ QString cppIncludeArguments = getCppIncludeArguments() + " " +getProjectIncludeArguments();
+
+ cCompileArguments.replace("\"","\\\"");
+ cppCompileArguments.replace("\"","\\\"");
+ libraryArguments.replace("\"","\\\"");
+ cIncludeArguments.replace("\"","\\\"");
+ cppIncludeArguments.replace("\"","\\\"");
+
+ writeln(file,QString("\tadd_cflags(\"%1\")").arg(cCompileArguments));
+ writeln(file,QString("\tadd_cflags(\"%1\")").arg(cIncludeArguments));
+ writeln(file,QString("\tadd_cxxflags(\"%1\")").arg(cppCompileArguments));
+ writeln(file,QString("\tadd_cxxflags(\"%1\")").arg(cppIncludeArguments));
+ writeln(file,QString("\tadd_ldflags(\"%1\")").arg(libraryArguments));
+
+#ifdef Q_OS_WIN
+ writeln(file,QString("\tadd_rcflags(\"%1\")").arg(mProject->options().resourceCmd));
+#endif
+
+ if (mProject->getCompileOption(CC_CMD_OPT_DEBUG_INFO) == COMPILER_OPTION_ON) {
+ writeln(file,QString("\tadd_defines(\"__DEBUG__\")"));
+ }
+
+ writeln(file,QString("target_end()"));
+}
+
+void XMakeCompiler::writeln(QFile &file, const QString &s)
+{
+ if (!s.isEmpty())
+ file.write(s.toLocal8Bit());
+ file.write("\n");
+}
+
+bool XMakeCompiler::onlyClean() const
+{
+ return mOnlyClean;
+}
+
+void XMakeCompiler::setOnlyClean(bool newOnlyClean)
+{
+ mOnlyClean = newOnlyClean;
+}
+
+bool XMakeCompiler::prepareForRebuild()
+{
+ //we use make argument to clean
+ return true;
+}
+
+bool XMakeCompiler::prepareForCompile()
+{
+ if (!mProject)
+ return false;
+ //initProgressForm();
+ log(tr("Compiling project changes..."));
+ log("--------");
+ log(tr("- Project Filename: %1").arg(mProject->filename()));
+ log(tr("- Compiler Set Name: %1").arg(compilerSet()->name()));
+ log("");
+
+ buildXMakeFile();
+
+ mCompiler = compilerSet()->make();
+
+ if (!fileExists(mCompiler)) {
+ throw CompileError(
+ tr("Make program '%1' doesn't exists!").arg(mCompiler)
+ +"
"
+ +tr("Please check the \"program\" page of compiler settings."));
+ }
+
+ QString parallelParam;
+ if (mProject->options().allowParallelBuilding) {
+ if (mProject->options().parellelBuildingJobs==0) {
+ parallelParam = " --jobs";
+ } else {
+ parallelParam = QString(" -j%1").arg(mProject->options().parellelBuildingJobs);
+ }
+ }
+
+ if (mOnlyClean) {
+ mArguments = QString(" %1 -f \"%2\" clean").arg(parallelParam,
+ extractRelativePath(
+ mProject->directory(),
+ mProject->makeFileName()));
+ } else if (mRebuild) {
+ mArguments = QString(" %1 -f \"%2\" clean all").arg(parallelParam,
+ extractRelativePath(
+ mProject->directory(),
+ mProject->makeFileName()));
+ } else {
+ mArguments = QString(" %1 -f \"%2\" all").arg(parallelParam,
+ extractRelativePath(
+ mProject->directory(),
+ mProject->makeFileName()));
+ }
+ mDirectory = mProject->directory();
+
+ log(tr("Processing makefile:"));
+ log("--------");
+ log(tr("- makefile processer: %1").arg(mCompiler));
+ log(tr("- Command: %1 %2").arg(extractFileName(mCompiler)).arg(mArguments));
+ log("");
+
+ return true;
+}
diff --git a/RedPandaIDE/compiler/xmakecompiler.h b/RedPandaIDE/compiler/xmakecompiler.h
new file mode 100644
index 00000000..f806faae
--- /dev/null
+++ b/RedPandaIDE/compiler/xmakecompiler.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020-2022 Roy Qu (royqh1979@gmail.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#ifndef XMAKECOMPILER_H
+#define XMAKECOMPILER_H
+
+#include "compiler.h"
+#include
+#include
+
+class Project;
+class XMakeCompiler : public Compiler
+{
+ Q_OBJECT
+public:
+ XMakeCompiler(std::shared_ptr project, bool silent,bool onlyCheckSyntax);
+ XMakeCompiler(const XMakeCompiler&)=delete;
+ XMakeCompiler& operator=(const XMakeCompiler&)=delete;
+ void buildXMakeFile();
+
+ bool onlyClean() const;
+ void setOnlyClean(bool newOnlyClean);
+
+private:
+ void newXMakeFile(QFile& file);
+ void writeln(QFile& file, const QString& s="");
+ // Compiler interface
+private:
+ bool mOnlyClean;
+protected:
+ bool prepareForCompile() override;
+ bool prepareForRebuild() override;
+};
+
+#endif // XMakeCompiler_H
diff --git a/RedPandaIDE/mainwindow.ui b/RedPandaIDE/mainwindow.ui
index 60de487d..f261bc59 100644
--- a/RedPandaIDE/mainwindow.ui
+++ b/RedPandaIDE/mainwindow.ui
@@ -483,7 +483,7 @@
QTabWidget::West
- 4
+ 1
true
diff --git a/RedPandaIDE/project.cpp b/RedPandaIDE/project.cpp
index 5315eadb..73cd4745 100644
--- a/RedPandaIDE/project.cpp
+++ b/RedPandaIDE/project.cpp
@@ -160,6 +160,11 @@ QString Project::makeFileName()
return QDir(directory()).filePath(MAKEFILE_NAME);
}
+QString Project::xmakeFileName()
+{
+ return QDir(directory()).filePath(XMAKEFILE_NAME);
+}
+
bool Project::unitsModifiedSince(const QDateTime& time)
{
foreach(const PProjectUnit& unit, mUnits) {
diff --git a/RedPandaIDE/project.h b/RedPandaIDE/project.h
index c3571978..d4efac52 100644
--- a/RedPandaIDE/project.h
+++ b/RedPandaIDE/project.h
@@ -214,6 +214,7 @@ public:
QString directory() const;
QString executable() const;
QString makeFileName();
+ QString xmakeFileName();
bool unitsModifiedSince(const QDateTime& time);
bool modified() const;
bool modifiedSince(const QDateTime& time);
diff --git a/RedPandaIDE/settings.cpp b/RedPandaIDE/settings.cpp
index 7deafbe9..a4d398ca 100644
--- a/RedPandaIDE/settings.cpp
+++ b/RedPandaIDE/settings.cpp
@@ -48,7 +48,8 @@ Settings::Settings(const QString &filename):
mCodeCompletion(this),
mCodeFormatter(this),
mUI(this),
- mVCS(this)
+ mVCS(this),
+ mExtTools(this)
{
//load();
}
@@ -112,6 +113,7 @@ void Settings::load()
mUI.load();
mDirs.load();
mVCS.load();
+ mExtTools.load();
}
Settings::Dirs &Settings::dirs()
@@ -144,6 +146,11 @@ QString Settings::filename() const
return mFilename;
}
+Settings::ExtTools &Settings::extTools()
+{
+ return mExtTools;
+}
+
Settings::CodeCompletion& Settings::codeCompletion()
{
return mCodeCompletion;
@@ -5865,3 +5872,28 @@ void Settings::VCS::detectGitInPath()
}
}
+
+const QString &Settings::ExtTools::xMakePath() const
+{
+ return mXMakePath;
+}
+
+void Settings::ExtTools::setXMakePath(const QString &newXMakePath)
+{
+ mXMakePath = newXMakePath;
+}
+
+void Settings::ExtTools::doSave()
+{
+ saveValue("xmake_path", mXMakePath);
+}
+
+void Settings::ExtTools::doLoad()
+{
+ mXMakePath=stringValue("xmake_path","");
+}
+
+Settings::ExtTools::ExtTools(Settings *settings):_Base(settings, SETTING_EXTTOOLS)
+{
+
+}
diff --git a/RedPandaIDE/settings.h b/RedPandaIDE/settings.h
index 677417eb..5a168725 100644
--- a/RedPandaIDE/settings.h
+++ b/RedPandaIDE/settings.h
@@ -37,6 +37,7 @@
#define SETTING_ENVIRONMENT "Environment"
#define SETTING_EXECUTOR "Executor"
#define SETTING_DEBUGGER "Debugger"
+#define SETTING_EXTTOOLS "ExtTools"
#define SETTING_HISTORY "History"
#define SETTING_UI "UI"
#define SETTING_VCS "VCS"
@@ -1266,6 +1267,21 @@ public:
void doLoad() override;
};
+ class ExtTools: public _Base {
+ public:
+ explicit ExtTools(Settings* settings);
+
+ const QString &xMakePath() const;
+ void setXMakePath(const QString &newXMakePath);
+
+ private:
+ QString mXMakePath;
+ // _Base interface
+ protected:
+ void doSave() override;
+ void doLoad() override;
+ };
+
class CompilerSet {
public:
@@ -1522,8 +1538,10 @@ public:
CodeFormatter &codeFormatter();
UI &ui();
VCS &vcs();
+ ExtTools &extTools();
QString filename() const;
+
private:
QString mFilename;
QSettings mSettings;
@@ -1537,6 +1555,8 @@ private:
CodeFormatter mCodeFormatter;
UI mUI;
VCS mVCS;
+ ExtTools mExtTools;
+
};
diff --git a/RedPandaIDE/systemconsts.h b/RedPandaIDE/systemconsts.h
index 0f03d6d9..c96b0056 100644
--- a/RedPandaIDE/systemconsts.h
+++ b/RedPandaIDE/systemconsts.h
@@ -116,6 +116,7 @@
# define STATIC_LIB_EXT "a"
# define DYNAMIC_LIB_EXT "dll"
# define MAKEFILE_NAME "makefile.win"
+# define XMAKEFILE_NAME "xmake.lua"
# define ALL_FILE_WILDCARD "*.*"
#elif defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
# define PATH_SENSITIVITY Qt::CaseSensitive
@@ -129,6 +130,7 @@
# define STATIC_LIB_EXT "a"
# define DYNAMIC_LIB_EXT "d"
# define MAKEFILE_NAME "makefile"
+# define XMAKEFILE_NAME "xmake.lua"
# define ALL_FILE_WILDCARD "*"
#else
#error "Only support windows and linux now!"
diff --git a/RedPandaIDE/utils.cpp b/RedPandaIDE/utils.cpp
index bd41ee74..b8378e90 100644
--- a/RedPandaIDE/utils.cpp
+++ b/RedPandaIDE/utils.cpp
@@ -146,6 +146,9 @@ FileType getFileType(const QString &filename)
if (filename.endsWith(".dat",PATH_SENSITIVITY)) {
return FileType::Text;
}
+ if (filename.endsWith(".lua",PATH_SENSITIVITY)) {
+ return FileType::LUA;
+ }
QFileInfo info(filename);
if (info.suffix().isEmpty()) {
return FileType::Other;
diff --git a/RedPandaIDE/utils.h b/RedPandaIDE/utils.h
index bb5e1f60..745278d2 100644
--- a/RedPandaIDE/utils.h
+++ b/RedPandaIDE/utils.h
@@ -34,6 +34,7 @@ using PSimpleIni = std::shared_ptr;
enum class FileType{
ASM, // asm source file (.asm)
GAS, // GNU assembler source file (.s)
+ LUA, // lua file (.lua)
CSource, // c source file (.c)
CppSource, // c++ source file (.cpp)
CHeader, // c header (.h)
diff --git a/libs/qsynedit/qsynedit/syntaxer/cpp.cpp b/libs/qsynedit/qsynedit/syntaxer/cpp.cpp
index d03cda87..4128a92e 100644
--- a/libs/qsynedit/qsynedit/syntaxer/cpp.cpp
+++ b/libs/qsynedit/qsynedit/syntaxer/cpp.cpp
@@ -407,9 +407,13 @@ void CppSyntaxer::braceOpenProc()
// if last indent is started by 'if' 'for' etc
// just replace it
int lastLine=-1;
+ if (!mRange.indents.isEmpty()) {
+ lastLine=mRange.indents.back().line;
+ } else {
+ lastLine=0;
+ }
while (mRange.getLastIndentType() == IndentType::Statement) {
popIndents(IndentType::Statement);
- lastLine = mRange.lastUnindent.line;
}
pushIndents(IndentType::Block, lastLine);
} else