--- a/PluginSplitMergeCamelCase.py Fri May 28 19:09:47 2021 +0200 +++ b/PluginSplitMergeCamelCase.py Fri May 28 19:37:46 2021 +0200 @@ -11,25 +11,26 @@ import os import re -from PyQt5.QtCore import QObject, QTranslator -from PyQt5.QtWidgets import QMenu +from PyQt6.QtCore import QObject, QTranslator +from PyQt6.QtWidgets import QMenu -from E5Gui.E5Application import e5App +from EricWidgets.EricApplication import ericApp # Start-Of-Header name = "Camel Case Handling Plug-in" author = "Detlev Offenbach <detlev@die-offenbachs.de>" autoactivate = True deactivateable = True -version = "3.1.0" +version = "1.0.0" className = "SplitMergeCamelCasePlugin" packageName = "SplitMergeCamelCase" -shortDescription = "Split, merge or convert camel case text" +shortDescription = "Split, merge or convert camel/snake case text" longDescription = ( - """This plug-in implements a tool to split, merge or convert""" - """ camel case text. It works with the text of the current""" - """ editor. The menu entries will only be selectable, if the""" - """ current editor has some selected text.""" + """This plug-in implements a tool to split or merge camel case """ + """or snake case text. It also offers the capability to convert""" + """ text between these case variants. It works with the text of""" + """ the current editor. The menu entries will only be enabled,""" + """ if the current editor has some selected text.""" ) needsRestart = False pyqtApi = 2 @@ -46,7 +47,8 @@ """ Constructor - @param ui reference to the user interface object (UI.UserInterface) + @param ui reference to the user interface object + @type UserInterface """ super().__init__(ui) self.__ui = ui @@ -63,7 +65,8 @@ """ Public method to activate this plugin. - @return tuple of None and activation status (boolean) + @return tuple of None and activation status + @rtype tuple of (None, bool) """ global error error = "" # clear previous error @@ -78,12 +81,12 @@ act = menu.addMenu(self.__menu) self.__mainActions.append(act) - e5App().getObject("ViewManager").editorOpenedEd.connect( + ericApp().getObject("ViewManager").editorOpenedEd.connect( self.__editorOpened) - e5App().getObject("ViewManager").editorClosedEd.connect( + ericApp().getObject("ViewManager").editorClosedEd.connect( self.__editorClosed) - for editor in e5App().getObject("ViewManager").getOpenEditors(): + for editor in ericApp().getObject("ViewManager").getOpenEditors(): self.__editorOpened(editor) return None, True @@ -100,9 +103,9 @@ menu.removeAction(act) self.__mainActions = [] - e5App().getObject("ViewManager").editorOpenedEd.disconnect( + ericApp().getObject("ViewManager").editorOpenedEd.disconnect( self.__editorOpened) - e5App().getObject("ViewManager").editorClosedEd.disconnect( + ericApp().getObject("ViewManager").editorClosedEd.disconnect( self.__editorClosed) for editor, acts in self.__editors.items(): @@ -127,7 +130,7 @@ loaded = translator.load(translation, locale_dir) if loaded: self.__translator = translator - e5App().installTranslator(self.__translator) + ericApp().installTranslator(self.__translator) else: print("Warning: translation file '{0}' could not be" " loaded.".format(translation)) @@ -137,30 +140,47 @@ """ Private method to initialize the camel case handling menu. """ - self.__menu = QMenu(self.tr("CamelCase Handling")) - self.__menu.addAction(self.tr("Split from CamelCase"), - self.__splitCamelCase) - self.__menu.addAction(self.tr("Merge to CamelCase"), - self.__mergeCamelCase) - self.__menu.addAction(self.tr("CamelCase to under_score"), - self.__camelCaseToUnderscore) - self.__menu.addAction(self.tr("under_score to CamelCase"), - self.__underscoreToCamelCase) + self.__menu = QMenu(self.tr("Camel/Snake Case Handling")) + self.__menu.addAction( + self.tr("Split from Camel Case"), + self.__splitCamelCase) + self.__menu.addAction( + self.tr("Merge to Camel Case"), + self.__mergeCamelCase) + self.__menu.addAction( + self.tr("Merge to Camel Case (upper case first)"), + self.__mergeCamelCaseUppercaseFirst) + self.__menu.addSeparator() self.__menu.addAction( - self.tr("under_score to CamelCase (upper case first)"), - self.__underscoreToCamelCaseUppercaseFirst) + self.tr("Split from Snake Case"), + self.__splitSnakeCase) + self.__menu.addAction( + self.tr("Merge to Snake Case"), + self.__mergeSnakeCase) + self.__menu.addSeparator() + self.__menu.addAction( + self.tr("Camel Case to Snake Case"), + self.__camelCaseToSnakeCase) + self.__menu.addAction( + self.tr("Snake Case to Camel Case"), + self.__snakeCaseToCamelCase) + self.__menu.addAction( + self.tr("Snake Case to Camel Case (upper case first)"), + self.__snakeCaseToCamelCaseUppercaseFirst) def __populateMenu(self, name, menu): """ Private slot to populate the tools menu with our entries. - @param name name of the menu (string) - @param menu reference to the menu to be populated (QMenu) + @param name name of the menu + @type str + @param menu reference to the menu to be populated + @type QMenu """ if name not in ["Tools", "PluginTools"]: return - editor = e5App().getObject("ViewManager").activeWindow() + editor = ericApp().getObject("ViewManager").activeWindow() if name == "Tools": if not menu.isEmpty(): @@ -175,7 +195,8 @@ """ Private slot called, when a new editor was opened. - @param editor reference to the new editor (QScintilla.Editor) + @param editor reference to the new editor + @type Editor """ menu = editor.getMenu("Tools") if menu is not None: @@ -191,7 +212,8 @@ """ Private slot called, when an editor was closed. - @param editor reference to the editor (QScintilla.Editor) + @param editor reference to the editor + @type Editor """ with contextlib.suppress(KeyError): del self.__editors[editor] @@ -201,9 +223,12 @@ Private slot called, when the the editor context menu or a submenu is about to be shown. - @param menuName name of the menu to be shown (string) - @param menu reference to the menu (QMenu) + @param menuName name of the menu to be shown + @type str + @param menu reference to the menu + @type QMenu @param editor reference to the editor + @type Editor """ if menuName == "Tools": if self.__menu.menuAction() not in menu.actions(): @@ -221,9 +246,11 @@ """ Private method to change the selected text. - @param newText new (converted) text (string) + @param newText new (converted) text + @type str @param editor reference to the editor to apply the text - change to (Editor) + change to + @type Editor """ editor.beginUndoAction() editor.replaceSelectedText(newText) @@ -233,73 +260,119 @@ """ Private slot to split the selected camel case text. """ - editor = e5App().getObject("ViewManager").activeWindow() + editor = ericApp().getObject("ViewManager").activeWindow() if editor is None: return text = editor.selectedText() if text: - newText = re.sub(r"([A-Z])", r" \1", text) - if newText.startswith(" "): - newText = newText[1:] + newText = re.sub(r"([A-Z])", r" \1", text).lstrip(" ") if newText != text: self.__applyChange(newText, editor) - def __mergeCamelCase(self): + def __mergeCamelCase(self, uppercaseFirst=False): """ Private slot to merge the selected text to camel case. + + @param uppercaseFirst flag indicating to upper case the + first character + @type bool """ - editor = e5App().getObject("ViewManager").activeWindow() + editor = ericApp().getObject("ViewManager").activeWindow() + if editor is None: + return + + text = editor.selectedText() + if text: + newText = "".join(w[0].upper() + w[1:] for w in text.split()) + if not uppercaseFirst: + newText = newText[0].lower() + newText[1:] + if newText != text: + self.__applyChange(newText, editor) + + def __mergeCamelCaseUppercaseFirst(self): + """ + Private slot to merge the selected text to camel case upper casing + the first character. + """ + self.__mergeCamelCase(True) + + def __splitSnakeCase(self): + """ + Private slot to split the selected snake case text. + """ + editor = ericApp().getObject("ViewManager").activeWindow() if editor is None: return text = editor.selectedText() if text: - newText = "".join(text.split()) + newText = text.replace("_", " ").lstrip(" ") if newText != text: self.__applyChange(newText, editor) - def __camelCaseToUnderscore(self): + def __mergeSnakeCase(self): + """ + Private slot to merge the selected text to snake case. + """ + editor = ericApp().getObject("ViewManager").activeWindow() + if editor is None: + return + + text = editor.selectedText() + if text: + newText = "_".join(w.lower() for w in text.split()) + if newText != text: + self.__applyChange(newText, editor) + + def __camelCaseToSnakeCase(self): """ Private slot to convert camel case text to underscore separated text. """ - editor = e5App().getObject("ViewManager").activeWindow() + editor = ericApp().getObject("ViewManager").activeWindow() if editor is None: return text = editor.selectedText() if text: - newText = re.sub(r"([A-Z])", r"_\1", text).lower() - if newText.startswith("_"): - newText = newText[1:] + newText = re.sub(r"([A-Z])", r"_\1", text).lower().lstrip("_") + if text.startswith("__"): + newText = "__" + newText + elif text.startswith("_"): + newText = "_" + newText if newText != text: self.__applyChange(newText, editor) - def __underscoreToCamelCase(self, uppercaseFirst=False): + def __snakeCaseToCamelCase(self, uppercaseFirst=False): """ Private slot to convert underscore separated text to camel case. @param uppercaseFirst flag indicating to upper case the - first character (boolean) + first character + @type bool """ - editor = e5App().getObject("ViewManager").activeWindow() + editor = ericApp().getObject("ViewManager").activeWindow() if editor is None: return text = editor.selectedText() if text: - newText = "".join([s.capitalize() for s in text.split("_")]) + newText = "".join(s.capitalize() for s in text.split("_")) if not uppercaseFirst: newText = newText[0].lower() + newText[1:] + if text.startswith("__"): + newText = "__" + newText + elif text.startswith("_"): + newText = "_" + newText if newText != text: self.__applyChange(newText, editor) - def __underscoreToCamelCaseUppercaseFirst(self): + def __snakeCaseToCamelCaseUppercaseFirst(self): """ Private slot to convert underscore separated text to camel case upper casing the first character. """ - self.__underscoreToCamelCase(True) + self.__snakeCaseToCamelCase(True) # # eflag: noqa = M801