Completed the coding stuff of the QRegularExpression support.

Fri, 28 Jun 2013 19:39:08 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Fri, 28 Jun 2013 19:39:08 +0200
changeset 2748
3731148a7cdf
parent 2747
68b920f307ff
child 2749
00de40c5ee85

Completed the coding stuff of the QRegularExpression support.

Plugins/WizardPlugins/QRegularExpressionWizard/QRegularExpressionWizardDialog.py file | annotate | diff | comparison | revisions
Plugins/WizardPlugins/QRegularExpressionWizard/QRegularExpressionWizardServer.py file | annotate | diff | comparison | revisions
--- a/Plugins/WizardPlugins/QRegularExpressionWizard/QRegularExpressionWizardDialog.py	Thu Jun 27 19:51:57 2013 +0200
+++ b/Plugins/WizardPlugins/QRegularExpressionWizard/QRegularExpressionWizardDialog.py	Fri Jun 28 19:39:08 2013 +0200
@@ -101,19 +101,18 @@
             self.nextButton = None
         
         if fromEric:
-            self.buttonBox.button(QDialogButtonBox.Close).hide()
+            self.buttonBox.setStandardButtons(
+                QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
             self.copyButton = None
         else:
             self.copyButton = \
                 self.buttonBox.addButton(self.trUtf8("Copy"), QDialogButtonBox.ActionRole)
             self.copyButton.setToolTip(
                 self.trUtf8("Copy the regular expression to the clipboard"))
-            self.buttonBox.button(QDialogButtonBox.Ok).hide()
-            self.buttonBox.button(QDialogButtonBox.Cancel).hide()
+            self.buttonBox.setStandardButtons(QDialogButtonBox.Close)
             self.variableLabel.hide()
             self.variableLineEdit.hide()
             self.variableLine.hide()
-            self.importCheckBox.hide()
             self.regexpTextEdit.setFocus()
     
     def __sendCommand(self, command, **kw):
@@ -514,119 +513,129 @@
             # only available for Qt5
             return
         
-        regex = self.regexpTextEdit.toPlainText()
+        regexp = self.regexpTextEdit.toPlainText()
         text = self.textTextEdit.toPlainText()
-        if regex and text:
-            options = QRegularExpression.NoPatternOption
+        if regexp and text:
+            options = []
             if self.caseInsensitiveCheckBox.isChecked():
-                options |= QRegularExpression.CaseInsensitiveOption
+                options.append("CaseInsensitiveOption")
             if self.multilineCheckBox.isChecked():
-                options |= QRegularExpression.MultilineOption
+                options.append("MultilineOption")
             if self.dotallCheckBox.isChecked():
-                options |= QRegularExpression.DotMatchesEverythingOption
+                options.append("DotMatchesEverythingOption")
             if self.extendedCheckBox.isChecked():
-                options |= QRegularExpression.ExtendedPatternSyntaxOption
+                options.append("ExtendedPatternSyntaxOption")
             if self.greedinessCheckBox.isChecked():
-                options |= QRegularExpression.InvertedGreedinessOption
+                options.append("InvertedGreedinessOption")
             if self.unicodeCheckBox.isChecked():
-                options |= QRegularExpression.UseUnicodePropertiesOption
+                options.append("UseUnicodePropertiesOption")
             if self.captureCheckBox.isChecked():
-                options |= QRegularExpression.DontCaptureOption
-            
-            re = QRegularExpression(regex, options)
-            if not re.isValid():
-                E5MessageBox.critical(self,
-                    self.trUtf8("Error"),
-                    self.trUtf8("""Invalid regular expression: {0}""")
-                        .format(re.errorString()))
-                # move cursor to error offset
-                offset = re.errorPatternOffset()
-                tc = self.regexpTextEdit.textCursor()
-                tc.setPosition(offset)
-                self.regexpTextEdit.setTextCursor(tc)
-                return
-            
-            match = re.match(text, startpos)
-            if match.hasMatch():
-                captures = match.lastCapturedIndex()
-            else:
-                captures = 0
-            row = 0
-            OFFSET = 5
-            
-            self.resultTable.setColumnCount(0)
-            self.resultTable.setColumnCount(3)
-            self.resultTable.setRowCount(0)
-            self.resultTable.setRowCount(OFFSET)
-            self.resultTable.setItem(row, 0, QTableWidgetItem(self.trUtf8("Regexp")))
-            self.resultTable.setItem(row, 1, QTableWidgetItem(regex))
+                options.append("DontCaptureOption")
             
-            if match.hasMatch():
-                # index 0 is the complete match
-                offset = match.capturedStart(0)
-                self.lastMatchEnd = match.capturedEnd(0)
-                self.nextButton.setEnabled(True)
-                row += 1
-                self.resultTable.setItem(row, 0,
-                    QTableWidgetItem(self.trUtf8("Offset")))
-                self.resultTable.setItem(row, 1,
-                    QTableWidgetItem("{0:d}".format(match.capturedStart(0))))
-                
-                row += 1
-                self.resultTable.setItem(row, 0,
-                    QTableWidgetItem(self.trUtf8("Captures")))
-                self.resultTable.setItem(row, 1,
-                    QTableWidgetItem("{0:d}".format(captures)))
-                row += 1
-                self.resultTable.setItem(row, 1,
-                    QTableWidgetItem(self.trUtf8("Text")))
-                self.resultTable.setItem(row, 2,
-                    QTableWidgetItem(self.trUtf8("Characters")))
-                
-                row += 1
-                self.resultTable.setItem(row, 0,
-                    QTableWidgetItem(self.trUtf8("Match")))
-                self.resultTable.setItem(row, 1,
-                    QTableWidgetItem(match.captured(0)))
-                self.resultTable.setItem(row, 2,
-                    QTableWidgetItem("{0:d}".format(match.capturedLength(0))))
-                
-                for i in range(1, captures + 1):
-                    if match.captured(i):
-                        row += 1
-                        self.resultTable.insertRow(row)
-                        self.resultTable.setItem(row, 0,
-                            QTableWidgetItem(self.trUtf8("Capture #{0}").format(i)))
-                        self.resultTable.setItem(row, 1,
-                            QTableWidgetItem(match.captured(i)))
-                        self.resultTable.setItem(row, 2,
-                            QTableWidgetItem("{0:d}".format(match.capturedLength(i))))
-                
-                # highlight the matched text
-                tc = self.textTextEdit.textCursor()
-                tc.setPosition(offset)
-                tc.setPosition(self.lastMatchEnd, QTextCursor.KeepAnchor)
-                self.textTextEdit.setTextCursor(tc)
+            if self.__sendCommand("execute", options=options, regexp=regexp,
+                                  text=text, startpos=startpos):
+                response = self.__receiveResponse()
+                if response and ("valid" in response or "matched" in response):
+                    if "valid" in response:
+                        E5MessageBox.critical(self,
+                            self.trUtf8("Error"),
+                            self.trUtf8("""Invalid regular expression: {0}""")
+                                .format(response["errorMessage"]))
+                        # move cursor to error offset
+                        offset = response["errorOffset"]
+                        tc = self.regexpTextEdit.textCursor()
+                        tc.setPosition(offset)
+                        self.regexpTextEdit.setTextCursor(tc)
+                        self.regexpTextEdit.setFocus()
+                        return
+                    else:
+                        row = 0
+                        OFFSET = 5
+                        
+                        self.resultTable.setColumnCount(0)
+                        self.resultTable.setColumnCount(3)
+                        self.resultTable.setRowCount(0)
+                        self.resultTable.setRowCount(OFFSET)
+                        self.resultTable.setItem(
+                            row, 0, QTableWidgetItem(self.trUtf8("Regexp")))
+                        self.resultTable.setItem(
+                            row, 1, QTableWidgetItem(regexp))
+                        if response["matched"]:
+                            captures = response["captures"]
+                            # index 0 is the complete match
+                            offset = captures[0][1]
+                            self.lastMatchEnd = captures[0][2]
+                            self.nextButton.setEnabled(True)
+                            row += 1
+                            self.resultTable.setItem(row, 0,
+                                QTableWidgetItem(self.trUtf8("Offset")))
+                            self.resultTable.setItem(row, 1,
+                                QTableWidgetItem("{0:d}".format(offset)))
+                            
+                            row += 1
+                            self.resultTable.setItem(row, 0,
+                                QTableWidgetItem(self.trUtf8("Captures")))
+                            self.resultTable.setItem(row, 1,
+                                QTableWidgetItem("{0:d}".format(len(captures) - 1)))
+                            row += 1
+                            self.resultTable.setItem(row, 1,
+                                QTableWidgetItem(self.trUtf8("Text")))
+                            self.resultTable.setItem(row, 2,
+                                QTableWidgetItem(self.trUtf8("Characters")))
+                            
+                            row += 1
+                            self.resultTable.setItem(row, 0,
+                                QTableWidgetItem(self.trUtf8("Match")))
+                            self.resultTable.setItem(row, 1,
+                                QTableWidgetItem(captures[0][0]))
+                            self.resultTable.setItem(row, 2,
+                                QTableWidgetItem("{0:d}".format(captures[0][3])))
+                            
+                            for i in range(1, len(captures)):
+                                if captures[i][0]:
+                                    row += 1
+                                    self.resultTable.insertRow(row)
+                                    self.resultTable.setItem(row, 0,
+                                        QTableWidgetItem(
+                                            self.trUtf8("Capture #{0}").format(i)))
+                                    self.resultTable.setItem(row, 1,
+                                        QTableWidgetItem(captures[i][0]))
+                                    self.resultTable.setItem(row, 2,
+                                        QTableWidgetItem("{0:d}".format(captures[i][3])))
+                            
+                            # highlight the matched text
+                            tc = self.textTextEdit.textCursor()
+                            tc.setPosition(offset)
+                            tc.setPosition(self.lastMatchEnd, QTextCursor.KeepAnchor)
+                            self.textTextEdit.setTextCursor(tc)
+                        else:
+                            self.nextButton.setEnabled(False)
+                            self.resultTable.setRowCount(2)
+                            row += 1
+                            if startpos > 0:
+                                self.resultTable.setItem(row, 0,
+                                    QTableWidgetItem(self.trUtf8("No more matches")))
+                            else:
+                                self.resultTable.setItem(row, 0,
+                                    QTableWidgetItem(self.trUtf8("No matches")))
+                            
+                            # remove the highlight
+                            tc = self.textTextEdit.textCursor()
+                            tc.setPosition(0)
+                            self.textTextEdit.setTextCursor(tc)
+                        
+                        self.resultTable.resizeColumnsToContents()
+                        self.resultTable.resizeRowsToContents()
+                        self.resultTable.verticalHeader().hide()
+                        self.resultTable.horizontalHeader().hide()
+                else:
+                    E5MessageBox.critical(self,
+                        self.trUtf8("Communication Error"),
+                        self.trUtf8("""Invalid response received from PyQt5 backend."""))
             else:
-                self.nextButton.setEnabled(False)
-                self.resultTable.setRowCount(2)
-                row += 1
-                if startpos > 0:
-                    self.resultTable.setItem(row, 0,
-                        QTableWidgetItem(self.trUtf8("No more matches")))
-                else:
-                    self.resultTable.setItem(row, 0,
-                        QTableWidgetItem(self.trUtf8("No matches")))
-                
-                # remove the highlight
-                tc = self.textTextEdit.textCursor()
-                tc.setPosition(0)
-                self.textTextEdit.setTextCursor(tc)
-            
-            self.resultTable.resizeColumnsToContents()
-            self.resultTable.resizeRowsToContents()
-            self.resultTable.verticalHeader().hide()
-            self.resultTable.horizontalHeader().hide()
+                E5MessageBox.critical(self,
+                    self.trUtf8("Communication Error"),
+                    self.trUtf8("""Communication with PyQt5 backend failed."""))
         else:
             E5MessageBox.critical(self,
                 self.trUtf8("Error"),
--- a/Plugins/WizardPlugins/QRegularExpressionWizard/QRegularExpressionWizardServer.py	Thu Jun 27 19:51:57 2013 +0200
+++ b/Plugins/WizardPlugins/QRegularExpressionWizard/QRegularExpressionWizardServer.py	Fri Jun 28 19:39:08 2013 +0200
@@ -3,12 +3,13 @@
 # Copyright (c) 2013 Detlev Offenbach <detlev@die-offenbachs.de>
 #
 
+"""
+Module implementing the PyQt5 server part of the QRegularExpression wizzard.
+"""
+
 import json
 import sys
 
-def printerr(string):
-    sys.stderr.write(string)
-    sys.stderr.flush()
 
 def rxValidate(regexp, options):
     """
@@ -52,13 +53,66 @@
     return valid, error, errorOffset
 
 
-if __name__ == "__main__":
+def rxExecute(regexp, options, text, startpos):
+    """
+    Function to execute the given regular expression for a given text.
+    
+    @param regexp regular expression to validate (string)
+    @param options list of options (list of string)
+    @param text text to execute on (string)
+    @param startpos start position for the execution (integer)
+    @return tuple of a flag indicating a successful match (boolean) and
+        a list of captures containing the complete match as matched string
+        (string), match start (integer), match end (integer) and match length
+        (integer) for each entry
+    """
+    valid, error, errorOffset = rxValidate(regexp, options)
+    if not valid:
+        return valid, error, errorOffset
+    
+    from PyQt5.QtCore import QRegularExpression
+    rxOptions = QRegularExpression.NoPatternOption
+    if "CaseInsensitiveOption" in options:
+        rxOptions |= QRegularExpression.CaseInsensitiveOption
+    if "MultilineOption" in options:
+        rxOptions |= QRegularExpression.MultilineOption
+    if "DotMatchesEverythingOption" in options:
+        rxOptions |= QRegularExpression.DotMatchesEverythingOption
+    if "ExtendedPatternSyntaxOption" in options:
+        rxOptions |= QRegularExpression.ExtendedPatternSyntaxOption
+    if "InvertedGreedinessOption" in options:
+        rxOptions |= QRegularExpression.InvertedGreedinessOption
+    if "UseUnicodePropertiesOption" in options:
+        rxOptions |= QRegularExpression.UseUnicodePropertiesOption
+    if "DontCaptureOption" in options:
+        rxOptions |= QRegularExpression.DontCaptureOption
+    
+    matched = False
+    captures = []
+    re = QRegularExpression(regexp, rxOptions)
+    match = re.match(text, startpos)
+    if match.hasMatch():
+        matched = True
+        for index in range(match.lastCapturedIndex() + 1):
+            captures.append([
+                match.captured(index),
+                match.capturedStart(index),
+                match.capturedEnd(index),
+                match.capturedLength(index)
+            ])
+    
+    return matched, captures
+
+
+def main():
+    """
+    Function containing the main routine.
+    """
     while True:
         commandStr = sys.stdin.readline()
         try:
             commandDict = json.loads(commandStr)
             responseDict = {"error": ""}
-            printerr(str(commandDict))
             if "command" in commandDict:
                 command = commandDict["command"]
                 if command == "exit":
@@ -75,6 +129,19 @@
                     responseDict["valid"] = valid
                     responseDict["errorMessage"] = error
                     responseDict["errorOffset"] = errorOffset
+                elif command == "execute":
+                    valid, error, errorOffset = rxValidate(commandDict["regexp"],
+                                                           commandDict["options"])
+                    if not valid:
+                        responseDict["valid"] = valid
+                        responseDict["errorMessage"] = error
+                        responseDict["errorOffset"] = errorOffset
+                    else:
+                        matched, captures = rxExecute(commandDict["regexp"],
+                            commandDict["options"], commandDict["text"],
+                            commandDict["startpos"])
+                        responseDict["matched"] = matched
+                        responseDict["captures"] = captures
         except ValueError as err:
             responseDict = {"error": str(err)}
         except Exception as err:
@@ -84,3 +151,7 @@
         sys.stdout.flush()
     
     sys.exit(0)
+
+
+if __name__ == "__main__":
+    main()

eric ide

mercurial