refactor: formatter interface for qsynedit
This commit is contained in:
parent
ac9d62ee5e
commit
45578a2603
|
@ -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());
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<QSynedit::GLSLSyntaxer>();
|
||||
case QSynedit::ProgrammingLanguage::LUA:
|
||||
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:
|
||||
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);
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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()<<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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue