src/ldrawsyntaxhighlighter.cpp

Sun, 09 Apr 2023 15:59:08 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Sun, 09 Apr 2023 15:59:08 +0300
changeset 362
e1d646a4cbd8
parent 343
4a82990affd5
permissions
-rw-r--r--

Extracted the state of the program into a MainState structure, and extracted local functions of main() into static functions.
I was planning to make the core logic and state of the program into a Main class, which would be a QObject that would
have lots of signals and slots, but it looks like this works even without it

#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->bfcPattern, {
		&this->lineTypeFormat,
		&this->bfcFormat,
	});
	matchRegex(this->commentPattern, {
		&this->lineTypeFormat,
		&this->nameFormat,
	});
	if (not matched) {
		this->setFormat(0, text.length(), this->errorFormat);
	}
}

mercurial