- Fehler in mehrzeiligen Kommentaren behoben

- Klammerpaare werden farblich hervorgehoben
- Beim einrücken oder ausrücken eines markierten Blocks wird die Zeile, in der der Coursor steht, nicht mehr mitgerückt
- Beim eintippen von Variablen wird eine Liste mit bereits deklarierten Variablen angezeigt
This commit is contained in:
2026-08-21 22:58:08 +02:00
parent aefa627e42
commit 53608725aa
13 changed files with 568 additions and 59 deletions

View File

@@ -11,6 +11,7 @@ SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent)
void SyntaxHighlighter::highlightBlock(const QString &text)
{
// Einzel-Zeilen-Regeln anwenden
for (const HighlightRule &rule : m_rules)
{
QRegularExpressionMatchIterator it = rule.pattern.globalMatch(text);
@@ -27,21 +28,65 @@ void SyntaxHighlighter::highlightBlock(const QString &text)
if (!m_hasMultiLineComment)
{
setCurrentBlockState(0);
return;
}
// Mehrzeilige Kommentare
// Zustand 0 = normal, 1 = mitten in /* ... */
setCurrentBlockState(0);
int startIndex = 0;
if (previousBlockState() != 1)
// Leere Zeile mitten im Kommentar — Zustand weitertragen
if (text.isEmpty())
{
if (previousBlockState() == 1)
{
setCurrentBlockState(1);
}
return;
}
int startIndex = 0;
if (previousBlockState() == 1)
{
// Vorherige Zeile war mitten im Kommentar — ab Zeilenanfang nach Ende suchen
QRegularExpressionMatch endMatch = m_commentEndExpression.match(text, 0);
if (endMatch.hasMatch())
{
// Ende des Kommentars gefunden
const int commentLength = static_cast<int>(endMatch.capturedStart())
+ static_cast<int>(endMatch.capturedLength());
setFormat(0, commentLength, m_multiLineCommentFormat);
// Nach weiteren Kommentaren in der gleichen Zeile suchen
QRegularExpressionMatch nextStart =
m_commentStartExpression.match(text, commentLength);
startIndex = nextStart.hasMatch()
? static_cast<int>(nextStart.capturedStart())
: -1;
}
else
{
// Noch kein Ende — gesamte Zeile ist Kommentar
setFormat(0, text.length(), m_multiLineCommentFormat);
setCurrentBlockState(1);
return;
}
}
else
{
// Neuen Kommentaranfang suchen
QRegularExpressionMatch m = m_commentStartExpression.match(text);
startIndex = m.hasMatch() ? static_cast<int>(m.capturedStart()) : -1;
}
while (startIndex >= 0)
{
QRegularExpressionMatch endMatch = m_commentEndExpression.match(text, startIndex);
QRegularExpressionMatch endMatch =
m_commentEndExpression.match(text, startIndex);
int commentLength = 0;
if (endMatch.hasMatch())
@@ -52,6 +97,7 @@ void SyntaxHighlighter::highlightBlock(const QString &text)
}
else
{
// Kommentar geht über Zeilenende
setCurrentBlockState(1);
commentLength = text.length() - startIndex;
}
@@ -63,6 +109,7 @@ void SyntaxHighlighter::highlightBlock(const QString &text)
break;
}
// Nach weiteren Kommentaren in dieser Zeile suchen
QRegularExpressionMatch nextStart =
m_commentStartExpression.match(text, startIndex + commentLength);
startIndex = nextStart.hasMatch()
@@ -374,14 +421,22 @@ void PhpHighlighter::highlightPhpRange(const QString &text, int start, int lengt
}
}
// /* */ Block-Kommentare innerhalb des PHP-Bereichs mehrzeilig behandeln.
// Block-Zustand 3 = wir sind mitten in einem /* ... */ PHP-Kommentar.
static const QRegularExpression blockOpen(R"(/\*)");
static const QRegularExpression blockClose(R"(\*/)");
int searchFrom = 0;
// Waren wir bereits in einem Block-Kommentar?
// Leere Zeile mitten im PHP-Blockkommentar — Zustand weitertragen
if (phpText.trimmed().isEmpty())
{
if (previousBlockState() == 3)
{
setFormat(start, length, m_phpCommentFormat);
setCurrentBlockState(3);
}
return;
}
if (previousBlockState() == 3)
{
QRegularExpressionMatch closeMatch = blockClose.match(phpText, 0);
@@ -391,18 +446,15 @@ void PhpHighlighter::highlightPhpRange(const QString &text, int start, int lengt
+ static_cast<int>(closeMatch.capturedLength());
setFormat(start, end, m_phpCommentFormat);
searchFrom = end;
// Block-Kommentar geschlossen — Zustand wird weiter unten gesetzt
}
else
{
// Gesamter Bereich ist noch Kommentar
setFormat(start, length, m_phpCommentFormat);
setCurrentBlockState(3);
return;
}
}
// Neue /* ... */ Kommentare innerhalb dieses PHP-Bereichs suchen
while (searchFrom < phpText.length())
{
QRegularExpressionMatch openMatch = blockOpen.match(phpText, searchFrom);
@@ -423,7 +475,6 @@ void PhpHighlighter::highlightPhpRange(const QString &text, int start, int lengt
}
else
{
// Kein schließendes */ gefunden — geht über Zeilenende
setFormat(start + openPos, length - openPos, m_phpCommentFormat);
setCurrentBlockState(3);
return;
@@ -434,13 +485,39 @@ void PhpHighlighter::highlightPhpRange(const QString &text, int start, int lengt
void PhpHighlighter::highlightBlock(const QString &text)
{
// Zuerst HTML-Basis-Regeln auf den gesamten Text anwenden
// (setzt auch den State für HTML <!-- --> Kommentare)
SyntaxHighlighter::highlightBlock(text);
// Block-Zustände:
// 0 = HTML-Modus
// 1 = HTML <!-- --> Kommentar (von Basisklasse verwaltet)
// 2 = innerhalb PHP-Block (kein /* */ Kommentar)
// 3 = innerhalb PHP /* */ Block-Kommentar
setCurrentBlockState(0);
// State 1 (HTML-Kommentar) wurde von der Basisklasse gesetzt — nicht überschreiben
if (currentBlockState() == 1)
{
return;
}
// Wenn der vorherige Block ein HTML-Kommentar war und dieser noch nicht
// abgeschlossen wurde, hat die Basisklasse das bereits korrekt behandelt.
// Wir setzen nur dann auf 0 zurück wenn wir sicher nicht in HTML-Kommentar sind.
if (previousBlockState() != 1)
{
setCurrentBlockState(0);
}
// Leere Zeile — Zustand weitertragen
if (text.isEmpty())
{
const int prev = previousBlockState();
if (prev == 2 || prev == 3)
{
setCurrentBlockState(prev);
}
return;
}
static const QRegularExpression phpOpen(R"(<\?(?:php|=)?\s?)",
QRegularExpression::CaseInsensitiveOption);
@@ -466,8 +543,6 @@ void PhpHighlighter::highlightBlock(const QString &text)
else
{
highlightPhpRange(text, 0, text.length());
// highlightPhpRange setzt den Zustand auf 3 falls nötig,
// sonst behalten wir 2 (offener PHP-Block ohne Kommentar)
if (currentBlockState() != 3)
{
setCurrentBlockState(2);