common: Put scopeMatch in util, use in highlights
authorShane Synan <digitalcircuit36939@gmail.com>
Thu, 1 Mar 2018 08:06:42 +0000 (02:06 -0600)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 6 Jun 2018 17:15:14 +0000 (19:15 +0200)
Move ignore rule scopeMatch() to util to share usage with highlight
rule scope matching.

Use scopeMatch() in highlight rule channel name processing.

Advantages:
> Simpler to manage common cases
> Shares the same rules as ignore lists, already-learned behavior
Disadvantages:
> No way to escape ';' in rules
> No longer able to use full regular expressions
> Breaks existing channel name rules (also applies to local!)

(Another approach is to keep only local highlight rules inconsistent)

src/common/highlightrulemanager.cpp
src/common/ignorelistmanager.cpp
src/common/ignorelistmanager.h
src/common/util.cpp
src/common/util.h
src/qtui/qtuimessageprocessor.cpp

index aca87e6..f23f6aa 100644 (file)
@@ -141,17 +141,10 @@ bool HighlightRuleManager::match(const QString &msgContents,
         if (!rule.isEnabled)
             continue;
 
         if (!rule.isEnabled)
             continue;
 
-        if (rule.chanName.size() > 0 && rule.chanName.compare(".*") != 0) {
-            if (rule.chanName.startsWith("!")) {
-                QRegExp rx(rule.chanName.mid(1), Qt::CaseInsensitive);
-                if (rx.exactMatch(bufferName))
-                    continue;
-            }
-            else {
-                QRegExp rx(rule.chanName, Qt::CaseInsensitive);
-                if (!rx.exactMatch(bufferName))
-                    continue;
-            }
+        if (!rule.chanName.isEmpty() && !scopeMatch(rule.chanName, bufferName)) {
+            // A channel name rule is specified and does NOT match the current buffer name, skip
+            // this rule
+            continue;
         }
 
         QRegExp rx;
         }
 
         QRegExp rx;
index 1599cde..e2e515c 100644 (file)
@@ -160,62 +160,6 @@ IgnoreListManager::StrictnessType IgnoreListManager::_match(const QString &msgCo
 }
 
 
 }
 
 
