refactor: formatter interface for qsynedit

This commit is contained in:
Roy Qu 2023-03-09 20:35:15 +08:00
parent ac9d62ee5e
commit 45578a2603
14 changed files with 402 additions and 119 deletions

View File

@ -111,11 +111,19 @@ Editor::Editor(QWidget *parent, const QString& filename,
resolveAutoDetectEncodingOption(); resolveAutoDetectEncodingOption();
if (syntaxer) { if (syntaxer) {
setSyntaxer(syntaxer); setSyntaxer(syntaxer);
setFormatter(syntaxerManager.getFormatter(syntaxer->language()));
setUseCodeFolding(true); setUseCodeFolding(true);
} else { } else {
setUseCodeFolding(false); 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 (mProject) {
if (syntaxer && syntaxer->language() == QSynedit::ProgrammingLanguage::CPP) if (syntaxer && syntaxer->language() == QSynedit::ProgrammingLanguage::CPP)
mParser = mProject->cppParser(); mParser = mProject->cppParser();
@ -481,10 +489,19 @@ bool Editor::saveAs(const QString &name, bool fromProject){
QSynedit::PSyntaxer newSyntaxer = syntaxerManager.getSyntaxer(mFilename); QSynedit::PSyntaxer newSyntaxer = syntaxerManager.getSyntaxer(mFilename);
if (newSyntaxer) { if (newSyntaxer) {
setUseCodeFolding(true); setUseCodeFolding(true);
setFormatter(syntaxerManager.getFormatter(newSyntaxer->language()));
} else { } else {
setUseCodeFolding(false); setUseCodeFolding(false);
setFormatter(syntaxerManager.getFormatter(QSynedit::ProgrammingLanguage::Unknown));
} }
setSyntaxer(newSyntaxer); 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) { if (!newSyntaxer || newSyntaxer->language() != QSynedit::ProgrammingLanguage::CPP) {
mSyntaxIssues.clear(); 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->setUndoLimit(pSettings->editor().undoLimit());
this->setUndoMemoryUsage(pSettings->editor().undoMemoryUsage()); this->setUndoMemoryUsage(pSettings->editor().undoMemoryUsage());

View File

@ -5933,11 +5933,36 @@ void Settings::Languages::setX86DialectOfASMGenerated(X86ASMDialect newX86Dialec
mX86DialectOfASMGenerated = newX86DialectOfASMGenerated; 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() void Settings::Languages::doSave()
{ {
//ASM
saveValue("no_debug_directives_when_generate_asm",mNoDebugDirectivesWhenGenerateASM); saveValue("no_debug_directives_when_generate_asm",mNoDebugDirectivesWhenGenerateASM);
saveValue("no_seh_directives_when_generate_asm",mNoSEHDirectivesWhenGenerateASM); saveValue("no_seh_directives_when_generate_asm",mNoSEHDirectivesWhenGenerateASM);
saveValue("x86_dialect_of_asm_generated",(int)mX86DialectOfASMGenerated); 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() void Settings::Languages::doLoad()
@ -5945,6 +5970,11 @@ void Settings::Languages::doLoad()
mNoDebugDirectivesWhenGenerateASM = boolValue("no_debug_directives_when_generate_asm",true); mNoDebugDirectivesWhenGenerateASM = boolValue("no_debug_directives_when_generate_asm",true);
mNoSEHDirectivesWhenGenerateASM = boolValue("no_seh_directives_when_generate_asm",false); mNoSEHDirectivesWhenGenerateASM = boolValue("no_seh_directives_when_generate_asm",false);
mX86DialectOfASMGenerated = (X86ASMDialect)intValue("x86_dialect_of_asm_generated",(int)X86ASMDialect::ATT); 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 bool Settings::Languages::noSEHDirectivesWhenGenerateASM() const

View File

@ -992,10 +992,18 @@ public:
X86ASMDialect x86DialectOfASMGenerated() const; X86ASMDialect x86DialectOfASMGenerated() const;
void setX86DialectOfASMGenerated(X86ASMDialect newX86DialectOfASMGenerated); void setX86DialectOfASMGenerated(X86ASMDialect newX86DialectOfASMGenerated);
bool indentCClassMemberVisibilityKeywords() const;
void setIndentCClassMemberVisibilityKeywords(bool newIndentCClassMemberVisibilityKeywords);
bool indentCSwitchCaseKeywords() const;
void setIndentCSwitchCaseKeywords(bool newIndentCSwitchCaseKeywords);
private: private:
bool mNoDebugDirectivesWhenGenerateASM; bool mNoDebugDirectivesWhenGenerateASM;
bool mNoSEHDirectivesWhenGenerateASM; bool mNoSEHDirectivesWhenGenerateASM;
X86ASMDialect mX86DialectOfASMGenerated; X86ASMDialect mX86DialectOfASMGenerated;
bool mIndentCClassMemberVisibilityKeywords;
bool mIndentCSwitchCaseKeywords;
protected: protected:
void doSave() override; void doSave() override;
void doLoad() override; void doLoad() override;

View File

@ -23,6 +23,7 @@
#include "qsynedit/syntaxer/glsl.h" #include "qsynedit/syntaxer/glsl.h"
#include "qsynedit/syntaxer/lua.h" #include "qsynedit/syntaxer/lua.h"
#include "qsynedit/syntaxer/makefile.h" #include "qsynedit/syntaxer/makefile.h"
#include "qsynedit/formatter/cppformatter.h"
#include "qsynedit/constants.h" #include "qsynedit/constants.h"
#include "colorscheme.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) { switch(language) {
case QSynedit::ProgrammingLanguage::CPP: case QSynedit::ProgrammingLanguage::CPP:
@ -49,12 +50,38 @@ QSynedit::PSyntaxer SyntaxerManager::getSyntaxer(QSynedit::ProgrammingLanguage l
return std::make_shared<QSynedit::GLSLSyntaxer>(); return std::make_shared<QSynedit::GLSLSyntaxer>();
case QSynedit::ProgrammingLanguage::LUA: case QSynedit::ProgrammingLanguage::LUA:
return std::make_shared<QSynedit::LuaSyntaxer>(); return std::make_shared<QSynedit::LuaSyntaxer>();
case QSynedit::ProgrammingLanguage::XMAKE: {
auto syntaxer=getSyntaxer(QSynedit::ProgrammingLanguage::LUA);
QSynedit::LuaSyntaxer* pSyntaxer= (QSynedit::LuaSyntaxer*)syntaxer.get();
pSyntaxer->setUseXMakeLibs(true);
return syntaxer;
}
default: default:
return QSynedit::PSyntaxer(); 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<QSynedit::CppFormatter>();
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); QFileInfo info(filename);
QString suffix = info.suffix(); QString suffix = info.suffix();
@ -64,37 +91,34 @@ QSynedit::PSyntaxer SyntaxerManager::getSyntaxer(const QString &filename)
|| suffix == "hxx" || suffix == "hh" || suffix == "C" || suffix == "hxx" || suffix == "hh" || suffix == "C"
|| suffix == "CPP" || suffix =="H" || suffix == "c++" || suffix == "CPP" || suffix =="H" || suffix == "c++"
|| suffix == "h++") { || suffix == "h++") {
return getSyntaxer(QSynedit::ProgrammingLanguage::CPP); return QSynedit::ProgrammingLanguage::CPP;
} else if (suffix == "vs" || suffix == "fs" || suffix == "frag") { } else if (suffix == "vs" || suffix == "fs" || suffix == "frag") {
return getSyntaxer(QSynedit::ProgrammingLanguage::GLSL); return QSynedit::ProgrammingLanguage::GLSL;
} else if (suffix == "asm") { } else if (suffix == "asm") {
return getSyntaxer(QSynedit::ProgrammingLanguage::Assembly); return QSynedit::ProgrammingLanguage::Assembly;
} else if (suffix == "s" || suffix == "S") { } else if (suffix == "s" || suffix == "S") {
return getSyntaxer(QSynedit::ProgrammingLanguage::ATTAssembly); return QSynedit::ProgrammingLanguage::ATTAssembly;
} else if (suffix == "lua") { } else if (suffix == "lua") {
if (basename=="xmake") { if (basename=="xmake") {
auto syntaxer=getSyntaxer(QSynedit::ProgrammingLanguage::LUA); return QSynedit::ProgrammingLanguage::XMAKE;
QSynedit::LuaSyntaxer* pSyntaxer= (QSynedit::LuaSyntaxer*)syntaxer.get();
pSyntaxer->setUseXMakeLibs(true);
return syntaxer;
} else } else
return getSyntaxer(QSynedit::ProgrammingLanguage::LUA); return QSynedit::ProgrammingLanguage::LUA;
} else if (basename.compare("makefile", Qt::CaseInsensitive)==0) { } else if (basename.compare("makefile", Qt::CaseInsensitive)==0) {
return getSyntaxer(QSynedit::ProgrammingLanguage::Makefile); return QSynedit::ProgrammingLanguage::Makefile;
} else if (suffix.isEmpty()) { } 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) if (!syntaxer)
return QSynedit::PSyntaxer(); return QSynedit::PSyntaxer();
return getSyntaxer(syntaxer->language()); 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) if (!syntaxer)
return; return;

View File

@ -17,16 +17,20 @@
#ifndef SYNTAXERMANAGER_H #ifndef SYNTAXERMANAGER_H
#define SYNTAXERMANAGER_H #define SYNTAXERMANAGER_H
#include "qsynedit/syntaxer/syntaxer.h" #include "qsynedit/syntaxer/syntaxer.h"
#include "qsynedit/formatter/formatter.h"
class SyntaxerManager class SyntaxerManager
{ {
public: public:
SyntaxerManager(); SyntaxerManager();
QSynedit::PSyntaxer getSyntaxer(QSynedit::ProgrammingLanguage language); QSynedit::PSyntaxer getSyntaxer(QSynedit::ProgrammingLanguage language) const;
QSynedit::PSyntaxer getSyntaxer(const QString& filename); QSynedit::PSyntaxer getSyntaxer(const QString& filename) const;
QSynedit::PSyntaxer copy(QSynedit::PSyntaxer syntaxer); QSynedit::PFormatter getFormatter(QSynedit::ProgrammingLanguage language) const;
void applyColorScheme(QSynedit::PSyntaxer syntaxer, const QString& schemeName); 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; extern SyntaxerManager syntaxerManager;

View File

@ -30,6 +30,8 @@ msvc {
SOURCES += qsynedit/codefolding.cpp \ SOURCES += qsynedit/codefolding.cpp \
qsynedit/constants.cpp \ qsynedit/constants.cpp \
qsynedit/document.cpp \ qsynedit/document.cpp \
qsynedit/formatter/cppformatter.cpp \
qsynedit/formatter/formatter.cpp \
qsynedit/keystrokes.cpp \ qsynedit/keystrokes.cpp \
qsynedit/miscprocs.cpp \ qsynedit/miscprocs.cpp \
qsynedit/exporter/exporter.cpp \ qsynedit/exporter/exporter.cpp \
@ -54,6 +56,8 @@ HEADERS += \
qsynedit/codefolding.h \ qsynedit/codefolding.h \
qsynedit/constants.h \ qsynedit/constants.h \
qsynedit/document.h \ qsynedit/document.h \
qsynedit/formatter/cppformatter.h \
qsynedit/formatter/formatter.h \
qsynedit/keystrokes.h \ qsynedit/keystrokes.h \
qsynedit/miscprocs.h \ qsynedit/miscprocs.h \
qsynedit/types.h \ qsynedit/types.h \

View File

@ -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()<<line<<lineText;
// qDebug()<<(int)rangeAfterFirstToken.lastUnindent.type<<rangeAfterFirstToken.lastUnindent.line;
if (trimmedLineText.startsWith('#')
&& attr == ((CppSyntaxer *)editor->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);
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -0,0 +1,33 @@
#ifndef QSYNEDIT_FORMATTER_H
#define QSYNEDIT_FORMATTER_H
#include "../types.h"
#include <QMap>
#include <QSet>
#include <QString>
#include <QVariant>
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<QString,QVariant> mOptions;
QStringList mOptionNames;
};
using PFormatter = std::shared_ptr<Formatter>;
}
#endif // FORMATTER_H

View File

@ -1551,36 +1551,20 @@ void QSynEdit::doShrinkSelection(const BufferCoord &/*pos*/)
//todo //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) int QSynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent)
{ {
if (!mSyntaxer)
return 0;
line = std::min(line, mDocument->count()+1); line = std::min(line, mDocument->count()+1);
if (line<=1) if (line<=1)
return 0; return 0;
if (mFormatter) {
return mFormatter->calcIndentSpaces(line,lineText,addIndent,this);
}
// find the first non-empty preceeding line // find the first non-empty preceeding line
int startLine = line-1; int startLine = line-1;
QString startLineText; QString startLineText;
while (startLine>=1) { while (startLine>=1) {
startLineText = mDocument->getLine(startLine-1); startLineText = mDocument->getLine(startLine-1);
if (!startLineText.startsWith('#') && !startLineText.trimmed().isEmpty()) { if (!startLineText.trimmed().isEmpty()) {
break; break;
} }
startLine -- ; startLine -- ;
@ -1589,71 +1573,6 @@ int QSynEdit::calcIndentSpaces(int line, const QString& lineText, bool addIndent
if (startLine>=1) { if (startLine>=1) {
//calculate the indents of last statement; //calculate the indents of last statement;
indentSpaces = leftSpaces(startLineText); 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()<<line<<lineText;
// qDebug()<<(int)rangeAfterFirstToken.lastUnindent.type<<rangeAfterFirstToken.lastUnindent.line;
if (trimmedLineText.startsWith('#')
&& attr == ((CppSyntaxer *)mSyntaxer.get())->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); return std::max(0,indentSpaces);
} }
@ -3853,6 +3772,16 @@ void QSynEdit::onScrolled(int)
invalidate(); invalidate();
} }
const PFormatter &QSynEdit::formatter() const
{
return mFormatter;
}
void QSynEdit::setFormatter(const PFormatter &newFormatter)
{
mFormatter = newFormatter;
}
const QDateTime &QSynEdit::lastModifyTime() const const QDateTime &QSynEdit::lastModifyTime() const
{ {
return mLastModifyTime; return mLastModifyTime;

View File

@ -30,6 +30,7 @@
#include "document.h" #include "document.h"
#include "keystrokes.h" #include "keystrokes.h"
#include "searcher/baseseacher.h" #include "searcher/baseseacher.h"
#include "formatter/formatter.h"
namespace QSynedit { namespace QSynedit {
@ -569,8 +570,6 @@ private:
int calcIndentSpaces(int line, const QString& lineText, bool addIndent); int calcIndentSpaces(int line, const QString& lineText, bool addIndent);
int findCommentStartLine(int searchStartLine);
int findStatementStartLine(int searchStartLine);
void processGutterClick(QMouseEvent* event); void processGutterClick(QMouseEvent* event);
@ -749,6 +748,8 @@ private:
int mWheelAccumulatedDeltaX; int mWheelAccumulatedDeltaX;
int mWheelAccumulatedDeltaY; int mWheelAccumulatedDeltaY;
PFormatter mFormatter;
friend class QSynEditPainter; friend class QSynEditPainter;
// QWidget interface // QWidget interface
@ -791,6 +792,9 @@ protected:
const QDateTime &lastModifyTime() const; const QDateTime &lastModifyTime() const;
const PFormatter &formatter() const;
void setFormatter(const PFormatter &newFormatter);
protected: protected:
void dragEnterEvent(QDragEnterEvent *event) override; void dragEnterEvent(QDragEnterEvent *event) override;
void dropEvent(QDropEvent *event) override; void dropEvent(QDropEvent *event) override;

View File

@ -91,18 +91,6 @@ enum class TokenType {
Embeded //language embeded in others Embeded //language embeded in others
}; };
enum class ProgrammingLanguage {
DecideBySuffix,
Composition,
Assembly,
ATTAssembly,
CPP,
GLSL,
Makefile,
LUA,
Custom
};
class TokenAttribute { class TokenAttribute {
public: public:
explicit TokenAttribute(const QString& name, TokenType mTokenType); explicit TokenAttribute(const QString& name, TokenType mTokenType);

View File

@ -26,6 +26,20 @@ namespace QSynedit {
enum class SelectionMode {Normal, Line, Column}; enum class SelectionMode {Normal, Line, Column};
enum class ProgrammingLanguage {
DecideBySuffix,
Composition,
Assembly,
ATTAssembly,
CPP,
GLSL,
Makefile,
LUA,
XMAKE,
Custom,
Unknown
};
struct BufferCoord { struct BufferCoord {
int ch; int ch;
int line; int line;