diff --git a/libs/core/highlighter_cfg.cpp b/libs/core/highlighter_cfg.cpp new file mode 100644 index 0000000..1609fa8 --- /dev/null +++ b/libs/core/highlighter_cfg.cpp @@ -0,0 +1,111 @@ +#include "highlighter_cfg.h" + +Highlighter_CFG::Highlighter_CFG(QTextDocument *parent) + : QSyntaxHighlighter(parent) { + HighlightingRule rule; + + // Command keywords: set, seta, bind, etc. + keywordFormat.setForeground(QColor("#569CD6")); + keywordFormat.setFontWeight(QFont::Bold); + const QString keywordPatterns[] = { + QStringLiteral("\\bset\\b"), + QStringLiteral("\\bseta\\b"), + QStringLiteral("\\bbind\\b"), + QStringLiteral("\\bvstr\\b"), + QStringLiteral("\\bsay\\b"), + QStringLiteral("\\bwait\\b"), + QStringLiteral("\\bexec\\b"), + QStringLiteral("\\bunbind\\b"), + QStringLiteral("\\bcreatefx\\b"), + QStringLiteral("\\bcreatefx_drawdist\\b"), + QStringLiteral("\\bcreatefx_scaleid\\b"), + QStringLiteral("\\bbindaxis\\b") + }; + for (const QString &pattern : keywordPatterns) { + rule.pattern = QRegularExpression(pattern); + rule.format = keywordFormat; + highlightingRules.append(rule); + } + + // Button constants: BUTTON_*, DPAD_* + buttonFormat.setForeground(QColor("#4EC9B0")); + rule.pattern = QRegularExpression(QStringLiteral("\\b(BUTTON|DPAD)_[A-Z]+\\b")); + rule.format = buttonFormat; + highlightingRules.append(rule); + + // Highlight *entire* 'bind var' or 'seta var' as one match, so we can highlight the variable part manually in highlightBlock() + // Regex captures the command and the following variable as two groups + bindSetVariablePattern = QRegularExpression(QStringLiteral("\\b(bind|bindaxis|set|seta)\\s+(\\w+)")); + + // Quoted strings (highlight first so numbers inside are overridden) + quotationFormat.setForeground(QColor("#CE9178")); + rule.pattern = QRegularExpression(QStringLiteral("\".*?\"")); + rule.format = quotationFormat; + highlightingRules.append(rule); + + // Numbers (normal numbers, no filtering for inside strings, since strings override them) + numberFormat.setForeground(QColor("#B5CEA8")); + rule.pattern = QRegularExpression(QStringLiteral("\\b-?\\d+(\\.\\d+)?f?\\b")); + rule.format = numberFormat; + highlightingRules.append(rule); + + // Comments: single-line comments with // + singleLineCommentFormat.setForeground(QColor("#6A9955")); + rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*")); + rule.format = singleLineCommentFormat; + highlightingRules.append(rule); + + // Command chaining symbol: ; + operatorFormat.setForeground(QColor("#D4D4D4")); + rule.pattern = QRegularExpression(QStringLiteral(";")); + rule.format = operatorFormat; + highlightingRules.append(rule); +} + +void Highlighter_CFG::highlightBlock(const QString &text) { + // Apply all standard highlighting rules + for (const HighlightingRule &rule : std::as_const(highlightingRules)) { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } + + // Highlight the immediate variable after 'bind', 'bindaxis', 'set', or 'seta' + QRegularExpressionMatchIterator iter = bindSetVariablePattern.globalMatch(text); + while (iter.hasNext()) { + QRegularExpressionMatch match = iter.next(); + int varStart = match.capturedStart(2); // Group 2 is the variable + int varLength = match.capturedLength(2); + setFormat(varStart, varLength, variableFormat); + } + + setCurrentBlockState(0); + + // Handle multiline comments safely + int startIndex = 0; + if (previousBlockState() != 1) + startIndex = text.indexOf(commentStartExpression); + + while (startIndex >= 0) { + QRegularExpressionMatch match = commentEndExpression.match(text, startIndex); + int endIndex = match.hasMatch() ? match.capturedStart() : -1; + + int commentLength; + if (endIndex == -1) { + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } else { + commentLength = endIndex - startIndex + match.capturedLength(); + } + + // Safety check to avoid infinite loops + if (commentLength <= 0) { + break; + } + + setFormat(startIndex, commentLength, multiLineCommentFormat); + startIndex = text.indexOf(commentStartExpression, startIndex + commentLength); + } +} diff --git a/libs/core/highlighter_cfg.h b/libs/core/highlighter_cfg.h new file mode 100644 index 0000000..a2a764a --- /dev/null +++ b/libs/core/highlighter_cfg.h @@ -0,0 +1,45 @@ +#ifndef HIGHLIGHTER_CFG_H +#define HIGHLIGHTER_CFG_H + +#include +#include + +class Highlighter_CFG : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + Highlighter_CFG(QTextDocument *parent = nullptr); + +protected: + void highlightBlock(const QString &text) override; + +private: + struct HighlightingRule + { + QRegularExpression pattern; + QTextCharFormat format; + }; + QList highlightingRules; + + QRegularExpression commentStartExpression; + QRegularExpression commentEndExpression; + QRegularExpression bindSetVariablePattern; + QTextCharFormat buttonFormat; + QTextCharFormat operatorFormat; + QTextCharFormat keywordFormat; + QTextCharFormat classFormat; + QTextCharFormat quotationFormat; + QTextCharFormat functionFormat; + QTextCharFormat singleLineCommentFormat; + QTextCharFormat multiLineCommentFormat; + QTextCharFormat preprocessorFormat; + QTextCharFormat variableFormat; + QTextCharFormat numberFormat; + QTextCharFormat devBlockCommentFormat; + + QRegularExpression devCommentStart; + QRegularExpression devCommentEnd; +}; + +#endif // HIGHLIGHTER_CFG_H diff --git a/libs/core/highlighter_gsc.cpp b/libs/core/highlighter_gsc.cpp new file mode 100644 index 0000000..94ea303 --- /dev/null +++ b/libs/core/highlighter_gsc.cpp @@ -0,0 +1,138 @@ +#include "highlighter_gsc.h" + +Highlighter_GSC::Highlighter_GSC(QTextDocument *parent) + : QSyntaxHighlighter(parent) { + HighlightingRule rule; + + // C++ Keywords + keywordFormat.setForeground(QColor("#569CD6")); + keywordFormat.setFontWeight(QFont::Bold); + const QString keywordPatterns[] = { + QStringLiteral("\\bchar\\b"), QStringLiteral("\\bclass\\b"), QStringLiteral("\\bconst\\b"), + QStringLiteral("\\bdouble\\b"), QStringLiteral("\\benum\\b"), QStringLiteral("\\bexplicit\\b"), + QStringLiteral("\\bfriend\\b"), QStringLiteral("\\binline\\b"), QStringLiteral("\\bint\\b"), + QStringLiteral("\\blong\\b"), QStringLiteral("\\bnamespace\\b"), QStringLiteral("\\boperator\\b"), + QStringLiteral("\\bprivate\\b"), QStringLiteral("\\bprotected\\b"), QStringLiteral("\\bpublic\\b"), + QStringLiteral("\\bshort\\b"), QStringLiteral("\\bsignals\\b"), QStringLiteral("\\bsigned\\b"), + QStringLiteral("\\bslots\\b"), QStringLiteral("\\bstatic\\b"), QStringLiteral("\\bstruct\\b"), + QStringLiteral("\\btemplate\\b"), QStringLiteral("\\btypedef\\b"), QStringLiteral("\\btypename\\b"), + QStringLiteral("\\bunion\\b"), QStringLiteral("\\bunsigned\\b"), QStringLiteral("\\bvirtual\\b"), + QStringLiteral("\\bvoid\\b"), QStringLiteral("\\bvolatile\\b"), QStringLiteral("\\bbool\\b") + }; + for (const QString &pattern : keywordPatterns) { + rule.pattern = QRegularExpression(pattern); + rule.format = keywordFormat; + highlightingRules.append(rule); + } + + // GSC Control Keywords + const QString gscKeywords[] = { + QStringLiteral("\\bif\\b"), QStringLiteral("\\belse\\b"), QStringLiteral("\\bswitch\\b"), + QStringLiteral("\\bcase\\b"), QStringLiteral("\\bbreak\\b"), QStringLiteral("\\bbreakpoint\\b"), + QStringLiteral("\\bcontinue\\b"), QStringLiteral("\\bfor\\b"), QStringLiteral("\\bwhile\\b"), + QStringLiteral("\\breturn\\b"), QStringLiteral("\\bdefault\\b"), QStringLiteral("\\bwait\\b"), + QStringLiteral("\\bwaittill\\b"), QStringLiteral("\\bwaittillframeend\\b"), + QStringLiteral("\\bendon\\b"), QStringLiteral("\\bnotify\\b"), QStringLiteral("\\bthread\\b") + }; + for (const QString &pattern : gscKeywords) { + rule.pattern = QRegularExpression(pattern); + rule.format = keywordFormat; + highlightingRules.append(rule); + } + + // Class format + classFormat.setForeground(QColor("#C586C0")); + classFormat.setFontWeight(QFont::Bold); + rule.pattern = QRegularExpression(QStringLiteral("\\bQ[A-Za-z]+\\b")); + rule.format = classFormat; + highlightingRules.append(rule); + + // Preprocessor: #include and #using_animtree + preprocessorFormat.setForeground(QColor("#D7BA7D")); + preprocessorFormat.setFontWeight(QFont::Bold); + rule.pattern = QRegularExpression(QStringLiteral("^\\s*#(?:include|using_animtree)\\b.*")); + rule.format = preprocessorFormat; + highlightingRules.append(rule); + + // Hardcoded Variables: self, level, game + variableFormat.setForeground(QColor("#4EC9B0")); + rule.pattern = QRegularExpression(QStringLiteral("\\b(self|level|game)\\b")); + rule.format = variableFormat; + highlightingRules.append(rule); + + // Quoted Strings + quotationFormat.setForeground(QColor("#CE9178")); + rule.pattern = QRegularExpression(QStringLiteral("\".*?\"")); + rule.format = quotationFormat; + highlightingRules.append(rule); + + // Numeric literals (including optional .f) + numberFormat.setForeground(QColor("#B5CEA8")); + rule.pattern = QRegularExpression(QStringLiteral("\\b-?\\d+(\\.\\d+)?f?\\b")); + rule.format = numberFormat; + highlightingRules.append(rule); + + // Boolean literals + rule.pattern = QRegularExpression(QStringLiteral("\\b(true|false|undefined)\\b")); + rule.format = numberFormat; + highlightingRules.append(rule); + + // Function calls + functionFormat.setForeground(QColor("#9CDCFE")); + functionFormat.setFontItalic(true); + rule.pattern = QRegularExpression(QStringLiteral("\\b[A-Za-z_][A-Za-z0-9_]*(?=\\s*\\()")); + rule.format = functionFormat; + highlightingRules.append(rule); + + // Function pointers ::func + rule.pattern = QRegularExpression(QStringLiteral("::\\b(\\w+)\\b")); + rule.format = functionFormat; + highlightingRules.append(rule); + + // Single-line comments + singleLineCommentFormat.setForeground(QColor("#6A9955")); + rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*")); + rule.format = singleLineCommentFormat; + highlightingRules.append(rule); + + // Developer block comments /# ... #/ + devBlockCommentFormat.setForeground(QColor("#6A9955")); + devCommentStart = QRegularExpression(QStringLiteral("/#")); + devCommentEnd = QRegularExpression(QStringLiteral("#/")); + + // Multi-line comment /* ... */ + multiLineCommentFormat.setForeground(QColor("#6A9955")); + commentStartExpression = QRegularExpression(QStringLiteral("/\\*")); + commentEndExpression = QRegularExpression(QStringLiteral("\\*/")); +} + + +void Highlighter_GSC::highlightBlock(const QString &text) { + for (const HighlightingRule &rule : std::as_const(highlightingRules)) { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } + setCurrentBlockState(0); + + int startIndex = 0; + if (previousBlockState() != 1) + startIndex = text.indexOf(commentStartExpression); + + while (startIndex >= 0) { + QRegularExpressionMatch match = commentEndExpression.match(text, startIndex); + int endIndex = match.capturedStart(); + int commentLength = 0; + if (endIndex == -1) { + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } else { + commentLength = endIndex - startIndex + + match.capturedLength(); + } + setFormat(startIndex, commentLength, multiLineCommentFormat); + startIndex = text.indexOf(commentStartExpression, startIndex + commentLength); + } +} diff --git a/libs/core/highlighter_gsc.h b/libs/core/highlighter_gsc.h new file mode 100644 index 0000000..0fbeb62 --- /dev/null +++ b/libs/core/highlighter_gsc.h @@ -0,0 +1,42 @@ +#ifndef HIGHLIGHTER_GSC_H +#define HIGHLIGHTER_GSC_H + +#include +#include + +class Highlighter_GSC : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + Highlighter_GSC(QTextDocument *parent = nullptr); + +protected: + void highlightBlock(const QString &text) override; + +private: + struct HighlightingRule + { + QRegularExpression pattern; + QTextCharFormat format; + }; + QList highlightingRules; + + QRegularExpression commentStartExpression; + QRegularExpression commentEndExpression; + QTextCharFormat keywordFormat; + QTextCharFormat classFormat; + QTextCharFormat quotationFormat; + QTextCharFormat functionFormat; + QTextCharFormat singleLineCommentFormat; + QTextCharFormat multiLineCommentFormat; + QTextCharFormat preprocessorFormat; + QTextCharFormat variableFormat; + QTextCharFormat numberFormat; + QTextCharFormat devBlockCommentFormat; + + QRegularExpression devCommentStart; + QRegularExpression devCommentEnd; +}; + +#endif // HIGHLIGHTER_GSC_H diff --git a/libs/core/highlighter_shock.cpp b/libs/core/highlighter_shock.cpp new file mode 100644 index 0000000..17f4675 --- /dev/null +++ b/libs/core/highlighter_shock.cpp @@ -0,0 +1,43 @@ +#include "highlighter_shock.h" + +Highlighter_Shock::Highlighter_Shock(QTextDocument *parent) + : QSyntaxHighlighter(parent) { + HighlightingRule rule; + + // Format for bg_shock_* keys + keyFormat.setForeground(QColor("#569CD6")); + keyFormat.setFontWeight(QFont::Bold); + rule.pattern = QRegularExpression(QStringLiteral("\\bbg_shock_[\\w]+\\b")); + rule.format = keyFormat; + highlightingRules.append(rule); + + // Format for quoted string values + stringFormat.setForeground(QColor("#CE9178")); + rule.pattern = QRegularExpression(QStringLiteral("\"[^\"]*\"")); + rule.format = stringFormat; + highlightingRules.append(rule); + + // Format for numeric values inside quotes (overridden by stringFormat but still useful for raw values) + numberFormat.setForeground(QColor("#B5CEA8")); + rule.pattern = QRegularExpression(QStringLiteral("-?\\d+(\\.\\d+)?")); + rule.format = numberFormat; + highlightingRules.append(rule); + + // Optional: Format for control groups (e.g., bg_shock_volume_*) + subgroupFormat.setForeground(QColor("#4EC9B0")); + rule.pattern = QRegularExpression(QStringLiteral("\\bbg_shock_volume_\\w+\\b")); + rule.format = subgroupFormat; + highlightingRules.append(rule); +} + +void Highlighter_Shock::highlightBlock(const QString &text) { + for (const HighlightingRule &rule : std::as_const(highlightingRules)) { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } + + setCurrentBlockState(0); +} diff --git a/libs/core/highlighter_shock.h b/libs/core/highlighter_shock.h new file mode 100644 index 0000000..7215c70 --- /dev/null +++ b/libs/core/highlighter_shock.h @@ -0,0 +1,30 @@ +#ifndef HIGHLIGHTER_SHOCK_H +#define HIGHLIGHTER_SHOCK_H + +#include +#include + +class Highlighter_Shock : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + Highlighter_Shock(QTextDocument *parent = nullptr); + +protected: + void highlightBlock(const QString &text) override; + +private: + struct HighlightingRule { + QRegularExpression pattern; + QTextCharFormat format; + }; + QVector highlightingRules; + + QTextCharFormat keyFormat; + QTextCharFormat stringFormat; + QTextCharFormat numberFormat; + QTextCharFormat subgroupFormat; +}; + +#endif // HIGHLIGHTER_SHOCK_H