Add basic syntax highlighting

Mon, 04 Jul 2022 01:20:36 +0300

author
Teemu Piippo <teemu.s.piippo@gmail.com>
date
Mon, 04 Jul 2022 01:20:36 +0300
changeset 331
638a7458ef5e
parent 330
edb6c09cdd3c
child 332
ae7f7fbb9cda

Add basic syntax highlighting

CMakeLists.txt file | annotate | diff | comparison | revisions
src/ldrawsyntaxhighlighter.cpp file | annotate | diff | comparison | revisions
src/ldrawsyntaxhighlighter.h file | annotate | diff | comparison | revisions
src/main.cpp file | annotate | diff | comparison | revisions
--- 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(

mercurial