-bool IgnoreListManager::scopeMatch(const QString &scopeRule, const QString &string) const
-{
-    // A match happens when the string does NOT match ANY inverted rules and matches AT LEAST one
-    // normal rule, unless no normal rules exist (implicit wildcard match).  This gives inverted
-    // rules higher priority regardless of ordering.
-    //
-    // TODO: After switching to Qt 5, use of this should be split into two parts, one part that
-    // would generate compiled QRegularExpressions for match/inverted match, regenerating it on any
-    // rule changes, and another part that would check each message against these compiled rules.
-
-    // Keep track if any matches are found
-    bool matches = false;
-    // Keep track if normal rules and inverted rules are found, allowing for implicit wildcard
-    bool normalRuleFound = false, invertedRuleFound = false;
-
-    // Split each scope rule by separator, ignoring empty parts
-    foreach(QString rule, scopeRule.split(";", QString::SkipEmptyParts)) {
-        // Trim whitespace from the start/end of the rule
-        rule = rule.trimmed();
-        // Ignore empty rules
-        if (rule.isEmpty())
-            continue;
-
-        // Check if this is an inverted rule (starts with '!')
-        if (rule.startsWith("!")) {
-            // Inverted rule found
-            invertedRuleFound = true;
-
-            // Take the reminder of the string
-            QRegExp ruleRx(rule.mid(1), Qt::CaseInsensitive);
-            ruleRx.setPatternSyntax(QRegExp::Wildcard);
-            if (ruleRx.exactMatch(string)) {
-                // Matches an inverted rule, full rule cannot match
-                return false;
-            }
-        } else {
-            // Normal rule found
-            normalRuleFound = true;
-
-            QRegExp ruleRx(rule, Qt::CaseInsensitive);
-            ruleRx.setPatternSyntax(QRegExp::Wildcard);
-            if (ruleRx.exactMatch(string)) {
-                // Matches a normal rule, full rule might match
-                matches = true;
-                // Continue checking in case other inverted rules negate this
-            }
-        }
-    }
-    // No inverted rules matched, okay to match normally
-    // Return true if...
-    // ...we found a normal match
-    // ...implicit wildcard: we had inverted rules (that didn't match) and no normal rules
-    return matches || (invertedRuleFound && !normalRuleFound);
-}
-
-
 void IgnoreListManager::removeIgnoreListItem(const QString &ignoreRule)
 {
     removeAt(indexOf(ignoreRule));
 void IgnoreListManager::removeIgnoreListItem(const QString &ignoreRule)
 {
     removeAt(indexOf(ignoreRule));
index ef86d5e..d5a1c8a 100644 (file)
@@ -26,6 +26,8 @@
 
 #include "message.h"
 #include "syncableobject.h"
 
 #include "message.h"
 #include "syncableobject.h"
+// Scope matching
+#include "util.h"
 
 class IgnoreListManager : public SyncableObject
 {
 
 class IgnoreListManager : public SyncableObject
 {
@@ -148,19 +150,6 @@ public slots:
 protected:
     void setIgnoreList(const QList<IgnoreListItem> &ignoreList) { _ignoreList = ignoreList; }
 
 protected:
     void setIgnoreList(const QList<IgnoreListItem> &ignoreList) { _ignoreList = ignoreList; }
 
-    //! Check if a scope rule matches a string
-    /** Checks that the string does NOT match ANY inverted rules (prefixed by '!'), then checks that
-     * it matches AT LEAST one normal (non-inverted) rule.
-     *
-     * If only inverted rules are specified, it'll match so long as the string does not match any
-     * inverted rules (implicit wildcard).
-     *
-     * \param scopeRule  A ';'-separated list of wildcard expressions, prefix of '!' inverts subrule
-     * \param string     String to test, e.g. network/channel name
-     * \return True if matches, otherwise false
-     */
-    bool scopeMatch(const QString &scopeRule, const QString &string) const;
-
     StrictnessType _match(const QString &msgContents, const QString &msgSender, Message::Type msgType, const QString &network, const QString &bufferName);
 
 signals:
     StrictnessType _match(const QString &msgContents, const QString &msgSender, Message::Type msgType, const QString &network, const QString &bufferName);
 
 signals:
index e3c1159..da3ea10 100644 (file)
@@ -280,3 +280,59 @@ QString formatCurrentDateTimeInString(const QString &formatStr)
 
     return formattedStr;
 }
 
     return formattedStr;
 }
+
+
+bool scopeMatch(const QString &scopeRule, const QString &string)
+{
+    // A match happens when the string does NOT match ANY inverted rules and matches AT LEAST one
+    // normal rule, unless no normal rules exist (implicit wildcard match).  This gives inverted
+    // rules higher priority regardless of ordering.
+    //
+    // TODO: After switching to Qt 5, use of this should be split into two parts, one part that
+    // would generate compiled QRegularExpressions for match/inverted match, regenerating it on any
+    // rule changes, and another part that would check each message against these compiled rules.
+
+    // Keep track if any matches are found
+    bool matches = false;
+    // Keep track if normal rules and inverted rules are found, allowing for implicit wildcard
+    bool normalRuleFound = false, invertedRuleFound = false;
+
+    // Split each scope rule by separator, ignoring empty parts
+    foreach(QString rule, scopeRule.split(";", QString::SkipEmptyParts)) {
+        // Trim whitespace from the start/end of the rule
+        rule = rule.trimmed();
+        // Ignore empty rules
+        if (rule.isEmpty())
+            continue;
+
+        // Check if this is an inverted rule (starts with '!')
+        if (rule.startsWith("!")) {
+            // Inverted rule found
+            invertedRuleFound = true;
+
+            // Take the reminder of the string
+            QRegExp ruleRx(rule.mid(1), Qt::CaseInsensitive);
+            ruleRx.setPatternSyntax(QRegExp::Wildcard);
+            if (ruleRx.exactMatch(string)) {
+                // Matches an inverted rule, full rule cannot match
+                return false;
+            }
+        } else {
+            // Normal rule found
+            normalRuleFound = true;
+
+            QRegExp ruleRx(rule, Qt::CaseInsensitive);
+            ruleRx.setPatternSyntax(QRegExp::Wildcard);
+            if (ruleRx.exactMatch(string)) {
+                // Matches a normal rule, full rule might match
+                matches = true;
+                // Continue checking in case other inverted rules negate this
+            }
+        }
+    }
+    // No inverted rules matched, okay to match normally
+    // Return true if...
+    // ...we found a normal match
+    // ...implicit wildcard: we had inverted rules (that didn't match) and no normal rules
+    return matches || (invertedRuleFound && !normalRuleFound);
+}
index 632ba0e..85d7910 100644 (file)
@@ -79,3 +79,17 @@ QByteArray prettyDigest(const QByteArray &digest);
  * @return String with current date/time substituted in via formatting codes
  */
 QString formatCurrentDateTimeInString(const QString &formatStr);
  * @return String with current date/time substituted in via formatting codes
  */
 QString formatCurrentDateTimeInString(const QString &formatStr);
+
+/** Check if a scope rule matches a string
+ *
+ * Checks that the string does NOT match ANY inverted rules (prefixed by '!'), then checks that
+ * it matches AT LEAST one normal (non-inverted) rule.
+ *
+ * If only inverted rules are specified, it'll match so long as the string does not match any
+ * inverted rules (implicit wildcard).
+ *
+ * @param scopeRule  A ';'-separated list of wildcard expressions, prefix of '!' inverts subrule
+ * @param string     String to test, e.g. network/channel name
+ * @return True if matches, otherwise false
+ */
+bool scopeMatch(const QString &scopeRule, const QString &string);
index 94f43e3..76415cc 100644 (file)
@@ -141,17 +141,11 @@ void QtUiMessageProcessor::checkForHighlight(Message &msg)
             if (!rule.isEnabled)
                 continue;
 
             if (!rule.isEnabled)
                 continue;
 
-            if (rule.chanName.size() > 0 && rule.chanName.compare(".*") != 0) {
-                if (rule.chanName.startsWith("!")) {
-                    QRegExp rx(rule.chanName.mid(1), Qt::CaseInsensitive);
-                    if (rx.exactMatch(msg.bufferInfo().bufferName()))
-                        continue;
-                }
-                else {
-                    QRegExp rx(rule.chanName, Qt::CaseInsensitive);
-                    if (!rx.exactMatch(msg.bufferInfo().bufferName()))
-                        continue;
-                }
+            if (!rule.chanName.isEmpty()
+                    && !scopeMatch(rule.chanName, msg.bufferInfo().bufferName())) {
+                // A channel name rule is specified and does NOT match the current buffer name, skip
+                // this rule
+                continue;
             }
 
             QRegExp rx;
             }
 
             QRegExp rx;