--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldrawsyntaxhighlighter.cpp Mon Jul 04 01:20:36 2022 +0300 @@ -0,0 +1,95 @@ +#include "ldrawsyntaxhighlighter.h" + +#define NUMBER_REGEX R"([+-]?(?:(?:\d+\.?\d*)|(?:\.\d+)))" +#define SPACE_REGEX R"(\s+)" +#define VEC3_REGEX "(" NUMBER_REGEX SPACE_REGEX NUMBER_REGEX SPACE_REGEX NUMBER_REGEX ")" +#define TWO_VECTORS VEC3_REGEX SPACE_REGEX VEC3_REGEX +#define THREE_VECTORS TWO_VECTORS SPACE_REGEX VEC3_REGEX +#define FOUR_VECTORS THREE_VECTORS SPACE_REGEX VEC3_REGEX + +LDrawSyntaxHighlighter::LDrawSyntaxHighlighter(QTextDocument* parent) : + QSyntaxHighlighter{parent} +{ + this->lineTypeFormat.setFontWeight(QFont::Bold); + this->point1Format.setForeground(Qt::green); + this->point2Format.setForeground(Qt::yellow); + this->point3Format.setForeground(Qt::cyan); + this->point4Format.setForeground(Qt::magenta); + this->point2Format.setFontWeight(QFont::Bold); + this->point4Format.setFontWeight(QFont::Bold); + this->nameFormat.setFontItalic(true); + this->bfcFormat.setForeground(Qt::green); + this->bfcFormat.setFontWeight(QFont::Bold); + this->errorFormat.setUnderlineColor(Qt::yellow); + this->errorFormat.setUnderlineStyle(QTextCharFormat::WaveUnderline); + this->refPattern = QRegularExpression{R"(^\s*(1)\s+(\d+)\s+)" FOUR_VECTORS SPACE_REGEX R"(([^ ]+)\s*$)"}; + this->trianglePattern = QRegularExpression{R"(^\s*(3)\s+(\d+)\s+)" THREE_VECTORS R"(\s*$)"}; + this->quadrilateralPattern = QRegularExpression{R"(^\s*(4)\s+(\d+)\s+)" FOUR_VECTORS R"(\s*$)"}; + this->cedgePattern = QRegularExpression{R"(^\s*(5)\s+(\d+)\s+)" FOUR_VECTORS R"(\s*$)"}; + this->bfcPattern = QRegularExpression{QStringLiteral( + R"(^\s*(0) (BFC (?:CERTIFY CCW|CERTIFY CW|NOCERTIFY|INVERTNEXT|CLIP|NOCLIP))\s*$)" + )}; + this->commentPattern = QRegularExpression{R"(^\s*(0)\s+(.+)$)"}; +} + +void LDrawSyntaxHighlighter::highlightBlock(const QString& text) +{ + bool matched = false; + const auto matchRegex = [&text, this, &matched]( + const QRegularExpression& re, + const QVector<const QTextCharFormat*> formats + ){ + if (not matched) { + QRegularExpressionMatch match = re.match(text); + if (match.hasMatch()) { + for (int i = 0; i < formats.size(); ++i) { + this->setFormat(match.capturedStart(i + 1), match.capturedLength(i + 1), *formats[i]); + } + } + matched = match.hasMatch(); + } + }; + matchRegex(this->refPattern, { + &this->lineTypeFormat, + &this->colorFormat, + &this->point1Format, + &this->point2Format, + &this->point3Format, + &this->point4Format, + &this->nameFormat, + }); + matchRegex(this->trianglePattern, { + &this->lineTypeFormat, + &this->colorFormat, + &this->point1Format, + &this->point2Format, + &this->point3Format, + }); + matchRegex(this->quadrilateralPattern, { + &this->lineTypeFormat, + &this->colorFormat, + &this->point1Format, + &this->point2Format, + &this->point3Format, + &this->point4Format, + }); + matchRegex(this->cedgePattern, { + &this->lineTypeFormat, + &this->colorFormat, + &this->point1Format, + &this->point2Format, + &this->point3Format, + &this->point4Format, + }); + matchRegex(this->commentPattern, { + &this->lineTypeFormat, + &this->nameFormat, + }); + matchRegex(this->bfcPattern, { + &this->lineTypeFormat, + &this->bfcFormat, + }); + if (not matched) { + this->setFormat(0, text.length(), this->errorFormat); + } +}