diff --git a/dataobjs.py b/dataobjs.py index 4c0d1ad..5306ad8 100644 --- a/dataobjs.py +++ b/dataobjs.py @@ -45,32 +45,8 @@ class pesterQuirk(object): self.checkstate = self.quirk["checkstate"] except KeyError: pass - def apply(self, string, first=False, last=False, checkstate=0): - # This function applies the quirks :3 - print("checkstate: " + str(checkstate)) - - # Try to get a list of breakable links, smilies, - # @handle, #memo, in the message. - try: - # Check for links, store list of links. - links = list() - for match in re.findall(_urlre, string): - links.append(match) - # Check for smilies, store list of smilies. - smilies = list() - for match in re.findall(_smilere, string): - smilies.append(match) - # Check for @handles, store list of @handles. - handles = list() - for match in re.findall(_handlere, string): - smilies.append(match) - # Check for #memos, store list of #memos. - memos = list() - for match in re.findall(_memore, string): - smilies.append(match) - except Exception as e: - PchumLog.warning("Quirk issue: " + str(e)) + def apply(self, string, first=False, last=False): if not self.on: return string elif self.type == "prefix": @@ -78,25 +54,7 @@ class pesterQuirk(object): elif self.type == "suffix": return string + self.quirk["value"] elif self.type == "replace": - try: - # Replace like normal - output = string.replace(self.quirk["from"], self.quirk["to"]) - # Try to revert links based on list. - for link in links: - output = output.replace(link.replace(self.quirk["from"], self.quirk["to"]), link) - # Try to revert smilies based on list. - for smiley in smilies: - output = output.replace(smiley.replace(self.quirk["from"], self.quirk["to"]), smiley) - # Try to revert @handles based on list. - for handle in handles: - output = output.replace(handle.replace(self.quirk["from"], self.quirk["to"]), handle) - # Try to revert #memos based on list. - for memo in memos: - output = output.replace(memo.replace(self.quirk["from"], self.quirk["to"]), memo) - return output - except Exception as e: - PchumLog.warning("Replace issue: " + str(e)) - return string.replace(self.quirk["from"], self.quirk["to"]) + return string.replace(self.quirk["from"], self.quirk["to"]) elif self.type == "regexp": fr = self.quirk["from"] if not first and len(fr) > 0 and fr[0] == "^": @@ -105,21 +63,11 @@ class pesterQuirk(object): return string to = self.quirk["to"] pt = parseRegexpFunctions(to) - output = re.sub(fr, pt.expand, string) - # Reverse sub for links/smilies if enabled. - if checkstate == 2: - for smiley in smilies: - output = output.replace(re.sub(fr, pt.expand, smiley), smiley) - for link in links: - output = output.replace(re.sub(fr, pt.expand, link), link) - for handle in handles: - output = output.replace(re.sub(fr, pt.expand, handle), handle) - for memo in memos: - output = output.replace(re.sub(fr, pt.expand, memo), memo) - return output + return re.sub(fr, pt.expand, string) elif self.type == "random": if len(self.quirk["randomlist"]) == 0: return string + fr = self.quirk["from"] if not first and len(fr) > 0 and fr[0] == "^": return string if not last and len(fr) > 0 and fr[len(fr)-1] == "$": @@ -128,69 +76,29 @@ class pesterQuirk(object): choice = random.choice(self.quirk["randomlist"]) pt = parseRegexpFunctions(choice) return pt.expand(mo) - return self.quirk["from"] + return re.sub(self.quirk["from"], randomrep, string) elif self.type == "spelling": percentage = self.quirk["percentage"]/100.0 words = string.split(" ") newl = [] - p = random.random() - - # Main /word loop + ctag = re.compile("()", re.I) for w in words: - if re.match(_urlre, w): - # Word is an url, don't break. - newl.append(w) - elif re.match(_memore, w): - # Word is an @memo, don't break. - newl.append(w) - elif re.match(_handlere, w): - # Word is an @handle, don't break. - newl.append(w) - elif re.match(_smilere, w): - # Word contains a smiley - # Split by ':' and only skip the smiley, - # this part is very messy and optional really. - stripped_smiles = list() - for smiley in smilies: - stripped_smiles.append(smiley.strip(':')) - denominated = w.split(':') - output = '' - for part in range(0, len(denominated)): - if denominated[part] in stripped_smiles: - output += denominated[part] + p = random.random() + if not ctag.search(w) and p < percentage: + newl.append(mispeller(w)) + elif p < percentage: + split = ctag.split(w) + tmp = [] + for s in split: + if s and not ctag.search(s): + tmp.append(mispeller(s)) else: - if not _ctagre.search(denominated[part]) and p < percentage: - output += mispeller(denominated[part]) - elif p < percentage: - split = _ctagre.split(denominated[part]) - tmp = [] - for s in split: - if s and not _ctagre.search(s): - tmp.append(mispeller(s)) - else: - tmp.append(s) - output += tmp - else: - output += denominated[part] - if part != len(denominated)-1: - output += ':' - newl.append(output) + tmp.append(s) + newl.append("".join(tmp)) else: - if not _ctagre.search(w) and p < percentage: - newl.append(mispeller(w)) - elif p < percentage: - split = _ctagre.split(w) - tmp = [] - for s in split: - if s and not _ctagre.search(s): - tmp.append(mispeller(s)) - else: - tmp.append(s) - newl.append("".join(tmp)) - else: - newl.append(w) + newl.append(w) return " ".join(newl) - + def __str__(self): if self.type == "prefix": return "BEGIN WITH: %s" % (self.quirk["value"]) @@ -238,20 +146,76 @@ class pesterQuirks(object): checkstate = int(q.checkstate) except Exception: checkstate = 0 - if q.type != 'prefix' and q.type != 'suffix': - if q.type == 'regexp' or q.type == 'random': - string = q.apply(string, - first=(i==0), - last=lastStr, - checkstate=checkstate) - else: + # Check for substring that should be excluded. + excludes = list() + # Check for links, store in list. + for match in re.finditer(_urlre, string): + excludes.append(match) + # Check for smilies, store in list. + for match in re.finditer(_smilere, string): + excludes.append(match) + # Check for @handles, store in list. + for match in re.finditer(_handlere, string): + excludes.append(match) + # Check for #memos, store in list. + for match in re.finditer(_memore, string): + excludes.append(match) + + # Checkstate == 0 means the exclude option is unchecked. + if (checkstate == 0) or (len(excludes) == 0): + # No split, apply like normal. + if q.type != 'prefix' and q.type != 'suffix': + if q.type == 'regexp' or q.type == 'random': + string = q.apply(string, + first=(i==0), + last=lastStr) + else: + string = q.apply(string) + elif q.type == 'prefix' and i == 0: string = q.apply(string) - elif q.type == 'prefix' and i == 0: - string = q.apply(string) - elif q.type == 'suffix' and lastStr: - string = q.apply(string) - newlist.append(string) + elif q.type == 'suffix' and lastStr: + string = q.apply(string) + # Exclude option is checked, split string and only quirk + # the parts without links/smilies/@handle/#memo + elif (checkstate == 2) and (len(excludes) >= 1): + # Seperate parts to be quirked. + sendparts = list() + # Add string until start of exclude at index 0. + until = excludes[0].start() + sendparts.append(string[:until]) + # Add strings between excludes. + for part in range(1, len(excludes)): + after = excludes[part-1].end() + until = excludes[part].start() + sendparts.append(string[after:until]) + # Add string after exclude at last index. + after = excludes[-1].end() + sendparts.append(string[after:]) + # Quirk to-be-quirked parts. + recvparts = list() + for part in sendparts: + # No split, apply like normal. + if q.type == 'regexp' or q.type == 'random': + recvparts.append(q.apply(part, + first=(i==0), + last=lastStr)) + elif q.type == 'prefix' and i == 0: + recvparts.append(q.apply(part)) + elif q.type == 'suffix' and lastStr: + recvparts.append(q.apply(part)) + else: + recvparts.append(q.apply(part)) + # Reconstruct and update string. + string = '' + #print("sendparts: " + str(sendparts)) + #print("recvparts: " + str(recvparts)) + for part in range(0, len(excludes)): + string += recvparts[part] + string += excludes[part].group() + string += recvparts[-1] + + newlist.append(string) final = [] for n in newlist: if type(n) in [str, str]: diff --git a/menus.py b/menus.py index 7d283e4..dc2ba9a 100644 --- a/menus.py +++ b/menus.py @@ -13,7 +13,6 @@ from convo import PesterInput, PesterText from parsetools import lexMessage QString = str - _datadir = ostools.getDataDir() class PesterQuirkItem(QtWidgets.QTreeWidgetItem): @@ -390,6 +389,12 @@ class PesterQuirkTypes(QtWidgets.QDialog): layout_3.addWidget(QtWidgets.QLabel("With:")) layout_3.addWidget(QtWidgets.QLineEdit()) layout_replace.addLayout(layout_3) + layout_3 = QtWidgets.QHBoxLayout() + excludeCheckbox = QtWidgets.QCheckBox("Exclude links and smilies") + excludeCheckbox.setToolTip("Splits input to exclude smilies, weblinks, @handles, and #memos." + + "\nThe replace is applied on every substring individually.") + layout_3.addWidget(excludeCheckbox) + layout_replace.addLayout(layout_3) # Regexp Replace widget = QtWidgets.QWidget() @@ -407,9 +412,10 @@ class PesterQuirkTypes(QtWidgets.QDialog): layout_3.addWidget(QtWidgets.QLineEdit()) layout_regexp.addLayout(layout_3) layout_3 = QtWidgets.QHBoxLayout() - excludeCheckbox = QtWidgets.QCheckBox("Fix links and smilies") - excludeCheckbox.setToolTip("Tries to revert changes to links, smilies, @handles, and #memos." - + "\nMay behave weirdly with more complex patterns and functions.") + excludeCheckbox = QtWidgets.QCheckBox("Exclude links and smilies") + excludeCheckbox.setToolTip("Splits input to exclude smilies, weblinks, @handles, and #memos." + + "\nSince the replace is applied on every substring individually," + + "\ncertain patterns or functions like gradients may not work correctly.") layout_3.addWidget(excludeCheckbox) layout_regexp.addLayout(layout_3) layout_all.addLayout(layout_f) @@ -449,13 +455,13 @@ class PesterQuirkTypes(QtWidgets.QDialog): layout_6.addWidget(self.replaceinput) layout_6.addLayout(layout_7) layout_random.addLayout(layout_6) - - #layout_9 = QtWidgets.QHBoxLayout() - #excludeCheckbox = QtWidgets.QCheckBox("Fix links and smilies") - #excludeCheckbox.setToolTip("Tries to revert changes to links, smilies, @handles, and #memos." - # + "\nMay behave weirdly with more complex patterns and functions.") - #layout_9.addWidget(excludeCheckbox) - #layout_random.addLayout(layout_9) + layout_9 = QtWidgets.QHBoxLayout() + excludeCheckbox = QtWidgets.QCheckBox("Exclude links and smilies") + excludeCheckbox.setToolTip("Splits input to exclude smilies, weblinks, @handles, and #memos." + + "\nSince the replace is applied on every substring individually," + + "\ncertain patterns or functions like gradients may not work correctly.") + layout_9.addWidget(excludeCheckbox) + layout_random.addLayout(layout_9) # Misspeller widget = QtWidgets.QWidget() @@ -483,6 +489,13 @@ class PesterQuirkTypes(QtWidgets.QDialog): layout_0.addWidget(self.pages) layout_0.addLayout(layout_2) + layout_3 = QtWidgets.QHBoxLayout() + excludeCheckbox = QtWidgets.QCheckBox("Exclude links and smilies") + excludeCheckbox.setToolTip("Splits input to exclude smilies, weblinks, @handles, and #memos." + + "\nThe replace is applied on every substring individually.") + layout_3.addWidget(excludeCheckbox) + layout_mispeller.addLayout(layout_3) + if quirk: types = ["prefix","suffix","replace","regexp","random","spelling"] for (i,r) in enumerate(self.radios): @@ -496,23 +509,31 @@ class PesterQuirkTypes(QtWidgets.QDialog): elif q["type"] == "replace": page.itemAt(1).layout().itemAt(1).widget().setText(q["from"]) page.itemAt(2).layout().itemAt(1).widget().setText(q["to"]) + try: + page.itemAt(3).layout().itemAt(0).widget().setCheckState(int(q["checkstate"])) + except (KeyError, ValueError) as e: + print("KeyError: %s" % str(e)) elif q["type"] == "regexp": page.itemAt(2).layout().itemAt(1).layout().itemAt(1).widget().setText(q["from"]) page.itemAt(2).layout().itemAt(2).layout().itemAt(1).widget().setText(q["to"]) try: page.itemAt(2).layout().itemAt(3).layout().itemAt(0).widget().setCheckState(int(q["checkstate"])) - except KeyError as e: + except (KeyError, ValueError) as e: print("KeyError: %s" % str(e)) elif q["type"] == "random": self.regexp.setText(q["from"]) for v in q["randomlist"]: item = QtWidgets.QListWidgetItem(v, self.replacelist) - #try: - # page.itemAt(2).layout().itemAt(2).layout().itemAt(0).widget().setCheckState(int(q["checkstate"])) - #except KeyError as e: - # print("KeyError: %s" % str(e)) + try: + page.itemAt(2).layout().itemAt(2).layout().itemAt(0).widget().setCheckState(int(q["checkstate"])) + except (KeyError, ValueError) as e: + print("KeyError: %s" % str(e)) elif q["type"] == "spelling": self.slider.setValue(q["percentage"]) + try: + page.itemAt(3).layout().itemAt(0).widget().setCheckState(int(q["checkstate"])) + except (KeyError, ValueError) as e: + print("KeyError: %s" % str(e)) self.setLayout(layout_0) @@ -693,19 +714,20 @@ class PesterChooseQuirks(QtWidgets.QDialog): elif vdict["type"] == "replace": vdict["from"] = str(page.itemAt(1).layout().itemAt(1).widget().text()) vdict["to"] = str(page.itemAt(2).layout().itemAt(1).widget().text()) + vdict["checkstate"] = str(page.itemAt(3).layout().itemAt(0).widget().checkState()) elif vdict["type"] == "regexp": vdict["from"] = str(page.itemAt(2).layout().itemAt(1).layout().itemAt(1).widget().text()) vdict["to"] = str(page.itemAt(2).layout().itemAt(2).layout().itemAt(1).widget().text()) vdict["checkstate"] = str(page.itemAt(2).layout().itemAt(3).layout().itemAt(0).widget().checkState()) elif vdict["type"] == "random": vdict["from"] = str(self.quirkadd.regexp.text()) - #vdict["checkstate"] = str(page.itemAt(2).layout().itemAt(2).layout().itemAt(0).widget().checkState()) + vdict["checkstate"] = str(page.itemAt(2).layout().itemAt(2).layout().itemAt(0).widget().checkState()) randomlist = [str(self.quirkadd.replacelist.item(i).text()) for i in range(0,self.quirkadd.replacelist.count())] vdict["randomlist"] = randomlist elif vdict["type"] == "spelling": vdict["percentage"] = self.quirkadd.slider.value() - + vdict["checkstate"] = str(page.itemAt(3).layout().itemAt(0).widget().checkState()) if vdict["type"] in ("regexp", "random"): try: re.compile(vdict["from"])