diff --git a/NEWS.md b/NEWS.md index 59815f46..4200c217 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +Red Panda C++ Version 2.6 + + - enhancement: Highlighter for makefiles + Red Panda C++ Version 2.5 - enhancement: New color scheme Monokai (contributed by 小龙Dev(XiaoLoong@github)) diff --git a/RedPandaIDE/HighlighterManager.cpp b/RedPandaIDE/HighlighterManager.cpp index 1b74d12d..ad8cf533 100644 --- a/RedPandaIDE/HighlighterManager.cpp +++ b/RedPandaIDE/HighlighterManager.cpp @@ -21,6 +21,8 @@ #include "qsynedit/highlighter/cpp.h" #include "qsynedit/highlighter/asm.h" #include "qsynedit/highlighter/glsl.h" +#include "qsynedit/highlighter/makefilehighlighter.h" + #include "qsynedit/Constants.h" #include "colorscheme.h" @@ -38,6 +40,8 @@ QSynedit::PHighlighter HighlighterManager::getHighlighter(QSynedit::HighlighterL return getCppHighlighter(); case QSynedit::HighlighterLanguage::Asssembly: return getAsmHighlighter(); + case QSynedit::HighlighterLanguage::Makefile: + return getMakefileHighlighter(); case QSynedit::HighlighterLanguage::GLSL: return getGLSLHighlighter(); default: @@ -49,6 +53,7 @@ QSynedit::PHighlighter HighlighterManager::getHighlighter(const QString &filenam { QFileInfo info(filename); QString suffix = info.suffix(); + QString basename = info.baseName(); if (suffix.isEmpty() || suffix == "c" || suffix == "cpp" || suffix == "cxx" || suffix == "cc" || suffix == "h" || suffix == "hpp" || suffix == "hxx" || suffix == "hh" || suffix == "C" @@ -59,7 +64,8 @@ QSynedit::PHighlighter HighlighterManager::getHighlighter(const QString &filenam return getGLSLHighlighter(); } else if (suffix == "s" || suffix == "asm") { return getAsmHighlighter(); - } + } else if (basename.compare("makefile", Qt::CaseInsensitive)==0) + return getMakefileHighlighter(); return QSynedit::PHighlighter(); } @@ -67,14 +73,7 @@ QSynedit::PHighlighter HighlighterManager::copyHighlighter(QSynedit::PHighlighte { if (!highlighter) return QSynedit::PHighlighter(); - if (highlighter->language() == QSynedit::HighlighterLanguage::Cpp) - return getCppHighlighter(); - else if (highlighter->language() == QSynedit::HighlighterLanguage::Asssembly) - return getAsmHighlighter(); - else if (highlighter->language() == QSynedit::HighlighterLanguage::GLSL) - return getGLSLHighlighter(); - //todo - return QSynedit::PHighlighter(); + return getHighlighter(highlighter->language()); } QSynedit::PHighlighter HighlighterManager::getCppHighlighter() @@ -95,26 +94,29 @@ QSynedit::PHighlighter HighlighterManager::getGLSLHighlighter() return highlighter; } +QSynedit::PHighlighter HighlighterManager::getMakefileHighlighter() +{ + std::shared_ptr highlighter=std::make_shared(); + return highlighter; +} + void HighlighterManager::applyColorScheme(QSynedit::PHighlighter highlighter, const QString &schemeName) { if (!highlighter) return; - if ( (highlighter->language() == QSynedit::HighlighterLanguage::Cpp) - || (highlighter->language() == QSynedit::HighlighterLanguage::Asssembly) - ) { - for (QString name: highlighter->attributes().keys()) { - PColorSchemeItem item = pColorManager->getItem(schemeName,name); - if (item) { - QSynedit::PHighlighterAttribute attr = highlighter->attributes()[name]; - attr->setBackground(item->background()); - attr->setForeground(item->foreground()); - QSynedit::FontStyles styles = QSynedit::FontStyle::fsNone; - styles.setFlag(QSynedit::FontStyle::fsBold, item->bold()); - styles.setFlag(QSynedit::FontStyle::fsItalic, item->italic()); - styles.setFlag(QSynedit::FontStyle::fsUnderline, item->underlined()); - styles.setFlag(QSynedit::FontStyle::fsStrikeOut, item->strikeout()); - attr->setStyles(styles); - } + + for (QString name: highlighter->attributes().keys()) { + PColorSchemeItem item = pColorManager->getItem(schemeName,name); + if (item) { + QSynedit::PHighlighterAttribute attr = highlighter->attributes()[name]; + attr->setBackground(item->background()); + attr->setForeground(item->foreground()); + QSynedit::FontStyles styles = QSynedit::FontStyle::fsNone; + styles.setFlag(QSynedit::FontStyle::fsBold, item->bold()); + styles.setFlag(QSynedit::FontStyle::fsItalic, item->italic()); + styles.setFlag(QSynedit::FontStyle::fsUnderline, item->underlined()); + styles.setFlag(QSynedit::FontStyle::fsStrikeOut, item->strikeout()); + attr->setStyles(styles); } } } diff --git a/RedPandaIDE/HighlighterManager.h b/RedPandaIDE/HighlighterManager.h index 71ccc28f..b45fd8ea 100644 --- a/RedPandaIDE/HighlighterManager.h +++ b/RedPandaIDE/HighlighterManager.h @@ -29,6 +29,7 @@ public: QSynedit::PHighlighter getCppHighlighter(); QSynedit::PHighlighter getAsmHighlighter(); QSynedit::PHighlighter getGLSLHighlighter(); + QSynedit::PHighlighter getMakefileHighlighter(); void applyColorScheme(QSynedit::PHighlighter highlighter, const QString& schemeName); }; diff --git a/RedPandaIDE/RedPandaIDE.pro b/RedPandaIDE/RedPandaIDE.pro index fcef9278..0568db9c 100644 --- a/RedPandaIDE/RedPandaIDE.pro +++ b/RedPandaIDE/RedPandaIDE.pro @@ -467,7 +467,7 @@ RESOURCES += \ RC_ICONS = images/devcpp.ico images/associations/c.ico images/associations/cpp.ico images/associations/dev.ico images/associations/c.ico images/associations/cpp.ico images/associations/h.ico images/associations/hpp.ico -## fixed lrelease.prf +# fixed lrelease.prf qtPrepareTool(QMAKE_LRELEASE, lrelease) isEmpty(LRELEASE_DIR): LRELEASE_DIR = .qm diff --git a/RedPandaIDE/editor.cpp b/RedPandaIDE/editor.cpp index 96bd5121..db8ded5f 100644 --- a/RedPandaIDE/editor.cpp +++ b/RedPandaIDE/editor.cpp @@ -52,8 +52,6 @@ #include "project.h" #include -using namespace std; - SaveException::SaveException(const QString& reason) { mReason = reason; mReasonBuffer = mReason.toLocal8Bit(); @@ -912,7 +910,7 @@ void Editor::onGetEditingAreas(int Line, QSynedit::EditingAreaList &areaList) { areaList.clear(); if (mTabStopBegin>=0 && mTabStopY == Line) { - QSynedit::PEditingArea p = make_shared(); + QSynedit::PEditingArea p = std::make_shared(); p->type = QSynedit::EditingAreaType::eatRectangleBorder; // int spaceCount = leftSpaces(mLineBeforeTabStop); // int spaceBefore = mLineBeforeTabStop.length()-TrimLeft(mLineBeforeTabStop).length(); diff --git a/RedPandaIDE/mainwindow.cpp b/RedPandaIDE/mainwindow.cpp index 68de1ec2..4e3d63f4 100644 --- a/RedPandaIDE/mainwindow.cpp +++ b/RedPandaIDE/mainwindow.cpp @@ -1331,8 +1331,8 @@ void MainWindow::setProjectCurrentFile(const QString &filename) if (!unit) return; QModelIndex index = mProject->model()->getNodeIndex(unit->node().get()); - index = mProjectProxyModel->mapFromSource(index); if (index.isValid()) { + index = mProjectProxyModel->mapFromSource(index); ui->projectView->expand(index); ui->projectView->setCurrentIndex(index); } diff --git a/libs/qsynedit/qsynedit.pro b/libs/qsynedit/qsynedit.pro index 47c04403..03ee6929 100644 --- a/libs/qsynedit/qsynedit.pro +++ b/libs/qsynedit/qsynedit.pro @@ -39,7 +39,8 @@ SOURCES += qsynedit/CodeFolding.cpp \ qsynedit/Search.cpp \ qsynedit/SearchBase.cpp \ qsynedit/SearchRegex.cpp \ - qsynedit/Types.cpp + qsynedit/Types.cpp \ + qsynedit/highlighter/makefilehighlighter.cpp HEADERS += qsynedit/Search.h \ qsynedit/SearchBase.h \ @@ -62,5 +63,6 @@ HEADERS += qsynedit/Search.h \ qsynedit/highlighter/cpp.h \ qsynedit/highlighter/customhighlighterv1.h \ qsynedit/highlighter/glsl.h \ + qsynedit/highlighter/makefilehighlighter.h INCLUDEPATH += ../redpanda_qt_utils diff --git a/libs/qsynedit/qsynedit/highlighter/base.h b/libs/qsynedit/qsynedit/highlighter/base.h index 37a9c2ab..c948f785 100644 --- a/libs/qsynedit/qsynedit/highlighter/base.h +++ b/libs/qsynedit/qsynedit/highlighter/base.h @@ -80,6 +80,7 @@ enum class HighlighterLanguage { Asssembly, Cpp, GLSL, + Makefile, Custom }; diff --git a/libs/qsynedit/qsynedit/highlighter/makefilehighlighter.cpp b/libs/qsynedit/qsynedit/highlighter/makefilehighlighter.cpp new file mode 100644 index 00000000..ed5c85d1 --- /dev/null +++ b/libs/qsynedit/qsynedit/highlighter/makefilehighlighter.cpp @@ -0,0 +1,641 @@ +/* + * 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 "makefilehighlighter.h" +#include "../Constants.h" +//#include + +namespace QSynedit { +const QSet MakefileHighlighter::Directives { + "abspath", + "addprefix", + "addsuffix", + "and", + "AR", + "ARFLAGS", + "AS", + "ASFLAGS", + "basename", + "bindir", + + "call", + "CC", + "CFLAGS", + "CO", + "COFLAGS", + "COMSPEC", + "CPP", + "CPPFLAGS", + "CTANGLE", + "CURDIR", + "CWEAVE", + "CXX", + "CXXFLAGS", + + "define", + "DESTDIR", + "dir", + + "else", + "endef", + "endif", + "error", + "eval", + "exec_prefix", + "export", + + "FC", + "FFLAGS", + "file", + "filter", + "filter-out", + "findstring", + "firstword", + "flavor", + "foreach", + + "GET", + "GFLAGS", + "gmk-eval", + "gmk-expand", + "gmk_add_function", + "gmk_alloc", + "gmk_eval", + "gmk_expand", + "gmk_free", + "gmk_func_ptr", + "GNUmakefile", + "GPATH", + "guile", + + "if", + "if", + "ifdef", + "ifeq", + "ifndef", + "ifneq", + "include", + "info", + "intcmp", + + "join", + + "lastword", + "LDFLAGS", + "LDLIBS", + "let", + "LEX", + "LFLAGS", + "libexecdir", + "LINT", + "LINTFLAGS", + "load", + "LOADLIBES", + + "M2C", + "MAKE", + "MAKE", + "MAKECMDGOALS", + "Makefile", + "makefile", + "MAKEFILES", + "MAKEFILES", + "MAKEFILE_LIST", + "MAKEFLAGS", + "MAKEINFO", + "MAKELEVEL", + "MAKELEVEL", + "MAKEOVERRIDES", + "MAKESHELL" + "MAKE_HOST", + "MAKE_RESTARTS" + "MAKE_TERMERR" + "MAKE_TERMOUT" + "MAKE_VERSION", + "MFLAGS", + + "notdir", + + "or", + "origin", + "OUTPUT_OPTION", + "override", + + "patsubst", + "patsubst", + "PC", + "PFLAGS", + "prefix", + "private", + + "realpath", + "RFLAGS", + "RM", + + "sbindir", + "SHELL", + "shell", + "sort", + "strip", + "subst", + "subst", + "suffix", + "SUFFIXES", + + "TANGLE", + "TEX", + "TEXI2DVI", + + "undefine", + "unexport", + + "value", + "VPATH", + "VPATH", + "vpath", + "vpath", + + "warning", + "WEAVE", + "wildcard", + "wildcard", + "word", + "wordlist", + "words", + + "YACC", + "YFLAGS", +}; + +MakefileHighlighter::MakefileHighlighter() +{ + mTargetAttribute = std::make_shared(SYNS_AttrClass, TokenType::Identifier); + addAttribute(mTargetAttribute); + mCommandAttribute = std::make_shared(SYNS_AttrGlobalVariable, TokenType::Identifier); + addAttribute(mCommandAttribute); + mCommandParamAttribute = std::make_shared(SYNS_AttrPreprocessor, TokenType::Identifier); + addAttribute(mCommandParamAttribute); + mNumberAttribute = std::make_shared(SYNS_AttrNumber, TokenType::Number); + addAttribute(mNumberAttribute); + mVariableAttribute = std::make_shared(SYNS_AttrLocalVariable, TokenType::Identifier); + addAttribute(mVariableAttribute); + mExpressionAttribute = std::make_shared(SYNS_AttrFunction, TokenType::Identifier); + addAttribute(mExpressionAttribute); +} + +void MakefileHighlighter::procSpace() +{ + mTokenID = TokenId::Space; + while (mLine[mRun]!=0 && mLine[mRun]<=32) + mRun++; +} + +void MakefileHighlighter::procNumber() +{ + while (isNumberChar(mLine[mRun])) + mRun++; + mTokenID = TokenId::Number; +} + +void MakefileHighlighter::procNull() +{ + mTokenID = TokenId::Null; + mState = RangeState::Unknown; +} + +void MakefileHighlighter::procString(bool inExpression ) +{ + mState = RangeState::String; + mTokenID = TokenId::String; + while (mLine[mRun] != 0) { + if (mLine[mRun] == '\"') { + mRun++; + popState(); + break; + } else if (!inExpression && mLine[mRun] == '$') { + break; + } else if (isSpaceChar(mLine[mRun])) { + break; + } else + mRun++; + } + +} + +void MakefileHighlighter::procStringStart() +{ + mRun++; + pushState(); + procString(mState!=RangeState::BraceExpression + && mState!=RangeState::ParenthesisExpression); +} + +void MakefileHighlighter::procExpressionStart(ExpressionStartType type) +{ + mRun+=2; //skip '$(' or '${' + pushState(); + switch(type) { + case ExpressionStartType::Brace: + mState = RangeState::BraceExpression; + break; + case ExpressionStartType::Parenthesis: + mState = RangeState::ParenthesisExpression; + break; + } + mTokenID = TokenId::Expression; +} + +void MakefileHighlighter::procExpressionEnd() +{ + mTokenID = TokenId::Expression; + mRun+=1; + popState(); +} + +void MakefileHighlighter::procSymbol() +{ + mTokenID = TokenId::Symbol; + mRun+=1; +} + +void MakefileHighlighter::procVariableExpression() +{ + mRun+=1; //skip $ + while (isIdentStartChar(mLine[mRun])) + mRun++; + mTokenID = TokenId::Variable; +} + +void MakefileHighlighter::procAutoVariable() +{ + mRun+=1; //skip $ + switch(mLine[mRun].unicode()) { + case '@': + case '%': + case '<': + case '?': + case '^': + case '+': + case '|': + case '*': + case '$': + mRun+=1; + mTokenID=TokenId::Expression; + break; + default: + mTokenID=TokenId::Symbol; + break; + } +} + +void MakefileHighlighter::procAssignment() +{ + mTokenID = TokenId::Symbol; + mRun++; + mState = RangeState::Assignment; +} + +void MakefileHighlighter::procDollar() +{ + if (mLine[mRun+1]=='(') { + procExpressionStart(ExpressionStartType::Parenthesis); + } else if (mLine[mRun+1]=='{') { + procExpressionStart(ExpressionStartType::Brace); + } else if (isIdentStartChar(mLine[mRun+1])) { + procVariableExpression(); + } else { + procAutoVariable(); + } +} + +void MakefileHighlighter::procComment() +{ + mRun++; //skip # + mRun = mLineString.length(); + mTokenID = TokenId::Comment; +} + +void MakefileHighlighter::procIdentifier() +{ + int start = mRun; + while (isIdentChar(mLine[mRun])) { + mRun++; + } + QString s = mLineString.mid(start,mRun-start).toLower(); + if (Directives.contains(s)) { + mTokenID = TokenId::Directive; + } else { + switch(mState) { + case RangeState::Assignment: + case RangeState::BraceExpression: + case RangeState::ParenthesisExpression: + mTokenID = TokenId::Variable; + break; + case RangeState::CommandParameters: + mTokenID = TokenId::CommandParam; + break; + case RangeState::Command: + mTokenID = TokenId::Command; + mState = RangeState::CommandParameters; + break; + case RangeState::Prequisitions: + case RangeState::Unknown: + mTokenID = TokenId::Target; + break; + case RangeState::String: + mTokenID = TokenId::String; + break; + } + } +} + + +void MakefileHighlighter::pushState() +{ + mStates.push_back(mState); +} + +void MakefileHighlighter::popState() +{ + if (!mStates.empty()) { + mState = mStates.back(); + mStates.pop_back(); + } +} + +bool MakefileHighlighter::isIdentChar(const QChar &ch) const +{ + if (ch == '_' || ch =='-') { + return true; + } + if ((ch>='0') && (ch <= '9')) { + return true; + } + if ((ch>='a') && (ch <= 'z')) { + return true; + } + if ((ch>='A') && (ch <= 'Z')) { + return true; + } + return false; +} + +bool MakefileHighlighter::eol() const +{ + return mTokenID == TokenId::Null; +} + +QString MakefileHighlighter::languageName() +{ + return "makefile"; +} + +HighlighterLanguage MakefileHighlighter::language() +{ + return HighlighterLanguage::Makefile; +} + +QString MakefileHighlighter::getToken() const +{ + return mLineString.mid(mTokenPos,mRun-mTokenPos); +} + +const PHighlighterAttribute &MakefileHighlighter::getTokenAttribute() const +{ + /* + Directive, + Unknown + */ + switch(mTokenID) { + case TokenId::Comment: + return mCommentAttribute; + case TokenId::Target: + return mTargetAttribute; + case TokenId::Command: + return mCommandAttribute; + case TokenId::CommandParam: + return mCommandParamAttribute; + case TokenId::Number: + return mNumberAttribute; + case TokenId::Space: + return mWhitespaceAttribute; + case TokenId::String: + return mStringAttribute; + case TokenId::Identifier: + return mIdentifierAttribute; + case TokenId::Variable: + return mVariableAttribute; + case TokenId::Expression: + return mExpressionAttribute; + case TokenId::Symbol: + return mSymbolAttribute; + case TokenId::Directive: + return mKeywordAttribute; + default: + return mSymbolAttribute; + } +} + +int MakefileHighlighter::getTokenPos() +{ + return mTokenPos; +} + +void MakefileHighlighter::next() +{ + mTokenPos = mRun; + if (mLine[mRun].unicode()==0) { + procNull(); + return; + } else if (mRun==0 && mLine[mRun]=='\t') { + mState = RangeState::Command; + procSpace(); + return; + } else if (isSpaceChar(mLine[mRun].unicode())) { + procSpace(); + return; + } + switch(mState) { + case RangeState::String: + if (mLine[mRun] == '$') + procDollar(); + else + procString(false); + break; + case RangeState::Command: + case RangeState::CommandParameters: + case RangeState::Prequisitions: + case RangeState::Assignment: + switch(mLine[mRun].unicode()) { + case '$': + procDollar(); + break; + case '\"': + procStringStart(); + break; + case '#': + procComment(); + break; + default: + if (mLine[mRun]>='0' && mLine[mRun]<='9') { + procNumber(); + } else if (isIdentStartChar(mLine[mRun])) { + procIdentifier(); + } else { + procSymbol(); + } + } + break; + case RangeState::ParenthesisExpression: + case RangeState::BraceExpression: + switch(mLine[mRun].unicode()) { + case '$': + procDollar(); + break; + case ')': + if (mState == RangeState::ParenthesisExpression) + procExpressionEnd(); + else + procSymbol(); + break; + case '}': + if (mState == RangeState::BraceExpression) + procExpressionEnd(); + else + procSymbol(); + break; + case '#': + procComment(); + break; + case '@': + case '+': + case '*': + case '%': + case '^': + case '<': + case '?': + if (mLine[mRun]=='D' || mLine[mRun]=='F') { + //auto variable + mRun+=2; + mTokenID = TokenId::Variable; + } else + procSymbol(); + break; + default: + if (mLine[mRun]>='0' && mLine[mRun]<='9') { + procNumber(); + } else if (isIdentStartChar(mLine[mRun])) { + procIdentifier(); + } else { + procSymbol(); + } + } + break; + case RangeState::Unknown: + switch(mLine[mRun].unicode()) { + case '$': + procDollar(); + break; + case '#': + procComment(); + break; + case '\"': + procStringStart(); + break; + case '?': + case '+': + if (mLine[mRun+1]=='=') { + mRun++; + procAssignment(); + } else { + procSymbol(); + } + break; + case ':': + if (mLine[mRun+1]=='=') { + mRun++; + procAssignment(); + } else { + mRun++; + mTokenID = TokenId::Target; + mState = RangeState::Prequisitions; + } + break; + case '=': + procAssignment(); + break; + default: + if (mLine[mRun]>='0' && mLine[mRun]<='9') { + procNumber(); + } else if (isIdentStartChar(mLine[mRun])) { + procIdentifier(); + } else { + procSymbol(); + } + } + + } +} + +void MakefileHighlighter::setLine(const QString &newLine, int lineNumber) +{ + mLineString = newLine; + mLine = mLineString.data(); + mLineNumber = lineNumber; + mRun = 0; + next(); +} + +bool MakefileHighlighter::getTokenFinished() const +{ + return true; +} + +bool MakefileHighlighter::isLastLineCommentNotFinished(int /*state*/) const +{ + return false; +} + +bool MakefileHighlighter::isLastLineStringNotFinished(int /*state*/) const +{ + return false; +} + +HighlighterState MakefileHighlighter::getState() const +{ + HighlighterState state; + state.state = (int)mState; + return state; +} + +void MakefileHighlighter::setState(const HighlighterState & rangeState) +{ + mState = (RangeState)rangeState.state; + mStates.clear(); +} + +void MakefileHighlighter::resetState() +{ + mState = RangeState::Unknown; + mStates.clear(); +} + +QSet MakefileHighlighter::keywords() const +{ + return Directives; +} + +} diff --git a/libs/qsynedit/qsynedit/highlighter/makefilehighlighter.h b/libs/qsynedit/qsynedit/highlighter/makefilehighlighter.h new file mode 100644 index 00000000..05537a84 --- /dev/null +++ b/libs/qsynedit/qsynedit/highlighter/makefilehighlighter.h @@ -0,0 +1,146 @@ +/* + * 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 MAKEFILEHIGHLIGHTER_H +#define MAKEFILEHIGHLIGHTER_H + + +#include "base.h" +#include + +namespace QSynedit { + +class MakefileHighlighter : public Highlighter +{ + enum class TokenId { + Null, + Comment, + Target, + Command, + CommandParam, + Number, + Space, + String, + Identifier, + Variable, + Expression, + Symbol, + Directive + }; + + enum RangeState { + Unknown, String, + /* Targets, */ + Prequisitions, + Command, + CommandParameters, + ParenthesisExpression, + BraceExpression, + Assignment, + }; + + enum ExpressionStartType { + Parenthesis, + Brace + }; + + +public: + explicit MakefileHighlighter(); + + static const QSet Directives; +private: + QChar* mLine; + QString mLineString; + int mLineNumber; + int mRun; + int mStringLen; + int mTokenPos; + QVector mStates; + RangeState mState; + TokenId mTokenID; + + PHighlighterAttribute mTargetAttribute; + PHighlighterAttribute mCommandAttribute; + PHighlighterAttribute mCommandParamAttribute; + PHighlighterAttribute mNumberAttribute; + PHighlighterAttribute mVariableAttribute; + PHighlighterAttribute mExpressionAttribute; + +private: + void procSpace(); + void procNumber(); + void procNull(); + void procString(bool inExpression ); + void procStringStart(); + void procExpressionStart(ExpressionStartType type); + void procExpressionEnd(); + void procSymbol(); + void procVariableExpression(); + void procAutoVariable(); + void procAssignment(); + void procDollar(); + void procComment(); + void procIdentifier(); + + void pushState(); + void popState(); + bool isIdentStartChar(const QChar& ch) { + if (ch == '_') { + return true; + } + if ((ch>='a') && (ch <= 'z')) { + return true; + } + if ((ch>='A') && (ch <= 'Z')) { + return true; + } + return false; + } + + bool isNumberChar(const QChar& ch) { + return (ch>='0') && (ch<='9'); + } + + // SynHighlighter interface +public: + bool eol() const override; + + QString languageName() override; + HighlighterLanguage language() override; + QString getToken() const override; + const PHighlighterAttribute &getTokenAttribute() const override; + int getTokenPos() override; + void next() override; + void setLine(const QString &newLine, int lineNumber) override; + + // SynHighlighter interface +public: + bool getTokenFinished() const override; + bool isLastLineCommentNotFinished(int state) const override; + bool isLastLineStringNotFinished(int state) const override; + HighlighterState getState() const override; + void setState(const HighlighterState& rangeState) override; + void resetState() override; + + bool isIdentChar(const QChar& ch) const override; +public: + QSet keywords() const override; + +}; + +} +#endif // MAKEFILEHIGHLIGHTER_H