Mon, 04 Jul 2022 01:20:36 +0300
Add basic syntax highlighting
--- a/CMakeLists.txt Mon Jul 04 00:23:50 2022 +0300 +++ b/CMakeLists.txt Mon Jul 04 01:20:36 2022 +0300 @@ -67,6 +67,7 @@ src/documentmanager.cpp src/geometry.cpp src/ldrawalgorithm.cpp + src/ldrawsyntaxhighlighter.cpp src/libraries.cpp src/inputvertices.cpp src/invert.cpp @@ -102,6 +103,7 @@ src/inputvertices.h src/invert.h src/ldrawalgorithm.h + src/ldrawsyntaxhighlighter.h src/libraries.h src/messagelog.h src/model.h
--- /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); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ldrawsyntaxhighlighter.h Mon Jul 04 01:20:36 2022 +0300 @@ -0,0 +1,29 @@ +#pragma once +#include <QSyntaxHighlighter> +#include <QRegularExpression> + +class LDrawSyntaxHighlighter final : public QSyntaxHighlighter +{ + Q_OBJECT + QRegularExpression commentPattern; + QRegularExpression bfcPattern; + QRegularExpression refPattern; + QRegularExpression trianglePattern; + QRegularExpression quadrilateralPattern; + QRegularExpression cedgePattern; + QTextCharFormat lineTypeFormat; + QTextCharFormat colorFormat; + QTextCharFormat point1Format; + QTextCharFormat point2Format; + QTextCharFormat point3Format; + QTextCharFormat point4Format; + QTextCharFormat bfcFormat; + QTextCharFormat nameFormat; + QTextCharFormat errorFormat; +public: + LDrawSyntaxHighlighter(QTextDocument* parent = nullptr); + + // QSyntaxHighlighter interface +protected: + void highlightBlock(const QString& text) override; +};
--- a/src/main.cpp Mon Jul 04 00:23:50 2022 +0300 +++ b/src/main.cpp Mon Jul 04 01:20:36 2022 +0300 @@ -21,6 +21,7 @@ #include "src/version.h" #include "src/widgets/colorselectdialog.h" #include "src/parser.h" +#include "src/ldrawsyntaxhighlighter.h" #include <GL/glew.h> static const QDir LOCALE_DIR {":/locale"}; @@ -529,6 +530,7 @@ data->textbuffer->setPlainText(modeltext); data->textbuffer->setDefaultFont(monospace()); data->textbuffer->setDocumentLayout(new QPlainTextDocumentLayout(data->textbuffer.get())); + new LDrawSyntaxHighlighter{data->textbuffer.get()}; data->textcursor = std::make_unique<QTextCursor>(data->textbuffer.get()); documents.setModelPayload(modelId, data); QObject::connect(