1

I am working on subclassed QSyntaxHighlighter:

UeSyntaxHiglighter::UeSyntaxHiglighter(QTextDocument* const parent)
    : QSyntaxHighlighter(parent)
{
    UeHighlightRule ruleInfo;
    UeHighlightRule ruleWarning;
    UeHighlightRule ruleError;
    UeHighlightRule ruleIPv4Address;
    UeHighlightRule rulePortNumber;
    UeHighlightRule ruleProtocolCommand;
    UeHighlightRule ruleProtocolCommandAcknowledge;

    QTextCharFormat ruleInfoFormat;
    QTextCharFormat ruleWarningFormat;
    QTextCharFormat ruleErrorFormat;;
    QTextCharFormat ruleIPv4AddressFormat;
    QTextCharFormat ruleProtocolCommandFormat;
    QTextCharFormat ruleProtocolCommandAcknowledgeFormat;

    ruleInfoFormat.setForeground(Qt::darkBlue);
    ruleInfoFormat.setFontWeight(QFont::ExtraLight);
    ruleInfo.pattern=QRegExp("^\\[INFO\\].*");
    ruleInfo.format=ruleInfoFormat;

    ruleWarningFormat.setForeground(Qt::darkYellow);
    ruleWarningFormat.setFontWeight(QFont::Normal);
    ruleWarning.pattern=QRegExp("^\\[WARNING\\].*");
    ruleWarning.format=ruleWarningFormat;

    ruleErrorFormat.setForeground(Qt::darkRed);
    ruleErrorFormat.setFontWeight(QFont::ExtraBold);
    ruleError.pattern=QRegExp("^\\[ERROR\\].*");
    ruleError.format=ruleErrorFormat;

    ruleIPv4AddressFormat.setFontWeight(QFont::ExtraBold);
    ruleIPv4Address.pattern=QRegExp("(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})");
    ruleIPv4Address.format=ruleIPv4AddressFormat;

    //BUG apply same coloring rule to port number as IP address
    rulePortNumber.pattern=QRegExp("\\d+$");
    rulePortNumber.format=ruleIPv4AddressFormat;

    ruleProtocolCommandFormat.setFontCapitalization(QFont::AllUppercase);
    ruleProtocolCommandFormat.setFontWeight(QFont::ExtraBold);
    ruleProtocolCommandFormat.setForeground(Qt::darkGreen);
    //BUG rule is not applied, i.e. text coloring is not active
    ruleProtocolCommand.pattern=QRegExp("^CMD.\\*");
    ruleProtocolCommand.format=ruleProtocolCommandFormat;

    ruleProtocolCommandAcknowledgeFormat.setFontCapitalization(QFont::AllUppercase);
    ruleProtocolCommandAcknowledgeFormat.setFontWeight(QFont::ExtraBold);
    ruleProtocolCommandAcknowledgeFormat.setForeground(Qt::darkMagenta);
    //BUG rule is not applied, i.e. text coloring is not active
    ruleProtocolCommandAcknowledge.pattern=QRegExp("^ACK.\\*");
    ruleProtocolCommandAcknowledge.format=ruleProtocolCommandAcknowledgeFormat;

    m_ueHighlightRules.append(ruleInfo);
    m_ueHighlightRules.append(ruleWarning);
    m_ueHighlightRules.append(ruleError);
    m_ueHighlightRules.append(ruleIPv4Address);
    m_ueHighlightRules.append(rulePortNumber);
    m_ueHighlightRules.append(ruleProtocolCommand);
    m_ueHighlightRules.append(ruleProtocolCommandAcknowledge);
}

Now, in app which is using this class, I have following sample log QString:

New incoming connection from host with IP address 192.168.1.4 using port 56748

What is the regular expression for port number (number at the end of string, which is following word port - case sensitive) AND excatly ONE whitespace?

KernelPanic
  • 2,328
  • 7
  • 47
  • 90
  • What is the pattern you tried and that did not work? Also, is there a possibility that the word `port` is followed with arbitrary number of whitespaces? – Wiktor Stribiżew Aug 01 '16 at 06:41
  • @WiktorStribiżew I've tried `rulePortNumber.pattern=QRegExp("\\d+$");`, however, it colors me **every** number at the end of **every** log string. – KernelPanic Aug 01 '16 at 06:42
  • That's true. If you have just 1 space between the number and `port`, you can try `(?<=\\bport )\\d+$`. However, this approach won't work if there can be 1 or more spaces, you'd need a capturing approach: `\\bport +(\\d+)$` (and access the capture #1). – Wiktor Stribiżew Aug 01 '16 at 06:43

2 Answers2

1

The \d+$ regex will match 1 or more digits at the end of the string, regardless of the left-hand context.

You should consider using a capturing approach: "\\bport +(\\d+)$" (and access the capture #1). That will require some code adjustment though.

The reason is that QRegExp does not support a lookbehind:

Both zero-width positive and zero-width negative lookahead assertions (?=pattern) and (?!pattern) are supported with the same syntax as Perl. Perl's lookbehind assertions, "independent" subexpressions and conditional expressions are not supported.

The space can be replaced with [ \t] if you only need to match ASCII horizontal whitespace (or you may try an \s with \r and \n excluded - "[^\\S\r\n]").

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Note I used string literals for the suggested patterns (hence double backslashes), while the regexes explained are just used inside backticks shown as code (and have single backslashes). – Wiktor Stribiżew Aug 01 '16 at 06:52
  • 1
    Also, if you had access to `QRegularExpression` in Qt5, you could use a better suited `\bport[ \t]+\K\d+$`. – Wiktor Stribiżew Aug 01 '16 at 06:58
  • Yes, that is true, I've followed [Syntax Highlighter Example](http://doc.qt.io/qt-5/qtwidgets-richtext-syntaxhighlighter-example.html). – KernelPanic Aug 01 '16 at 07:02
0

Is there a reason you couldn't use something like port \d+$ ?

a p
  • 3,098
  • 2
  • 24
  • 46