From 45578a260397bf24262e654fdf4c22704e2408ad Mon Sep 17 00:00:00 2001 From: Roy Qu Date: Thu, 9 Mar 2023 20:35:15 +0800 Subject: [PATCH] refactor: formatter interface for qsynedit --- RedPandaIDE/editor.cpp | 24 +++ RedPandaIDE/settings.cpp | 30 ++++ RedPandaIDE/settings.h | 8 + RedPandaIDE/syntaxermanager.cpp | 56 +++++-- RedPandaIDE/syntaxermanager.h | 12 +- libs/qsynedit/qsynedit.pro | 4 + .../qsynedit/formatter/cppformatter.cpp | 141 ++++++++++++++++++ .../qsynedit/formatter/cppformatter.h | 26 ++++ .../qsynedit/qsynedit/formatter/formatter.cpp | 54 +++++++ libs/qsynedit/qsynedit/formatter/formatter.h | 33 ++++ libs/qsynedit/qsynedit/qsynedit.cpp | 99 ++---------- libs/qsynedit/qsynedit/qsynedit.h | 8 +- libs/qsynedit/qsynedit/syntaxer/syntaxer.h | 12 -- libs/qsynedit/qsynedit/types.h | 14 ++ 14 files changed, 402 insertions(+), 119 deletions(-) create mode 100644 libs/qsynedit/qsynedit/formatter/cppformatter.cpp create mode 100644 libs/qsynedit/qsynedit/formatter/cppformatter.h create mode 100644 libs/qsynedit/qsynedit/formatter/formatter.cpp create mode 100644 libs/qsynedit/qsynedit/formatter/formatter.h diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 4292c83f..132ab07a 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -111,11 +111,19 @@ Editor::Editor(QWidget *parent, const QString& filename, resolveAutoDetectEncodingOption(); if (syntaxer) { setSyntaxer(syntaxer); + setFormatter(syntaxerManager.getFormatter(syntaxer->language())); setUseCodeFolding(true); } else { setUseCodeFolding(false); } + if (formatter()) { + if (formatter()->supportLanguage()==QSynedit::ProgrammingLanguage::CPP) { + formatter()->setOption("IndentClassMemberVisibilityKeywords",pSettings->languages().indentCClassMemberVisibilityKeywords()); + formatter()->setOption("IndentSwitchCases",pSettings->languages().indentCSwitchCaseKeywords()); + } + } + if (mProject) { if (syntaxer && syntaxer->language() == QSynedit::ProgrammingLanguage::CPP) mParser = mProject->cppParser(); @@ -481,10 +489,19 @@ bool Editor::saveAs(const QString &name, bool fromProject){ QSynedit::PSyntaxer newSyntaxer = syntaxerManager.getSyntaxer(mFilename); if (newSyntaxer) { setUseCodeFolding(true); + setFormatter(syntaxerManager.getFormatter(newSyntaxer->language())); } else { setUseCodeFolding(false); + setFormatter(syntaxerManager.getFormatter(QSynedit::ProgrammingLanguage::Unknown)); } setSyntaxer(newSyntaxer); + if (formatter()) { + if (formatter()->supportLanguage()==QSynedit::ProgrammingLanguage::CPP) { + formatter()->setOption("IndentClassMemberVisibilityKeywords",pSettings->languages().indentCClassMemberVisibilityKeywords()); + formatter()->setOption("IndentSwitchCases",pSettings->languages().indentCSwitchCaseKeywords()); + } + } + if (!newSyntaxer || newSyntaxer->language() != QSynedit::ProgrammingLanguage::CPP) { mSyntaxIssues.clear(); } @@ -5183,6 +5200,13 @@ void Editor::applySettings() } } + if (formatter()) { + if (formatter()->supportLanguage()==QSynedit::ProgrammingLanguage::CPP) { + formatter()->setOption("IndentClassMemberVisibilityKeywords",pSettings->languages().indentCClassMemberVisibilityKeywords()); + formatter()->setOption("IndentSwitchCases",pSettings->languages().indentCSwitchCaseKeywords()); + } + } + this->setUndoLimit(pSettings->editor().undoLimit()); this->setUndoMemoryUsage(pSettings->editor().undoMemoryUsage()); diff --git a/RedPandaIDE/settings.cpp b/RedPandaIDE/settings.cpp index 5161d7dc..a7455112 100644 --- a/RedPandaIDE/settings.cpp +++ b/RedPandaIDE/settings.cpp @@ -5933,11 +5933,36 @@ void Settings::Languages::setX86DialectOfASMGenerated(X86ASMDialect newX86Dialec mX86DialectOfASMGenerated = newX86DialectOfASMGenerated; } +bool Settings::Languages::indentCSwitchCaseKeywords() const +{ + return mIndentCSwitchCaseKeywords; +} + +void Settings::Languages::setIndentCSwitchCaseKeywords(bool newIndentCSwitchCaseKeywords) +{ + mIndentCSwitchCaseKeywords = newIndentCSwitchCaseKeywords; +} + +bool Settings::Languages::indentCClassMemberVisibilityKeywords() const +{ + return mIndentCClassMemberVisibilityKeywords; +} + +void Settings::Languages::setIndentCClassMemberVisibilityKeywords(bool newIndentCClassMemberVisibilityKeywords) +{ + mIndentCClassMemberVisibilityKeywords = newIndentCClassMemberVisibilityKeywords; +} + void Settings::Languages::doSave() { + //ASM saveValue("no_debug_directives_when_generate_asm",mNoDebugDirectivesWhenGenerateASM); saveValue("no_seh_directives_when_generate_asm",mNoSEHDirectivesWhenGenerateASM); saveValue("x86_dialect_of_asm_generated",(int)mX86DialectOfASMGenerated); + + //C/C++ + saveValue("ident_c_class_member_visibility_keywords",mIndentCClassMemberVisibilityKeywords); + saveValue("ident_c_switch_case_keywords",mIndentCSwitchCaseKeywords); } void Settings::Languages::doLoad() @@ -5945,6 +5970,11 @@ void Settings::Languages::doLoad() mNoDebugDirectivesWhenGenerateASM = boolValue("no_debug_directives_when_generate_asm",true); mNoSEHDirectivesWhenGenerateASM = boolValue("no_seh_directives_when_generate_asm",false); mX86DialectOfASMGenerated = (X86ASMDialect)intValue("x86_dialect_of_asm_generated",(int)X86ASMDialect::ATT); + + + //C/C++ + mIndentCClassMemberVisibilityKeywords = boolValue("ident_c_class_member_visibility_keywords",true); + mIndentCSwitchCaseKeywords = boolValue("ident_c_switch_case_keywords",true); } bool Settings::Languages::noSEHDirectivesWhenGenerateASM() const diff --git a/RedPandaIDE/settings.h b/RedPandaIDE/settings.h index d7b24c99..9256a913 100644 --- a/RedPandaIDE/settings.h +++ b/RedPandaIDE/settings.h @@ -992,10 +992,18 @@ public: X86ASMDialect x86DialectOfASMGenerated() const; void setX86DialectOfASMGenerated(X86ASMDialect newX86DialectOfASMGenerated); + bool indentCClassMemberVisibilityKeywords() const; + void setIndentCClassMemberVisibilityKeywords(bool newIndentCClassMemberVisibilityKeywords); + + bool indentCSwitchCaseKeywords() const; + void setIndentCSwitchCaseKeywords(bool newIndentCSwitchCaseKeywords); + private: bool mNoDebugDirectivesWhenGenerateASM; bool mNoSEHDirectivesWhenGenerateASM; X86ASMDialect mX86DialectOfASMGenerated; + bool mIndentCClassMemberVisibilityKeywords; + bool mIndentCSwitchCaseKeywords; protected: void doSave() override; void doLoad() override; diff --git a/RedPandaIDE/syntaxermanager.cpp b/RedPandaIDE/syntaxermanager.cpp index 4137fb29..9c2a5c91 100644 --- a/RedPandaIDE/syntaxermanager.cpp +++ b/RedPandaIDE/syntaxermanager.cpp @@ -23,6 +23,7 @@ #include "qsynedit/syntaxer/glsl.h" #include "qsynedit/syntaxer/lua.h" #include "qsynedit/syntaxer/makefile.h" +#include "qsynedit/formatter/cppformatter.h" #include "qsynedit/constants.h" #include "colorscheme.h" @@ -34,7 +35,7 @@ SyntaxerManager::SyntaxerManager() } -QSynedit::PSyntaxer SyntaxerManager::getSyntaxer(QSynedit::ProgrammingLanguage language) +QSynedit::PSyntaxer SyntaxerManager::getSyntaxer(QSynedit::ProgrammingLanguage language) const { switch(language) { case QSynedit::ProgrammingLanguage::CPP: @@ -49,12 +50,38 @@ QSynedit::PSyntaxer SyntaxerManager::getSyntaxer(QSynedit::ProgrammingLanguage l return std::make_shared(); case QSynedit::ProgrammingLanguage::LUA: return std::make_shared(); + case QSynedit::ProgrammingLanguage::XMAKE: { + auto syntaxer=getSyntaxer(QSynedit::ProgrammingLanguage::LUA); + QSynedit::LuaSyntaxer* pSyntaxer= (QSynedit::LuaSyntaxer*)syntaxer.get(); + pSyntaxer->setUseXMakeLibs(true); + return syntaxer; + } default: return QSynedit::PSyntaxer(); } } -QSynedit::PSyntaxer SyntaxerManager::getSyntaxer(const QString &filename) +QSynedit::PSyntaxer SyntaxerManager::getSyntaxer(const QString &filename) const +{ + return getSyntaxer(getLanguage(filename)); +} + +QSynedit::PFormatter SyntaxerManager::getFormatter(QSynedit::ProgrammingLanguage language) const +{ + switch(language) { + case QSynedit::ProgrammingLanguage::CPP: + return std::make_shared(); + default: + return QSynedit::PFormatter(); + } +} + +QSynedit::PFormatter SyntaxerManager::getFormatter(const QString &filename) const +{ + return getFormatter(getLanguage(filename)); +} + +QSynedit::ProgrammingLanguage SyntaxerManager::getLanguage(const QString &filename) const { QFileInfo info(filename); QString suffix = info.suffix(); @@ -64,37 +91,34 @@ QSynedit::PSyntaxer SyntaxerManager::getSyntaxer(const QString &filename) || suffix == "hxx" || suffix == "hh" || suffix == "C" || suffix == "CPP" || suffix =="H" || suffix == "c++" || suffix == "h++") { - return getSyntaxer(QSynedit::ProgrammingLanguage::CPP); + return QSynedit::ProgrammingLanguage::CPP; } else if (suffix == "vs" || suffix == "fs" || suffix == "frag") { - return getSyntaxer(QSynedit::ProgrammingLanguage::GLSL); + return QSynedit::ProgrammingLanguage::GLSL; } else if (suffix == "asm") { - return getSyntaxer(QSynedit::ProgrammingLanguage::Assembly); + return QSynedit::ProgrammingLanguage::Assembly; } else if (suffix == "s" || suffix == "S") { - return getSyntaxer(QSynedit::ProgrammingLanguage::ATTAssembly); + return QSynedit::ProgrammingLanguage::ATTAssembly; } else if (suffix == "lua") { if (basename=="xmake") { - auto syntaxer=getSyntaxer(QSynedit::ProgrammingLanguage::LUA); - QSynedit::LuaSyntaxer* pSyntaxer= (QSynedit::LuaSyntaxer*)syntaxer.get(); - pSyntaxer->setUseXMakeLibs(true); - return syntaxer; + return QSynedit::ProgrammingLanguage::XMAKE; } else - return getSyntaxer(QSynedit::ProgrammingLanguage::LUA); + return QSynedit::ProgrammingLanguage::LUA; } else if (basename.compare("makefile", Qt::CaseInsensitive)==0) { - return getSyntaxer(QSynedit::ProgrammingLanguage::Makefile); + return QSynedit::ProgrammingLanguage::Makefile; } else if (suffix.isEmpty()) { - return getSyntaxer(QSynedit::ProgrammingLanguage::CPP); + return QSynedit::ProgrammingLanguage::CPP; } - return QSynedit::PSyntaxer(); + return QSynedit::ProgrammingLanguage::Unknown; } -QSynedit::PSyntaxer SyntaxerManager::copy(QSynedit::PSyntaxer syntaxer) +QSynedit::PSyntaxer SyntaxerManager::copy(QSynedit::PSyntaxer syntaxer) const { if (!syntaxer) return QSynedit::PSyntaxer(); return getSyntaxer(syntaxer->language()); } -void SyntaxerManager::applyColorScheme(QSynedit::PSyntaxer syntaxer, const QString &schemeName) +void SyntaxerManager::applyColorScheme(QSynedit::PSyntaxer syntaxer, const QString &schemeName) const { if (!syntaxer) return; diff --git a/RedPandaIDE/syntaxermanager.h b/RedPandaIDE/syntaxermanager.h index f79de7bb..11f2bb47 100644 --- a/RedPandaIDE/syntaxermanager.h +++ b/RedPandaIDE/syntaxermanager.h @@ -17,16 +17,20 @@ #ifndef SYNTAXERMANAGER_H #define SYNTAXERMANAGER_H #include "qsynedit/syntaxer/syntaxer.h" +#include "qsynedit/formatter/formatter.h" class SyntaxerManager { public: SyntaxerManager(); - QSynedit::PSyntaxer getSyntaxer(QSynedit::ProgrammingLanguage language); - QSynedit::PSyntaxer getSyntaxer(const QString& filename); - QSynedit::PSyntaxer copy(QSynedit::PSyntaxer syntaxer); - void applyColorScheme(QSynedit::PSyntaxer syntaxer, const QString& schemeName); + QSynedit::PSyntaxer getSyntaxer(QSynedit::ProgrammingLanguage language) const; + QSynedit::PSyntaxer getSyntaxer(const QString& filename) const; + QSynedit::PFormatter getFormatter(QSynedit::ProgrammingLanguage language) const; + QSynedit::PFormatter getFormatter(const QString& filename) const; + QSynedit::ProgrammingLanguage getLanguage(const QString& filename) const; + QSynedit::PSyntaxer copy(QSynedit::PSyntaxer syntaxer) const; + void applyColorScheme(QSynedit::PSyntaxer syntaxer, const QString& schemeName) const; }; extern SyntaxerManager syntaxerManager; diff --git a/libs/qsynedit/qsynedit.pro b/libs/qsynedit/qsynedit.pro index 925b7d32..bf1dbf07 100644 --- a/libs/qsynedit/qsynedit.pro +++ b/libs/qsynedit/qsynedit.pro @@ -30,6 +30,8 @@ msvc { SOURCES += qsynedit/codefolding.cpp \ qsynedit/constants.cpp \ qsynedit/document.cpp \ + qsynedit/formatter/cppformatter.cpp \ + qsynedit/formatter/formatter.cpp \ qsynedit/keystrokes.cpp \ qsynedit/miscprocs.cpp \ qsynedit/exporter/exporter.cpp \ @@ -54,6 +56,8 @@ HEADERS += \ qsynedit/codefolding.h \ qsynedit/constants.h \ qsynedit/document.h \ + qsynedit/formatter/cppformatter.h \ + qsynedit/formatter/formatter.h \ qsynedit/keystrokes.h \ qsynedit/miscprocs.h \ qsynedit/types.h \ diff --git a/libs/qsynedit/qsynedit/formatter/cppformatter.cpp b/libs/qsynedit/qsynedit/formatter/cppformatter.cpp new file mode 100644 index 00000000..e7237a06 --- /dev/null +++ b/libs/qsynedit/qsynedit/formatter/cppformatter.cpp @@ -0,0 +1,141 @@ +#include "cppformatter.h" +#include "../qsynedit.h" +#include "../syntaxer/cpp.h" + + +namespace QSynedit { + CppFormatter::CppFormatter() + { + + } + + ProgrammingLanguage CppFormatter::supportLanguage() + { + return ProgrammingLanguage::CPP; + } + + int CppFormatter::calcIndentSpaces(int line, const QString &lineText, bool addIndent, + QSynEdit *editor) + { + Q_ASSERT(editor!=nullptr); + if (!editor->syntaxer()) + return 0; + line = std::min(line, editor->document()->count()+1); + if (line<=1) + return 0; + // find the first non-empty preceeding line + int startLine = line-1; + QString startLineText; + while (startLine>=1) { + startLineText = editor->document()->getLine(startLine-1); + if (!startLineText.startsWith('#') && !startLineText.trimmed().isEmpty()) { + break; + } + startLine -- ; + } + int indentSpaces = 0; + if (startLine>=1) { + //calculate the indents of last statement; + indentSpaces = editor->leftSpaces(startLineText); + if (editor->syntaxer()->language() != ProgrammingLanguage::CPP) + return indentSpaces; + SyntaxState rangePreceeding = editor->document()->getSyntaxState(startLine-1); + if (addIndent) { + // QString trimmedS = s.trimmed(); + QString trimmedLineText = lineText.trimmed(); + editor->syntaxer()->setState(rangePreceeding); + editor->syntaxer()->setLine(trimmedLineText,line-1); + SyntaxState rangeAfterFirstToken = editor->syntaxer()->getState(); + QString firstToken = editor->syntaxer()->getToken(); + PTokenAttribute attr = editor->syntaxer()->getTokenAttribute(); + if ( + attr->tokenType() == TokenType::Keyword + + && lineText.endsWith(':') + && ( + (getBoolOption("IndentClassMemberVisibilityKeywords",true) + && ( + firstToken == "public" || firstToken == "private" + || firstToken == "protected" + ) + ) + || + (getBoolOption("IndentSwitchCases",true) + && ( + firstToken == "case" + || firstToken == "default" + ) + ) + ) + ) { + // public: private: protecte: case: should indents like it's parent statement + editor->syntaxer()->setState(rangePreceeding); + editor->syntaxer()->setLine("}",line-1); + rangeAfterFirstToken = editor->syntaxer()->getState(); + firstToken = editor->syntaxer()->getToken(); + attr = editor->syntaxer()->getTokenAttribute(); + } + // qDebug()<syntaxer().get())->preprocessorAttribute()) { + indentSpaces=0; + } else if (editor->syntaxer()->isLastLineCommentNotFinished(rangePreceeding.state) + ) { + // last line is a not finished comment, + if (trimmedLineText.startsWith("*")) { + // this line start with "* " + // it means this line is a docstring, should indents according to + // the line the comment beginning , and add 1 additional space + int commentStartLine = findCommentStartLine(startLine-1,editor); + SyntaxState range; + indentSpaces = editor->leftSpaces(editor->document()->getLine(commentStartLine-1))+1; + range = editor->document()->getSyntaxState(commentStartLine-1); + } else { + //indents according to the beginning of the comment and 2 additional space + int commentStartLine = findCommentStartLine(startLine-1,editor); + SyntaxState range; + indentSpaces = editor->leftSpaces(editor->document()->getLine(commentStartLine-1))+2; + range = editor->document()->getSyntaxState(commentStartLine-1); + } + } else if (rangeAfterFirstToken.lastUnindent.type!=IndentType::None + && firstToken=="}") { + IndentInfo matchingIndents = rangeAfterFirstToken.lastUnindent; + indentSpaces = editor->leftSpaces(editor->document()->getLine(matchingIndents.line)); + } else if (firstToken=="{") { + IndentInfo matchingIndents = rangeAfterFirstToken.getLastIndent(); + indentSpaces = editor->leftSpaces(editor->document()->getLine(matchingIndents.line)); + } else if (rangePreceeding.getLastIndentType()!=IndentType::None) { + IndentInfo matchingIndents = rangePreceeding.getLastIndent(); + indentSpaces = editor->leftSpaces(editor->document()->getLine(matchingIndents.line))+editor->tabWidth(); + } else { + indentSpaces = 0; + } + } + } + return std::max(0,indentSpaces); + } + + int CppFormatter::findCommentStartLine(int searchStartLine, QSynEdit* editor) + { + int commentStartLine = searchStartLine; + SyntaxState range; + while (commentStartLine>=1) { + range = editor->document()->getSyntaxState(commentStartLine-1); + if (!editor->syntaxer()->isLastLineCommentNotFinished(range.state)){ + commentStartLine++; + break; + } + commentStartLine--; + } + if (commentStartLine<1) + commentStartLine = 1; + return commentStartLine; + } + + void CppFormatter::doInitOptions() + { + mOptions.insert("IndentClassMemberVisibilityKeywords",true); + mOptions.insert("IndentSwitchCases",true); + } +} diff --git a/libs/qsynedit/qsynedit/formatter/cppformatter.h b/libs/qsynedit/qsynedit/formatter/cppformatter.h new file mode 100644 index 00000000..e55bbdc7 --- /dev/null +++ b/libs/qsynedit/qsynedit/formatter/cppformatter.h @@ -0,0 +1,26 @@ +#ifndef QSYNEDIT_CPPFORMATTER_H +#define QSYNEDIT_CPPFORMATTER_H + +#include "formatter.h" + +namespace QSynedit { +class CppFormatter : public Formatter +{ +public: + CppFormatter(); + + // IndentCalculator interface +public: + ProgrammingLanguage supportLanguage() override; + int calcIndentSpaces(int line, const QString &lineText, bool addIndent, + QSynEdit *editor) override; + + + // IndentCalculator interface +protected: + int findCommentStartLine(int searchStartLine, QSynEdit *editor); + void doInitOptions() override; +}; +} + +#endif // CPPFORMATTER_H diff --git a/libs/qsynedit/qsynedit/formatter/formatter.cpp b/libs/qsynedit/qsynedit/formatter/formatter.cpp new file mode 100644 index 00000000..2b98b275 --- /dev/null +++ b/libs/qsynedit/qsynedit/formatter/formatter.cpp @@ -0,0 +1,54 @@ +#include "formatter.h" +namespace QSynedit { + Formatter::Formatter() + { + } + + const QStringList &Formatter::optionNames() const + { + return mOptionNames; + } + + void Formatter::setOption(const QString &name, QVariant val) + { + Q_ASSERT(mOptions.contains("name")); + mOptions.insert(name,val); + } + + QVariant Formatter::getOption(const QString &name, const QVariant& defaultValue) const + { + return mOptions.value(name,defaultValue); + } + + bool Formatter::getBoolOption(const QString &name, bool defaultValue) const + { + QVariant val = getOption(name); + if (val.isValid()) + return val.toBool(); + else + return defaultValue; + } + + QString Formatter::getStringOption(const QString &name, const QString &defaultValue) const + { + return getOption(name,defaultValue).toString(); + } + + int Formatter::getIntOption(const QString &name, int defaultValue) const + { + bool ok; + int val = getOption(name,defaultValue).toInt(&ok); + if (!ok) + return defaultValue; + else + return val; + } + + void Formatter::initOptions() + { + doInitOptions(); + mOptionNames.clear(); + foreach(const QString& s, mOptions.keys()) + mOptionNames.append(s); + } +} diff --git a/libs/qsynedit/qsynedit/formatter/formatter.h b/libs/qsynedit/qsynedit/formatter/formatter.h new file mode 100644 index 00000000..2da2b669 --- /dev/null +++ b/libs/qsynedit/qsynedit/formatter/formatter.h @@ -0,0 +1,33 @@ +#ifndef QSYNEDIT_FORMATTER_H +#define QSYNEDIT_FORMATTER_H +#include "../types.h" +#include +#include +#include +#include +namespace QSynedit { + class QSynEdit; + class Formatter + { + public: + Formatter(); + virtual ProgrammingLanguage supportLanguage()=0; + const QStringList &optionNames() const; + void setOption(const QString& name, QVariant val); + QVariant getOption(const QString& name, const QVariant& defaultValue=QVariant()) const; + bool getBoolOption(const QString& name,bool defaultValue) const; + QString getStringOption(const QString& name,const QString& defaultValue) const; + int getIntOption(const QString& name,int defaultValue) const; + virtual int calcIndentSpaces(int line, const QString& lineText, bool addIndent, + QSynEdit *editor)=0; + void initOptions(); + protected: + virtual void doInitOptions() = 0; + protected: + QMap mOptions; + QStringList mOptionNames; + }; + using PFormatter = std::shared_ptr; +} + +#endif // FORMATTER_H diff --git a/libs/qsynedit/qsynedit/qsynedit.cpp b/libs/qsynedit/qsynedit/qsynedit.cpp index bfc580b0..757f45ca 100644 --- a/libs/qsynedit/qsynedit/qsynedit.cpp +++ b/libs/qsynedit/qsynedit/qsynedit.cpp @@ -1551,36 +1551,20 @@ void QSynEdit::doShrinkSelection(const BufferCoord &/*pos*/) //todo } -int QSynEdit::findCommentStartLine(int searchStartLine) -{ - int commentStartLine = searchStartLine; - SyntaxState range; - while (commentStartLine>=1) { - range = mDocument->getSyntaxState(commentStartLine-1); - if (!mSyntaxer->isLastLineCommentNotFinished(range.state)){ - commentStartLine++; - break; - } - commentStartLine--; - } - if (commentStartLine<1) - commentStartLine = 1; - return commentStartLine; -} - int QSynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent) { - if (!mSyntaxer) - return 0; line = std::min(line, mDocument->count()+1); if (line<=1) return 0; + if (mFormatter) { + return mFormatter->calcIndentSpaces(line,lineText,addIndent,this); + } // find the first non-empty preceeding line int startLine = line-1; QString startLineText; while (startLine>=1) { startLineText = mDocument->getLine(startLine-1); - if (!startLineText.startsWith('#') && !startLineText.trimmed().isEmpty()) { + if (!startLineText.trimmed().isEmpty()) { break; } startLine -- ; @@ -1589,71 +1573,6 @@ int QSynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent if (startLine>=1) { //calculate the indents of last statement; indentSpaces = leftSpaces(startLineText); - if (mSyntaxer->language() != ProgrammingLanguage::CPP) - return indentSpaces; - SyntaxState rangePreceeding = mDocument->getSyntaxState(startLine-1); - if (addIndent) { -// QString trimmedS = s.trimmed(); - QString trimmedLineText = lineText.trimmed(); - mSyntaxer->setState(rangePreceeding); - mSyntaxer->setLine(trimmedLineText,line-1); - SyntaxState rangeAfterFirstToken = mSyntaxer->getState(); - QString firstToken = mSyntaxer->getToken(); - PTokenAttribute attr = mSyntaxer->getTokenAttribute(); - if ( - (attr->tokenType() == TokenType::Keyword - && ( - firstToken == "public" || firstToken == "private" - || firstToken == "protected" || firstToken == "case" - || firstToken == "default" - ) - ) - && lineText.endsWith(':') - ) { - // public: private: protecte: case: should indents like it's parent statement - mSyntaxer->setState(rangePreceeding); - mSyntaxer->setLine("}",line-1); - rangeAfterFirstToken = mSyntaxer->getState(); - firstToken = mSyntaxer->getToken(); - attr = mSyntaxer->getTokenAttribute(); - } -// qDebug()<preprocessorAttribute()) { - indentSpaces=0; - } else if (mSyntaxer->isLastLineCommentNotFinished(rangePreceeding.state) - ) { - // last line is a not finished comment, - if (trimmedLineText.startsWith("*")) { - // this line start with "* " - // it means this line is a docstring, should indents according to - // the line the comment beginning , and add 1 additional space - int commentStartLine = findCommentStartLine(startLine-1); - SyntaxState range; - indentSpaces = leftSpaces(mDocument->getLine(commentStartLine-1))+1; - range = mDocument->getSyntaxState(commentStartLine-1); - } else { - //indents according to the beginning of the comment and 2 additional space - int commentStartLine = findCommentStartLine(startLine-1); - SyntaxState range; - indentSpaces = leftSpaces(mDocument->getLine(commentStartLine-1))+2; - range = mDocument->getSyntaxState(commentStartLine-1); - } - } else if (rangeAfterFirstToken.lastUnindent.type!=IndentType::None - && firstToken=="}") { - IndentInfo matchingIndents = rangeAfterFirstToken.lastUnindent; - indentSpaces = leftSpaces(mDocument->getLine(matchingIndents.line)); - } else if (firstToken=="{") { - IndentInfo matchingIndents = rangeAfterFirstToken.getLastIndent(); - indentSpaces = leftSpaces(mDocument->getLine(matchingIndents.line)); - } else if (rangePreceeding.getLastIndentType()!=IndentType::None) { - IndentInfo matchingIndents = rangePreceeding.getLastIndent(); - indentSpaces = leftSpaces(mDocument->getLine(matchingIndents.line))+tabWidth(); - } else { - indentSpaces = 0; - } - } } return std::max(0,indentSpaces); } @@ -3853,6 +3772,16 @@ void QSynEdit::onScrolled(int) invalidate(); } +const PFormatter &QSynEdit::formatter() const +{ + return mFormatter; +} + +void QSynEdit::setFormatter(const PFormatter &newFormatter) +{ + mFormatter = newFormatter; +} + const QDateTime &QSynEdit::lastModifyTime() const { return mLastModifyTime; diff --git a/libs/qsynedit/qsynedit/qsynedit.h b/libs/qsynedit/qsynedit/qsynedit.h index 6fc4dc61..2817040c 100644 --- a/libs/qsynedit/qsynedit/qsynedit.h +++ b/libs/qsynedit/qsynedit/qsynedit.h @@ -30,6 +30,7 @@ #include "document.h" #include "keystrokes.h" #include "searcher/baseseacher.h" +#include "formatter/formatter.h" namespace QSynedit { @@ -569,8 +570,6 @@ private: int calcIndentSpaces(int line, const QString& lineText, bool addIndent); - int findCommentStartLine(int searchStartLine); - int findStatementStartLine(int searchStartLine); void processGutterClick(QMouseEvent* event); @@ -749,6 +748,8 @@ private: int mWheelAccumulatedDeltaX; int mWheelAccumulatedDeltaY; + PFormatter mFormatter; + friend class QSynEditPainter; // QWidget interface @@ -791,6 +792,9 @@ protected: const QDateTime &lastModifyTime() const; + const PFormatter &formatter() const; + void setFormatter(const PFormatter &newFormatter); + protected: void dragEnterEvent(QDragEnterEvent *event) override; void dropEvent(QDropEvent *event) override; diff --git a/libs/qsynedit/qsynedit/syntaxer/syntaxer.h b/libs/qsynedit/qsynedit/syntaxer/syntaxer.h index 84916609..3be9963d 100644 --- a/libs/qsynedit/qsynedit/syntaxer/syntaxer.h +++ b/libs/qsynedit/qsynedit/syntaxer/syntaxer.h @@ -91,18 +91,6 @@ enum class TokenType { Embeded //language embeded in others }; -enum class ProgrammingLanguage { - DecideBySuffix, - Composition, - Assembly, - ATTAssembly, - CPP, - GLSL, - Makefile, - LUA, - Custom -}; - class TokenAttribute { public: explicit TokenAttribute(const QString& name, TokenType mTokenType); diff --git a/libs/qsynedit/qsynedit/types.h b/libs/qsynedit/qsynedit/types.h index 69e5dfee..422dcbcb 100644 --- a/libs/qsynedit/qsynedit/types.h +++ b/libs/qsynedit/qsynedit/types.h @@ -26,6 +26,20 @@ namespace QSynedit { enum class SelectionMode {Normal, Line, Column}; +enum class ProgrammingLanguage { + DecideBySuffix, + Composition, + Assembly, + ATTAssembly, + CPP, + GLSL, + Makefile, + LUA, + XMAKE, + Custom, + Unknown +}; + struct BufferCoord { int ch; int line;