|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2013 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the PyQt5 server part of the QRegularExpression wizzard. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals # __IGNORE_WARNING__ |
|
11 |
|
12 import json |
|
13 import sys |
|
14 |
|
15 |
|
16 def rxValidate(regexp, options): |
|
17 """ |
|
18 Function to validate the given regular expression. |
|
19 |
|
20 @param regexp regular expression to validate (string) |
|
21 @param options list of options (list of string) |
|
22 @return tuple of flag indicating validity (boolean), error |
|
23 string (string) and error offset (integer) |
|
24 """ |
|
25 try: |
|
26 from PyQt5.QtCore import QRegularExpression |
|
27 rxOptions = QRegularExpression.NoPatternOption |
|
28 if "CaseInsensitiveOption" in options: |
|
29 rxOptions |= QRegularExpression.CaseInsensitiveOption |
|
30 if "MultilineOption" in options: |
|
31 rxOptions |= QRegularExpression.MultilineOption |
|
32 if "DotMatchesEverythingOption" in options: |
|
33 rxOptions |= QRegularExpression.DotMatchesEverythingOption |
|
34 if "ExtendedPatternSyntaxOption" in options: |
|
35 rxOptions |= QRegularExpression.ExtendedPatternSyntaxOption |
|
36 if "InvertedGreedinessOption" in options: |
|
37 rxOptions |= QRegularExpression.InvertedGreedinessOption |
|
38 if "UseUnicodePropertiesOption" in options: |
|
39 rxOptions |= QRegularExpression.UseUnicodePropertiesOption |
|
40 if "DontCaptureOption" in options: |
|
41 rxOptions |= QRegularExpression.DontCaptureOption |
|
42 |
|
43 error = "" |
|
44 errorOffset = -1 |
|
45 re = QRegularExpression(regexp, rxOptions) |
|
46 valid = re.isValid() |
|
47 if not valid: |
|
48 error = re.errorString() |
|
49 errorOffset = re.patternErrorOffset() |
|
50 except ImportError: |
|
51 valid = False |
|
52 error = "ImportError" |
|
53 errorOffset = 0 |
|
54 |
|
55 return valid, error, errorOffset |
|
56 |
|
57 |
|
58 def rxExecute(regexp, options, text, startpos): |
|
59 """ |
|
60 Function to execute the given regular expression for a given text. |
|
61 |
|
62 @param regexp regular expression to validate (string) |
|
63 @param options list of options (list of string) |
|
64 @param text text to execute on (string) |
|
65 @param startpos start position for the execution (integer) |
|
66 @return tuple of a flag indicating a successful match (boolean) and |
|
67 a list of captures containing the complete match as matched string |
|
68 (string), match start (integer), match end (integer) and match length |
|
69 (integer) for each entry |
|
70 """ |
|
71 valid, error, errorOffset = rxValidate(regexp, options) |
|
72 if not valid: |
|
73 return valid, error, errorOffset |
|
74 |
|
75 from PyQt5.QtCore import QRegularExpression |
|
76 rxOptions = QRegularExpression.NoPatternOption |
|
77 if "CaseInsensitiveOption" in options: |
|
78 rxOptions |= QRegularExpression.CaseInsensitiveOption |
|
79 if "MultilineOption" in options: |
|
80 rxOptions |= QRegularExpression.MultilineOption |
|
81 if "DotMatchesEverythingOption" in options: |
|
82 rxOptions |= QRegularExpression.DotMatchesEverythingOption |
|
83 if "ExtendedPatternSyntaxOption" in options: |
|
84 rxOptions |= QRegularExpression.ExtendedPatternSyntaxOption |
|
85 if "InvertedGreedinessOption" in options: |
|
86 rxOptions |= QRegularExpression.InvertedGreedinessOption |
|
87 if "UseUnicodePropertiesOption" in options: |
|
88 rxOptions |= QRegularExpression.UseUnicodePropertiesOption |
|
89 if "DontCaptureOption" in options: |
|
90 rxOptions |= QRegularExpression.DontCaptureOption |
|
91 |
|
92 matched = False |
|
93 captures = [] |
|
94 re = QRegularExpression(regexp, rxOptions) |
|
95 match = re.match(text, startpos) |
|
96 if match.hasMatch(): |
|
97 matched = True |
|
98 for index in range(match.lastCapturedIndex() + 1): |
|
99 captures.append([ |
|
100 match.captured(index), |
|
101 match.capturedStart(index), |
|
102 match.capturedEnd(index), |
|
103 match.capturedLength(index) |
|
104 ]) |
|
105 |
|
106 return matched, captures |
|
107 |
|
108 |
|
109 def main(): |
|
110 """ |
|
111 Function containing the main routine. |
|
112 """ |
|
113 while True: |
|
114 commandStr = sys.stdin.readline() |
|
115 try: |
|
116 commandDict = json.loads(commandStr) |
|
117 responseDict = {"error": ""} |
|
118 if "command" in commandDict: |
|
119 command = commandDict["command"] |
|
120 if command == "exit": |
|
121 break |
|
122 elif command == "available": |
|
123 try: |
|
124 import PyQt5 # __IGNORE_WARNING__ |
|
125 responseDict["available"] = True |
|
126 except ImportError: |
|
127 responseDict["available"] = False |
|
128 elif command == "validate": |
|
129 valid, error, errorOffset = rxValidate(commandDict["regexp"], |
|
130 commandDict["options"]) |
|
131 responseDict["valid"] = valid |
|
132 responseDict["errorMessage"] = error |
|
133 responseDict["errorOffset"] = errorOffset |
|
134 elif command == "execute": |
|
135 valid, error, errorOffset = rxValidate(commandDict["regexp"], |
|
136 commandDict["options"]) |
|
137 if not valid: |
|
138 responseDict["valid"] = valid |
|
139 responseDict["errorMessage"] = error |
|
140 responseDict["errorOffset"] = errorOffset |
|
141 else: |
|
142 matched, captures = rxExecute(commandDict["regexp"], |
|
143 commandDict["options"], commandDict["text"], |
|
144 commandDict["startpos"]) |
|
145 responseDict["matched"] = matched |
|
146 responseDict["captures"] = captures |
|
147 except ValueError as err: |
|
148 responseDict = {"error": str(err)} |
|
149 except Exception as err: |
|
150 responseDict = {"error": str(err)} |
|
151 responseStr = json.dumps(responseDict) |
|
152 sys.stdout.write(responseStr) |
|
153 sys.stdout.flush() |
|
154 |
|
155 sys.exit(0) |
|
156 |
|
157 |
|
158 if __name__ == "__main__": |
|
159 main() |