src/ldrawsyntaxhighlighter.cpp

changeset 331
638a7458ef5e
child 342
9fd7dcab6d76
--- /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);
+	}
+}

mercurial