Pith - wedge
#include "WedgeHighlighter.h"
#include "WedgeHeader.h"
#include <QDateTime>
#include <QRegularExpression>

void WedgeHighlighter::highlightBlock(const QString &text) {

// next time high light

	int state = previousBlockState();
	if (state == -1) {
		state = 0;
	}

	QDateTime now = QDateTime::currentDateTime();
	QRegularExpression headerRegex = WedgeHeader::dateRegex(m_headerFormat, now.date());
	QString trimmedText = text.trimmed();

	if (headerRegex.match(text).hasMatch()) {
		state = 1;
	} else if (trimmedText.isEmpty()) {
		state = 0;
	} else if (state == 1 || state == 2) {
		static QRegularExpression timeRegex("^\\s*(\\d{2}):(\\d{2})");
		QRegularExpressionMatch timeMatch = timeRegex.match(text);

		if (timeMatch.hasMatch()) {
			int h = timeMatch.captured(1).toInt();
			int m = timeMatch.captured(2).toInt();
			int currentMinutes = now.time().hour() * 60 + now.time().minute();

			if ((h * 60 + m) > currentMinutes) {
				QTextCharFormat highlightFormat;
				highlightFormat.setBackground(m_highlightColor);
				setFormat(0, text.length(), highlightFormat);

				state = 3;
			} else {
				state = 2;
			}
		}
	} else if (state == 3) {
		state = 3;
	}

// trailing markers

	static const QString kMarks = QStringLiteral("!?*~");
	const bool closed = text.endsWith(')');
	const int tail = text.length() - (closed ? 1 : 0);
	int markEnd = tail;
	while (markEnd > 0 && kMarks.contains(text.at(markEnd - 1))) --markEnd;
	QString marks = text.mid(markEnd, tail - markEnd);
	int from = 0;
	int to = text.length();
	if (!marks.isEmpty()) {
        // paren scope
		int open = markEnd - 1;
		while (open >= 0 && text.at(open) != '(' && text.at(open) != ')') --open;
		if (open >= 0 && text.at(open) == '(') {
			from = open + 1;
			to = tail;
		} else if (closed) {
			marks.clear();
		}
	}
	if (!marks.isEmpty()) {
		int lead = from;
		while (lead < to && text.at(lead).isSpace()) ++lead;
		QTextCharFormat all;
		if (marks.contains('!')) {
			all.setFontWeight(QFont::Bold);
			all.setForeground(m_focusColor);
		}
		if (marks.contains('?')) all.setFontItalic(true);
		QTextCharFormat body = all;
		if (marks.contains('*')) body.setFontUnderline(true);
		if (marks.contains('~')) body.setFontStrikeOut(true);
		for (int i = from; i < to; ++i) {
			QTextCharFormat f = format(i);
			f.merge(i < lead ? all : body);
			setFormat(i, 1, f);
		}
	}

// comment fade regex

	static QRegularExpression commentRegex("(?<=^|\\s)//.*$");
	QRegularExpressionMatchIterator ci = commentRegex.globalMatch(text);
	while (ci.hasNext()) {
		QRegularExpressionMatch cm = ci.next();
		QColor faded = m_textColor;
		faded.setAlphaF(0.6);
		QTextCharFormat cFormat;
		cFormat.setForeground(faded);
		setFormat(cm.capturedStart(), cm.capturedLength(), cFormat);
	}

	setCurrentBlockState(state);
}