--- a/src/eric7/QScintilla/Shell.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/QScintilla/Shell.py Wed Jul 13 14:55:47 2022 +0200 @@ -16,8 +16,14 @@ from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QEvent from PyQt6.QtGui import QClipboard, QPalette, QFont, QShortcut from PyQt6.QtWidgets import ( - QDialog, QInputDialog, QApplication, QMenu, QWidget, QHBoxLayout, - QVBoxLayout, QSizePolicy + QDialog, + QInputDialog, + QApplication, + QMenu, + QWidget, + QHBoxLayout, + QVBoxLayout, + QSizePolicy, ) from PyQt6.Qsci import QsciScintilla @@ -38,10 +44,11 @@ """ Class implementing the containing widget for the shell. """ + def __init__(self, dbs, vm, project, horizontal=True, parent=None): """ Constructor - + @param dbs reference to the debug server object @type DebugServer @param vm reference to the viewmanager object @@ -54,15 +61,17 @@ @type QWidget """ super().__init__(parent) - + self.__shell = Shell(dbs, vm, project, False, self) - + from UI.SearchWidget import SearchWidget + self.__searchWidget = SearchWidget(self.__shell, self, horizontal) - self.__searchWidget.setSizePolicy(QSizePolicy.Policy.Fixed, - QSizePolicy.Policy.Preferred) + self.__searchWidget.setSizePolicy( + QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Preferred + ) self.__searchWidget.hide() - + if horizontal: self.__layout = QHBoxLayout(self) else: @@ -70,24 +79,23 @@ self.__layout.setContentsMargins(1, 1, 1, 1) self.__layout.addWidget(self.__shell) self.__layout.addWidget(self.__searchWidget) - + self.__searchWidget.searchNext.connect(self.__shell.searchNext) self.__searchWidget.searchPrevious.connect(self.__shell.searchPrev) - self.__shell.searchStringFound.connect( - self.__searchWidget.searchStringFound) - + self.__shell.searchStringFound.connect(self.__searchWidget.searchStringFound) + def showFind(self, txt=""): """ Public method to display the search widget. - + @param txt text to be shown in the combo (string) """ self.__searchWidget.showFind(txt) - + def shell(self): """ Public method to get a reference to the shell widget. - + @return reference to the shell widget (Shell) """ return self.__shell @@ -97,6 +105,7 @@ """ Class defining the shell history styles. """ + DISABLED = 0 LINUXSTYLE = 1 WINDOWSSTYLE = 2 @@ -105,10 +114,10 @@ class Shell(QsciScintillaCompat): """ Class implementing a graphical Python shell. - + A user can enter commands that are executed in the remote Python interpreter. - + @signal searchStringFound(bool) emitted to indicate the search result @signal historyStyleChanged(ShellHistoryStyle) emitted to indicate a @@ -117,15 +126,16 @@ @signal virtualEnvironmentChanged(str) emitted to signal the new virtual environment of the shell """ + searchStringFound = pyqtSignal(bool) historyStyleChanged = pyqtSignal(ShellHistoryStyle) queueText = pyqtSignal(str) virtualEnvironmentChanged = pyqtSignal(str) - + def __init__(self, dbs, vm, project, windowedVariant, parent=None): """ Constructor - + @param dbs reference to the debug server object @type DebugServer @param vm reference to the viewmanager object @@ -139,90 +149,95 @@ """ super().__init__(parent) self.setUtf8(True) - + self.vm = vm self.__mainWindow = parent self.__lastSearch = () self.__windowed = windowedVariant self.__currentVenv = "" self.__currentWorkingDirectory = "" - + self.linesepRegExp = r"\r\n|\n|\r" - - self.passive = ((not self.__windowed) and - Preferences.getDebugger("PassiveDbgEnabled")) + + self.passive = (not self.__windowed) and Preferences.getDebugger( + "PassiveDbgEnabled" + ) if self.passive: - self.setWindowTitle(self.tr('Shell - Passive')) + self.setWindowTitle(self.tr("Shell - Passive")) else: - self.setWindowTitle(self.tr('Shell')) - + self.setWindowTitle(self.tr("Shell")) + if self.__windowed: - self.setWhatsThis(self.tr( - """<b>The Shell Window</b>""" - """<p>You can use the cursor keys while entering commands.""" - """ There is also a history of commands that can be recalled""" - """ using the up and down cursor keys while holding down the""" - """ Ctrl-key. This can be switched to just the up and down""" - """ cursor keys on the Shell page of the configuration""" - """ dialog. Pressing these keys after some text has been""" - """ entered will start an incremental search.</p>""" - """<p>The shell has some special commands. '%restart' kills""" - """ the shell and starts a new one. '%clear' clears the""" - """ display of the shell window. '%start' is used to start a""" - """ shell for a virtual environment and should be followed""" - """ by a virtual environment name. '%start' without a""" - """ virtual environment name starts the default shell.""" - """ Available virtual environments may be listed with the""" - """ '%envs' or '%environments' commands. The active virtual""" - """ environment can be questioned by the '%which' command.""" - """ '%quit' or '%exit' is used to exit the application.""" - """ These commands (except '%environments', '%envs' and""" - """ '%which') are available through the window menus as""" - """ well.</p>""" - """<p>Pressing the Tab key after some text has been entered""" - """ will show a list of possible completions. The relevant""" - """ entry may be selected from this list. If only one entry""" - """ is available, this will be inserted automatically.</p>""" - )) + self.setWhatsThis( + self.tr( + """<b>The Shell Window</b>""" + """<p>You can use the cursor keys while entering commands.""" + """ There is also a history of commands that can be recalled""" + """ using the up and down cursor keys while holding down the""" + """ Ctrl-key. This can be switched to just the up and down""" + """ cursor keys on the Shell page of the configuration""" + """ dialog. Pressing these keys after some text has been""" + """ entered will start an incremental search.</p>""" + """<p>The shell has some special commands. '%restart' kills""" + """ the shell and starts a new one. '%clear' clears the""" + """ display of the shell window. '%start' is used to start a""" + """ shell for a virtual environment and should be followed""" + """ by a virtual environment name. '%start' without a""" + """ virtual environment name starts the default shell.""" + """ Available virtual environments may be listed with the""" + """ '%envs' or '%environments' commands. The active virtual""" + """ environment can be questioned by the '%which' command.""" + """ '%quit' or '%exit' is used to exit the application.""" + """ These commands (except '%environments', '%envs' and""" + """ '%which') are available through the window menus as""" + """ well.</p>""" + """<p>Pressing the Tab key after some text has been entered""" + """ will show a list of possible completions. The relevant""" + """ entry may be selected from this list. If only one entry""" + """ is available, this will be inserted automatically.</p>""" + ) + ) else: - self.setWhatsThis(self.tr( - """<b>The Shell Window</b>""" - """<p>This is simply an interpreter running in a window. The""" - """ interpreter is the one that is used to run the program""" - """ being debugged. This means that you can execute any""" - """ command while the program being debugged is running.</p>""" - """<p>You can use the cursor keys while entering commands.""" - """ There is also a history of commands that can be recalled""" - """ using the up and down cursor keys while holding down the""" - """ Ctrl-key. This can be switched to just the up and down""" - """ cursor keys on the Shell page of the configuration""" - """ dialog. Pressing these keys after some text has been""" - """ entered will start an incremental search.</p>""" - """<p>The shell has some special commands. '%restart' kills""" - """ the shell and starts a new one. '%clear' clears the""" - """ display of the shell window. '%start' is used to start a""" - """ shell for a virtual environment and should be followed""" - """ by a virtual environment name. '%start' without a""" - """ virtual environment name starts the default shell.""" - """ Available virtual environments may be listed with the""" - """ '%envs' or '%environments' commands. The active virtual""" - """ environment can be questioned by the '%which' command.""" - """ These commands (except '%environments' and '%envs') are""" - """ available through the context menu as well.</p>""" - """<p>Pressing the Tab key after some text has been entered""" - """ will show a list of possible completions. The relevant""" - """ entry may be selected from this list. If only one entry""" - """ is available, this will be inserted automatically.</p>""" - """<p>In passive debugging mode the shell is only available""" - """ after the program to be debugged has connected to the""" - """ IDE until it has finished. This is indicated by a""" - """ different prompt and by an indication in the window""" - """ caption.</p>""" - )) - + self.setWhatsThis( + self.tr( + """<b>The Shell Window</b>""" + """<p>This is simply an interpreter running in a window. The""" + """ interpreter is the one that is used to run the program""" + """ being debugged. This means that you can execute any""" + """ command while the program being debugged is running.</p>""" + """<p>You can use the cursor keys while entering commands.""" + """ There is also a history of commands that can be recalled""" + """ using the up and down cursor keys while holding down the""" + """ Ctrl-key. This can be switched to just the up and down""" + """ cursor keys on the Shell page of the configuration""" + """ dialog. Pressing these keys after some text has been""" + """ entered will start an incremental search.</p>""" + """<p>The shell has some special commands. '%restart' kills""" + """ the shell and starts a new one. '%clear' clears the""" + """ display of the shell window. '%start' is used to start a""" + """ shell for a virtual environment and should be followed""" + """ by a virtual environment name. '%start' without a""" + """ virtual environment name starts the default shell.""" + """ Available virtual environments may be listed with the""" + """ '%envs' or '%environments' commands. The active virtual""" + """ environment can be questioned by the '%which' command.""" + """ These commands (except '%environments' and '%envs') are""" + """ available through the context menu as well.</p>""" + """<p>Pressing the Tab key after some text has been entered""" + """ will show a list of possible completions. The relevant""" + """ entry may be selected from this list. If only one entry""" + """ is available, this will be inserted automatically.</p>""" + """<p>In passive debugging mode the shell is only available""" + """ after the program to be debugged has connected to the""" + """ IDE until it has finished. This is indicated by a""" + """ different prompt and by an indication in the window""" + """ caption.</p>""" + ) + ) + self.userListActivated.connect(self.__completionListSelected) self.linesChanged.connect(self.__resizeLinenoMargin) - + if self.__windowed: self.__showStdOutErr = True else: @@ -242,10 +257,10 @@ dbs.clientSignal.connect(self.__clientSignal) dbs.mainClientExit.connect(self.__writePrompt) self.dbs = dbs - + # will register a method to get the debugger ID to work with self.__getSelectedDebuggerId = None - + # Make sure we have prompts. if self.passive: sys.ps1 = self.tr("Passive >>> ") @@ -258,7 +273,7 @@ sys.ps2 except AttributeError: sys.ps2 = "... " - + # Initialize instance variables. self.__initialise() self.prline = 0 @@ -266,9 +281,9 @@ self.inDragDrop = False self.lexer_ = None self.completionText = "" - - self.clientType = '' - + + self.clientType = "" + # Initialize history self.__historyLists = {} self.__maxHistoryEntries = Preferences.getShell("MaxHistoryEntries") @@ -279,116 +294,108 @@ # remove obsolete shell histories (Python and Ruby) for clientType in ["Python", "Ruby"]: Preferences.getSettings().remove("Shell/Histories/" + clientType) - + # clear QScintilla defined keyboard commands # we do our own handling through the view manager self.clearAlternateKeys() self.clearKeys() self.__actionsAdded = False - + if self.passive: self.__getBanner() - + if not self.__windowed: # Create a little language context menu - self.lmenu = QMenu(self.tr('Start')) + self.lmenu = QMenu(self.tr("Start")) self.lmenu.aboutToShow.connect(self.__showStartMenu) self.lmenu.triggered.connect(self.__startDebugClient) - + # Create the history context menu - self.hmenu = QMenu(self.tr('History')) - self.hmenu.addAction(self.tr('Select entry'), self.selectHistory) - self.hmenu.addAction(self.tr('Show'), self.showHistory) - self.hmenu.addAction(self.tr('Clear'), self.clearHistory) - + self.hmenu = QMenu(self.tr("History")) + self.hmenu.addAction(self.tr("Select entry"), self.selectHistory) + self.hmenu.addAction(self.tr("Show"), self.showHistory) + self.hmenu.addAction(self.tr("Clear"), self.clearHistory) + # Create a little context menu self.menu = QMenu(self) - self.menu.addAction(self.tr('Cut'), self.cut) - self.menu.addAction(self.tr('Copy'), self.copy) - self.menu.addAction(self.tr('Paste'), self.paste) + self.menu.addAction(self.tr("Cut"), self.cut) + self.menu.addAction(self.tr("Copy"), self.copy) + self.menu.addAction(self.tr("Paste"), self.paste) self.menu.addMenu(self.hmenu).setEnabled(self.isHistoryEnabled()) - + self.menu.addSeparator() - self.menu.addAction(self.tr('Find'), self.__find) + self.menu.addAction(self.tr("Find"), self.__find) self.menu.addSeparator() - self.menu.addAction(self.tr('Clear'), self.clear) - self.menu.addAction(self.tr('Restart'), self.doRestart) - self.menu.addAction( - self.tr('Restart and Clear'), self.doClearRestart) + self.menu.addAction(self.tr("Clear"), self.clear) + self.menu.addAction(self.tr("Restart"), self.doRestart) + self.menu.addAction(self.tr("Restart and Clear"), self.doClearRestart) self.menu.addSeparator() self.menu.addMenu(self.lmenu) - self.menu.addAction(self.tr('Active Name'), self.__showVenvName) + self.menu.addAction(self.tr("Active Name"), self.__showVenvName) self.menu.addSeparator() self.menu.addAction(self.tr("Save Contents..."), self.saveContents) self.menu.addSeparator() self.menu.addAction(self.tr("Configure..."), self.__configure) - + self.__bindLexer() self.__setTextDisplay() self.__setMargin0() - + # set the autocompletion and calltips function self.__setAutoCompletion() self.__setCallTips() - + self.setWindowIcon(UI.PixmapCache.getIcon("eric")) - + self.incrementalSearchString = "" self.incrementalSearchActive = False - + self.supportedEditorCommands = { QsciScintilla.SCI_LINEDELETE: self.__clearCurrentLine, QsciScintilla.SCI_TAB: self.__QScintillaTab, QsciScintilla.SCI_NEWLINE: self.__QScintillaNewline, - QsciScintilla.SCI_DELETEBACK: self.__QScintillaDeleteBack, QsciScintilla.SCI_CLEAR: self.__QScintillaDelete, QsciScintilla.SCI_DELWORDLEFT: self.__QScintillaDeleteWordLeft, QsciScintilla.SCI_DELWORDRIGHT: self.__QScintillaDeleteWordRight, QsciScintilla.SCI_DELLINELEFT: self.__QScintillaDeleteLineLeft, QsciScintilla.SCI_DELLINERIGHT: self.__QScintillaDeleteLineRight, - QsciScintilla.SCI_CHARLEFT: self.__QScintillaCharLeft, QsciScintilla.SCI_CHARRIGHT: self.__QScintillaCharRight, QsciScintilla.SCI_WORDLEFT: self.__QScintillaWordLeft, QsciScintilla.SCI_WORDRIGHT: self.__QScintillaWordRight, QsciScintilla.SCI_VCHOME: self.__QScintillaVCHome, QsciScintilla.SCI_LINEEND: self.__QScintillaLineEnd, - QsciScintilla.SCI_LINEUP: self.__QScintillaCursorCommand, QsciScintilla.SCI_LINEDOWN: self.__QScintillaCursorCommand, QsciScintilla.SCI_LINESCROLLUP: self.__QScintillaCursorCommand, QsciScintilla.SCI_LINESCROLLDOWN: self.__QScintillaCursorCommand, - QsciScintilla.SCI_PAGEUP: self.__QScintillaAutoCompletionCommand, QsciScintilla.SCI_PAGEDOWN: self.__QScintillaAutoCompletionCommand, - QsciScintilla.SCI_CHARLEFTEXTEND: self.__QScintillaCharLeftExtend, QsciScintilla.SCI_CHARRIGHTEXTEND: self.extendSelectionRight, QsciScintilla.SCI_WORDLEFTEXTEND: self.__QScintillaWordLeftExtend, QsciScintilla.SCI_WORDRIGHTEXTEND: self.extendSelectionWordRight, QsciScintilla.SCI_VCHOMEEXTEND: self.__QScintillaVCHomeExtend, QsciScintilla.SCI_LINEENDEXTEND: self.extendSelectionToEOL, - QsciScintilla.SCI_CANCEL: self.__QScintillaCancel, } - - self.__historyNavigateByCursor = ( - Preferences.getShell("HistoryNavigateByCursor") + + self.__historyNavigateByCursor = Preferences.getShell("HistoryNavigateByCursor") + + self.__queuedText = "" + self.__blockTextProcessing = False + self.queueText.connect( + self.__concatenateText, Qt.ConnectionType.QueuedConnection ) - - self.__queuedText = '' - self.__blockTextProcessing = False - self.queueText.connect(self.__concatenateText, - Qt.ConnectionType.QueuedConnection) - + self.__project = project if self.__project: self.__project.projectOpened.connect(self.__projectOpened) self.__project.projectClosed.connect(self.__projectClosed) - + self.grabGesture(Qt.GestureType.PinchGesture) - + def __showStartMenu(self): """ Private slot to prepare the start submenu. @@ -400,43 +407,44 @@ if self.__project.isOpen(): self.lmenu.addSeparator() self.lmenu.addAction(self.tr("Project")) - + def __resizeLinenoMargin(self): """ Private slot to resize the line numbers margin. """ linenoMargin = Preferences.getShell("LinenoMargin") if linenoMargin: - self.setMarginWidth(0, '8' * (len(str(self.lines())) + 1)) - + self.setMarginWidth(0, "8" * (len(str(self.lines())) + 1)) + def closeShell(self): """ Public method to shutdown the shell. """ for clientType in self.__historyLists: self.saveHistory(clientType) - - def __bindLexer(self, language='Python3'): + + def __bindLexer(self, language="Python3"): """ Private slot to set the lexer. - + @param language lexer language to set (string) """ self.language = language if Preferences.getShell("SyntaxHighlightingEnabled"): from . import Lexers + self.lexer_ = Lexers.getLexer(self.language, self) else: self.lexer_ = None - + if self.lexer_ is None: self.setLexer(None) font = Preferences.getShell("MonospacedFont") self.monospacedStyles(font) return - + # get the font for style 0 and set it as the default font - key = 'Scintilla/{0}/style0/font'.format(self.lexer_.language()) + key = "Scintilla/{0}/style0/font".format(self.lexer_.language()) fdesc = Preferences.getSettings().value(key) if fdesc is not None: font = QFont([fdesc[0]], int(fdesc[1])) @@ -445,28 +453,26 @@ self.lexer_.readSettings(Preferences.getSettings(), "Scintilla") if self.lexer_.hasSubstyles(): self.lexer_.readSubstyles(self) - + # initialize the lexer APIs settings api = self.vm.getAPIsManager().getAPIs(self.language) if api is not None: api = api.getQsciAPIs() if api is not None: self.lexer_.setAPIs(api) - + self.lexer_.setDefaultColor(self.lexer_.color(0)) self.lexer_.setDefaultPaper(self.lexer_.paper(0)) - + def __setMargin0(self): """ Private method to configure margin 0. """ # set the settings for all margins self.setMarginsFont(Preferences.getShell("MarginsFont")) - self.setMarginsForegroundColor( - Preferences.getEditorColour("MarginsForeground")) - self.setMarginsBackgroundColor( - Preferences.getEditorColour("MarginsBackground")) - + self.setMarginsForegroundColor(Preferences.getEditorColour("MarginsForeground")) + self.setMarginsBackgroundColor(Preferences.getEditorColour("MarginsBackground")) + # set margin 0 settings linenoMargin = Preferences.getShell("LinenoMargin") self.setMarginLineNumbers(0, linenoMargin) @@ -474,60 +480,65 @@ self.__resizeLinenoMargin() else: self.setMarginWidth(0, 0) - + # disable margins 1 and 2 self.setMarginWidth(1, 0) self.setMarginWidth(2, 0) - + def __setTextDisplay(self): """ Private method to configure the text display. """ self.setTabWidth(Preferences.getEditor("TabWidth")) if Preferences.getEditor("ShowWhitespace"): - self.setWhitespaceVisibility( - QsciScintilla.WhitespaceVisibility.WsVisible) + self.setWhitespaceVisibility(QsciScintilla.WhitespaceVisibility.WsVisible) with contextlib.suppress(AttributeError): self.setWhitespaceForegroundColor( - Preferences.getEditorColour("WhitespaceForeground")) + Preferences.getEditorColour("WhitespaceForeground") + ) self.setWhitespaceBackgroundColor( - Preferences.getEditorColour("WhitespaceBackground")) - self.setWhitespaceSize( - Preferences.getEditor("WhitespaceSize")) + Preferences.getEditorColour("WhitespaceBackground") + ) + self.setWhitespaceSize(Preferences.getEditor("WhitespaceSize")) else: - self.setWhitespaceVisibility( - QsciScintilla.WhitespaceVisibility.WsInvisible) + self.setWhitespaceVisibility(QsciScintilla.WhitespaceVisibility.WsInvisible) self.setEolVisibility(Preferences.getEditor("ShowEOL")) if Preferences.getEditor("BraceHighlighting"): self.setBraceMatching(QsciScintilla.BraceMatch.SloppyBraceMatch) else: self.setBraceMatching(QsciScintilla.BraceMatch.NoBraceMatch) self.setMatchedBraceForegroundColor( - Preferences.getEditorColour("MatchingBrace")) + Preferences.getEditorColour("MatchingBrace") + ) self.setMatchedBraceBackgroundColor( - Preferences.getEditorColour("MatchingBraceBack")) + Preferences.getEditorColour("MatchingBraceBack") + ) self.setUnmatchedBraceForegroundColor( - Preferences.getEditorColour("NonmatchingBrace")) + Preferences.getEditorColour("NonmatchingBrace") + ) self.setUnmatchedBraceBackgroundColor( - Preferences.getEditorColour("NonmatchingBraceBack")) + Preferences.getEditorColour("NonmatchingBraceBack") + ) if Preferences.getEditor("CustomSelectionColours"): self.setSelectionBackgroundColor( - Preferences.getEditorColour("SelectionBackground")) + Preferences.getEditorColour("SelectionBackground") + ) else: self.setSelectionBackgroundColor( - QApplication.palette().color(QPalette.ColorRole.Highlight)) + QApplication.palette().color(QPalette.ColorRole.Highlight) + ) if Preferences.getEditor("ColourizeSelText"): self.resetSelectionForegroundColor() elif Preferences.getEditor("CustomSelectionColours"): self.setSelectionForegroundColor( - Preferences.getEditorColour("SelectionForeground")) + Preferences.getEditorColour("SelectionForeground") + ) else: self.setSelectionForegroundColor( - QApplication.palette().color( - QPalette.ColorRole.HighlightedText)) + QApplication.palette().color(QPalette.ColorRole.HighlightedText) + ) self.setSelectionToEol(Preferences.getEditor("ExtendSelectionToEol")) - self.setCaretForegroundColor( - Preferences.getEditorColour("CaretForeground")) + self.setCaretForegroundColor(Preferences.getEditorColour("CaretForeground")) self.setCaretLineVisible(False) self.caretWidth = Preferences.getEditor("CaretWidth") self.setCaretWidth(self.caretWidth) @@ -537,17 +548,17 @@ self.setWrapMode(QsciScintilla.WrapMode.WrapNone) self.useMonospaced = Preferences.getShell("UseMonospacedFont") self.__setMonospaced(self.useMonospaced) - + self.setCursorFlashTime(QApplication.cursorFlashTime()) - + if Preferences.getEditor("OverrideEditAreaColours"): self.setColor(Preferences.getEditorColour("EditAreaForeground")) self.setPaper(Preferences.getEditorColour("EditAreaBackground")) - + def __setMonospaced(self, on): """ Private method to set/reset a monospaced font. - + @param on flag to indicate usage of a monospace font (boolean) """ if on: @@ -559,76 +570,78 @@ self.clearStyles() self.__setMargin0() self.setFont(Preferences.getShell("MonospacedFont")) - + self.useMonospaced = on - - def __setAutoCompletion(self, language='Python'): + + def __setAutoCompletion(self, language="Python"): """ Private method to configure the autocompletion function. - + @param language of the autocompletion set to set (string) """ self.setAutoCompletionCaseSensitivity( - Preferences.getEditor("AutoCompletionCaseSensitivity")) + Preferences.getEditor("AutoCompletionCaseSensitivity") + ) self.setAutoCompletionThreshold(-1) - + self.racEnabled = Preferences.getShell("AutoCompletionEnabled") - + self.setAutoCompletionWidgetSize( Preferences.getEditor("AutoCompletionMaxChars"), - Preferences.getEditor("AutoCompletionMaxLines") + Preferences.getEditor("AutoCompletionMaxLines"), ) - - def __setCallTips(self, language='Python'): + + def __setCallTips(self, language="Python"): """ Private method to configure the calltips function. - + @param language of the calltips set to set (string) """ if Preferences.getShell("CallTipsEnabled"): self.setCallTipsBackgroundColor( - Preferences.getEditorColour("CallTipsBackground")) + Preferences.getEditorColour("CallTipsBackground") + ) self.setCallTipsForegroundColor( - Preferences.getEditorColour("CallTipsForeground")) + Preferences.getEditorColour("CallTipsForeground") + ) self.setCallTipsHighlightColor( - Preferences.getEditorColour("CallTipsHighlight")) + Preferences.getEditorColour("CallTipsHighlight") + ) self.setCallTipsVisible(Preferences.getEditor("CallTipsVisible")) calltipsStyle = Preferences.getEditor("CallTipsStyle") if calltipsStyle == QsciScintilla.CallTipsStyle.CallTipsNoContext: - self.setCallTipsStyle( - QsciScintilla.CallTipsStyle.CallTipsNoContext) + self.setCallTipsStyle(QsciScintilla.CallTipsStyle.CallTipsNoContext) elif ( - calltipsStyle == - QsciScintilla.CallTipsStyle.CallTipsNoAutoCompletionContext + calltipsStyle + == QsciScintilla.CallTipsStyle.CallTipsNoAutoCompletionContext ): self.setCallTipsStyle( - QsciScintilla.CallTipsStyle - .CallTipsNoAutoCompletionContext) + QsciScintilla.CallTipsStyle.CallTipsNoAutoCompletionContext + ) else: - self.setCallTipsStyle( - QsciScintilla.CallTipsStyle.CallTipsContext) + self.setCallTipsStyle(QsciScintilla.CallTipsStyle.CallTipsContext) else: self.setCallTipsStyle(QsciScintilla.CallTipsStyle.CallTipsNone) - + def setDebuggerUI(self, ui): """ Public method to set the debugger UI. - + @param ui reference to the debugger UI object (DebugUI) """ ui.exceptionInterrupt.connect(self.__writePrompt) self.registerDebuggerIdMethod(ui.getSelectedDebuggerId) - + def registerDebuggerIdMethod(self, method): """ Public method to register a method to get the debugger ID to send data to. - + @param method reference to the method @type function """ self.__getSelectedDebuggerId = method - + def __initialise(self): """ Private method to get ready for a new remote interpreter. @@ -642,11 +655,11 @@ self.clientCapabilities = 0 self.inCommandExecution = False self.interruptCommandExecution = False - + def __clientCapabilities(self, cap, clType, venvName): """ Private slot to handle the reporting of the clients capabilities. - + @param cap client capabilities @type int @param clType type of the debug client @@ -664,34 +677,37 @@ self.__setAutoCompletion(self.clientType) self.__setCallTips(self.clientType) self.racEnabled = ( - Preferences.getShell("AutoCompletionEnabled") and - (cap & HasCompleter) > 0 + Preferences.getShell("AutoCompletionEnabled") + and (cap & HasCompleter) > 0 ) - + if self.clientType not in self.__historyLists: # load history list self.loadHistory(self.clientType) self.__history = self.__historyLists[self.clientType] self.__setHistoryIndex() - + self.virtualEnvironmentChanged.emit(venvName) Preferences.setShell("LastVirtualEnvironment", venvName) - + def __setHistoryIndex(self, index=None): """ Private method to set the initial history index. - + @param index index value to be set @type int or None """ if index is None: # determine based on history style if ( - self.clientType and - self.__historyStyle == ShellHistoryStyle.WINDOWSSTYLE + self.clientType + and self.__historyStyle == ShellHistoryStyle.WINDOWSSTYLE ): - idx = int(Preferences.getSettings().value( - "Shell/HistoryIndexes/" + self.clientType, -1)) + idx = int( + Preferences.getSettings().value( + "Shell/HistoryIndexes/" + self.clientType, -1 + ) + ) if idx >= len(self.__history): idx = -1 self.__histidx = idx @@ -702,42 +718,43 @@ if self.__histidx >= len(self.__history): self.__histidx = -1 if ( - self.clientType and - self.__historyStyle == ShellHistoryStyle.WINDOWSSTYLE + self.clientType + and self.__historyStyle == ShellHistoryStyle.WINDOWSSTYLE ): Preferences.getSettings().setValue( - "Shell/HistoryIndexes/" + self.clientType, self.__histidx) - + "Shell/HistoryIndexes/" + self.clientType, self.__histidx + ) + def __isHistoryIndexValid(self): """ Private method to test, if the history index is valid. - + @return flag indicating validity @rtype bool """ - return (0 <= self.__histidx < len(self.__history)) - + return 0 <= self.__histidx < len(self.__history) + def getHistoryIndex(self): """ Public method to get the current value of the history index. - + @return history index @rtype int """ return self.__histidx - + def loadHistory(self, clientType): """ Public method to load the history for the given client type. - + @param clientType type of the debug client (string) """ hl = Preferences.getSettings().value("Shell/Histories/" + clientType) if hl is not None: - self.__historyLists[clientType] = hl[-self.__maxHistoryEntries:] + self.__historyLists[clientType] = hl[-self.__maxHistoryEntries :] else: self.__historyLists[clientType] = [] - + def reloadHistory(self): """ Public method to reload the history of the currently selected client @@ -746,22 +763,22 @@ self.loadHistory(self.clientType) self.__history = self.__historyLists[self.clientType] self.__setHistoryIndex() - + def saveHistory(self, clientType): """ Public method to save the history for the given client type. - + @param clientType type of the debug client (string) """ if clientType in self.__historyLists: Preferences.getSettings().setValue( - "Shell/Histories/" + clientType, - self.__historyLists[clientType]) - + "Shell/Histories/" + clientType, self.__historyLists[clientType] + ) + def getHistory(self, clientType): """ Public method to get the history for the given client type. - + @param clientType type of the debug client (string). If it is None, the current history is returned. @return reference to the history list (list of strings) @@ -772,7 +789,7 @@ return self.__historyLists[clientType] else: return [] - + def clearHistory(self): """ Public slot to clear the current history. @@ -783,7 +800,7 @@ else: self.__history = [] self.__setHistoryIndex(index=-1) - + def selectHistory(self): """ Public slot to select a history entry to execute. @@ -794,24 +811,26 @@ cmd, ok = QInputDialog.getItem( self, self.tr("Select History"), - self.tr("Select the history entry to execute" - " (most recent shown last)."), + self.tr("Select the history entry to execute" " (most recent shown last)."), self.__history, - current, False) + current, + False, + ) if ok: self.__insertHistory(cmd) - + def showHistory(self): """ Public slot to show the shell history dialog. """ from .ShellHistoryDialog import ShellHistoryDialog + dlg = ShellHistoryDialog(self.__history, self.vm, self) if dlg.exec() == QDialog.DialogCode.Accepted: self.__historyLists[self.clientType], idx = dlg.getHistory() self.__history = self.__historyLists[self.clientType] self.__setHistoryIndex(index=idx) - + def clearAllHistories(self): """ Public method to clear all available histories and sync them. @@ -821,33 +840,33 @@ self.__historyLists[clientType] = [] self.saveHistory(clientType) Preferences.getSettings().endGroup() - + self.clearHistory() - + def getClientType(self): """ Public slot to get the clients type. - + @return client type (string) """ return self.clientType - + def __getBanner(self): """ Private method to get the banner for the remote interpreter. - + It requests the interpreter version and platform running on the debug client side. """ if self.passive: - self.__writeBanner('', '', '', '') + self.__writeBanner("", "", "", "") else: self.dbs.remoteBanner() - + def __writeBanner(self, version, platform, venvName): """ Private method to write a banner with info from the debug client. - + @param version interpreter version string @type str @param platform platform of the remote interpreter @@ -857,34 +876,34 @@ """ super().clear() if self.passive and not self.dbs.isConnected(): - self.__write(self.tr('Passive Debug Mode')) - self.__write(self.tr('\nNot connected')) + self.__write(self.tr("Passive Debug Mode")) + self.__write(self.tr("\nNot connected")) else: self.__currentVenv = venvName version = version.replace("#", self.tr("No.")) if platform != "": - self.__write(self.tr('{0} on {1}').format(version, platform)) + self.__write(self.tr("{0} on {1}").format(version, platform)) else: self.__write(version) if venvName: self.__write("\n[{0}]".format(venvName)) - + self.virtualEnvironmentChanged.emit(venvName) Preferences.setShell("LastVirtualEnvironment", venvName) - self.__write('\n') - + self.__write("\n") + self.__write(sys.ps1) - + def __writePrompt(self): """ Private method to write the prompt using a write queue. """ self.queueText.emit(self.inContinue and sys.ps2 or sys.ps1) - + def __clientStatement(self, more): """ Private method to handle the response from the debugger client. - + @param more flag indicating that more user input is required @type bool """ @@ -892,44 +911,42 @@ self.inContinue = more self.__writePrompt() self.inCommandExecution = False - + def __clientException(self, exceptionType, exceptionMessage, stackTrace): """ Private method to handle an exception of the client. - + @param exceptionType type of exception raised (string) @param exceptionMessage message given by the exception (string) @param stackTrace list of stack entries (list of string) """ - self .__clientError() - + self.__clientError() + if ( - not self.__windowed and - Preferences.getDebugger("ShowExceptionInShell") and - exceptionType + not self.__windowed + and Preferences.getDebugger("ShowExceptionInShell") + and exceptionType ): if stackTrace: self.__write( - self.tr('Exception "{0}"\n{1}\nFile: {2}, Line: {3}\n') - .format( + self.tr('Exception "{0}"\n{1}\nFile: {2}, Line: {3}\n').format( exceptionType, exceptionMessage, stackTrace[0][0], - stackTrace[0][1] + stackTrace[0][1], ) ) else: self.__write( - self.tr('Exception "{0}"\n{1}\n') - .format( - exceptionType, - exceptionMessage) + self.tr('Exception "{0}"\n{1}\n').format( + exceptionType, exceptionMessage + ) ) - + def __clientSyntaxError(self, message, filename, lineNo, characterNo): """ Private method to handle a syntax error in the debugged program. - + @param message message of the syntax error (string) @param filename translated filename of the syntax error position (string) @@ -937,25 +954,23 @@ @param characterNo character number of the syntax error position (integer) """ - self .__clientError() - - if ( - not self.__windowed and - Preferences.getDebugger("ShowExceptionInShell") - ): + self.__clientError() + + if not self.__windowed and Preferences.getDebugger("ShowExceptionInShell"): if message is None: self.__write(self.tr("Unspecified syntax error.\n")) else: self.__write( - self.tr('Syntax error "{1}" in file {0} at line {2},' - ' character {3}.\n') - .format(filename, message, lineNo, characterNo) + self.tr( + 'Syntax error "{1}" in file {0} at line {2},' + " character {3}.\n" + ).format(filename, message, lineNo, characterNo) ) - + def __clientSignal(self, message, filename, lineNo, funcName, funcArgs): """ Private method to handle a signal generated on the client side. - + @param message message of the syntax error @type str @param filename translated filename of the syntax error position @@ -968,13 +983,14 @@ @type str """ self.__clientError() - + self.__write( - self.tr("""Signal "{0}" generated in file {1} at line {2}.\n""" - """Function: {3}({4})""") - .format(message, filename, lineNo, funcName, funcArgs) + self.tr( + """Signal "{0}" generated in file {1} at line {2}.\n""" + """Function: {3}({4})""" + ).format(message, filename, lineNo, funcName, funcArgs) ) - + def __clientError(self): """ Private method to handle an error in the client. @@ -982,20 +998,20 @@ self.inCommandExecution = False self.interruptCommandExecution = True self.inContinue = False - + def __getEndPos(self): """ Private method to return the line and column of the last character. - + @return tuple of two values (int, int) giving the line and column """ line = self.lines() - 1 return (line, len(self.text(line))) - + def __writeQueued(self, s): """ Private method to display some text using a write queue. - + @param s text to be displayed (string) """ self.queueText.emit(s) @@ -1003,38 +1019,38 @@ def __concatenateText(self, text): """ Private slot to queue text and process it in one step. - + @param text text to be appended @type str """ self.__queuedText += text if self.__blockTextProcessing: return - + self.__blockTextProcessing = True # Get all text which is still waiting for output QApplication.processEvents() - + # Finally process the accumulated text self.__flushQueuedText() - + def __flushQueuedText(self): """ Private slot to flush the accumulated text output. """ self.__write(self.__queuedText) - - self.__queuedText = '' + + self.__queuedText = "" self.__blockTextProcessing = False - + # little trick to get the cursor position registered within QScintilla self.SendScintilla(QsciScintilla.SCI_CHARLEFT) self.SendScintilla(QsciScintilla.SCI_CHARRIGHT) - + def __write(self, s): """ Private method to display some text without queuing. - + @param s text to be displayed @type str """ @@ -1044,27 +1060,27 @@ self.prline, self.prcol = self.getCursorPosition() self.ensureCursorVisible() self.ensureLineVisible(self.prline) - + def __writeStdOut(self, s): """ Private method to display some text with StdOut label. - + @param s text to be displayed (string) """ self.__write(self.tr("StdOut: {0}").format(s)) - + def __writeStdErr(self, s): """ Private method to display some text with StdErr label. - + @param s text to be displayed (string) """ self.__write(self.tr("StdErr: {0}").format(s)) - + def __raw_input(self, prompt, echo, debuggerId): """ Private method to handle raw input. - + @param prompt the input prompt @type str @param echo flag indicating an echoing of the input @@ -1080,11 +1096,11 @@ self.__inRawMode = True self.__echoInput = echo self.__rawModeDebuggerId = debuggerId - + # Get all text which is still waiting for output QApplication.processEvents() self.__flushQueuedText() - + self.__write(self.tr("<{0}> {1}").format(debuggerId, prompt)) line, col = self.__getEndPos() self.setCursorPosition(line, col) @@ -1096,11 +1112,11 @@ self.prompt = buf # move cursor to end of line self.moveCursorToEOL() - + def paste(self, lines=None): """ Public slot to handle the paste action. - + @param lines list of lines to be inserted @type list of str """ @@ -1108,11 +1124,11 @@ line, col = self.getCursorPosition() lastLine = self.text(line) if lastLine.startswith(sys.ps1): - lastLine = lastLine[len(sys.ps1):] + lastLine = lastLine[len(sys.ps1) :] col -= len(sys.ps1) prompt = sys.ps1 elif lastLine.startswith(sys.ps2): - lastLine = lastLine[len(sys.ps2):] + lastLine = lastLine[len(sys.ps2) :] col -= len(sys.ps2) prompt = sys.ps2 else: @@ -1120,7 +1136,7 @@ if col < 0: col = 0 prompt = "" - + # Remove if text is selected if self.hasSelectedText(): lineFrom, indexFrom, lineTo, indexTo = self.getSelection() @@ -1137,20 +1153,20 @@ self.setCursorPosition(line, len(prompt)) self.deleteLineRight() - + if lines is None: lines = QApplication.clipboard().text() - + lines = lastLine[:col] + lines + lastLine[col:] self.executeLines(lines) line, _ = self.getCursorPosition() pos = len(self.text(line)) - (len(lastLine) - col) self.setCursorPosition(line, pos) - + def executeLines(self, lines, historyIndex=None): """ Public method to execute a set of lines as multiple commands. - + @param lines multiple lines of text to be executed as single commands @type str @@ -1160,47 +1176,47 @@ lines = lines.splitlines(True) if not lines: return - + indentLen = self.__indentLength(lines[0]) for line in lines: if line.startswith(sys.ps1): - line = line[len(sys.ps1) + indentLen:] + line = line[len(sys.ps1) + indentLen :] elif line.startswith(sys.ps2): - line = line[len(sys.ps2) + indentLen:] + line = line[len(sys.ps2) + indentLen :] else: line = line[indentLen:] - + if line.endswith(("\r\n", "\r", "\n")): fullline = True cmd = line.rstrip() else: fullline = False - + self.incrementalSearchActive = True self.__insertTextAtEnd(line) if fullline: self.incrementalSearchActive = False - + self.__executeCommand(cmd, historyIndex=historyIndex) if self.interruptCommandExecution: self.__executeCommand("") break - + def __indentLength(self, line): """ Private method to determine the indentation length of the given line. - + @param line line to determine the indentation length for @type str @return indentation length @rtype int """ if line.startswith(sys.ps1): - line = line[len(sys.ps1):] + line = line[len(sys.ps1) :] # If line starts with sys.ps2 or neither don't manipulate the line. indentLen = len(line) - len(line.lstrip()) return indentLen - + def __clearCurrentLine(self): """ Private method to clear the line containing the cursor. @@ -1214,42 +1230,42 @@ col = 0 self.setCursorPosition(line, col) self.deleteLineRight() - + def __insertText(self, s): """ Private method to insert some text at the current cursor position. - + @param s text to be inserted (string) """ line, col = self.getCursorPosition() self.insertAt(Utilities.filterAnsiSequences(s), line, col) self.setCursorPosition(line, col + len(s)) - + def __insertTextAtEnd(self, s): """ Private method to insert some text at the end of the command line. - + @param s text to be inserted (string) """ line, col = self.__getEndPos() self.setCursorPosition(line, col) self.insert(Utilities.filterAnsiSequences(s)) self.prline, _ = self.getCursorPosition() - + def __insertTextNoEcho(self, s): """ Private method to insert some text at the end of the buffer without echoing it. - + @param s text to be inserted (string) """ self.buff += s self.prline, self.prcol = self.getCursorPosition() - + def mousePressEvent(self, event): """ Protected method to handle the mouse press event. - + @param event the mouse press event (QMouseEvent) """ self.setFocus() @@ -1258,11 +1274,11 @@ self.paste(lines) else: super().mousePressEvent(event) - + def wheelEvent(self, evt): """ Protected method to handle wheel events. - + @param evt reference to the wheel event (QWheelEvent) """ if evt.modifiers() & Qt.KeyboardModifier.ControlModifier: @@ -1273,26 +1289,26 @@ self.zoomIn() evt.accept() return - + super().wheelEvent(evt) - + def event(self, evt): """ Public method handling events. - + @param evt reference to the event (QEvent) @return flag indicating, if the event was handled (boolean) """ if evt.type() == QEvent.Type.Gesture: self.gestureEvent(evt) return True - + return super().event(evt) - + def gestureEvent(self, evt): """ Protected method handling gesture events. - + @param evt reference to the gesture event (QGestureEvent """ pinch = evt.gesture(Qt.GestureType.PinchGesture) @@ -1310,11 +1326,11 @@ pinch.setTotalScaleFactor(3.0) self.zoomTo(zoom) evt.accept() - + def editorCommand(self, cmd): """ Public method to perform an editor command. - + @param cmd the scintilla command to be performed """ try: @@ -1323,24 +1339,24 @@ self.supportedEditorCommands[cmd](cmd) except KeyError: pass - + def __isCursorOnLastLine(self): """ Private method to check, if the cursor is on the last line. - + @return flag indicating that the cursor is on the last line (boolean) """ cline, ccol = self.getCursorPosition() return cline == self.lines() - 1 - + def keyPressEvent(self, ev): """ Protected method to handle the user input a key at a time. - + @param ev key event (QKeyEvent) """ txt = ev.text() - + # See it is text to insert. if len(txt) and txt >= " ": if not self.__isCursorOnLastLine(): @@ -1353,26 +1369,25 @@ self.incrementalSearchActive = True if ac and self.racEnabled: self.dbs.remoteCompletion( - self.__getSelectedDebuggerId(), - self.completionText + txt + self.__getSelectedDebuggerId(), self.completionText + txt ) else: self.__insertTextNoEcho(txt) else: ev.ignore() - + def __QScintillaCommand(self, cmd): """ Private method to send the command to QScintilla. - + @param cmd QScintilla command """ self.SendScintilla(cmd) - + def __QScintillaTab(self, cmd): """ Private method to handle the Tab key. - + @param cmd QScintilla command """ if self.isListActive(): @@ -1384,19 +1399,16 @@ buf = buf.replace(sys.ps1, "") if buf.startswith(sys.ps2): buf = buf.replace(sys.ps2, "") - if self.inContinue and not buf[:index - len(sys.ps2)].strip(): + if self.inContinue and not buf[: index - len(sys.ps2)].strip(): self.SendScintilla(cmd) elif self.racEnabled: - self.dbs.remoteCompletion( - self.__getSelectedDebuggerId(), - buf - ) - + self.dbs.remoteCompletion(self.__getSelectedDebuggerId(), buf) + def __QScintillaLeftDeleteCommand(self, method): """ Private method to handle a QScintilla delete command working to the left. - + @param method shell method to execute """ if self.__isCursorOnLastLine(): @@ -1404,7 +1416,7 @@ db = 0 ac = self.isListActive() oldLength = len(self.text(line)) - + if self.text(line).startswith(sys.ps1): if col > len(sys.ps1): method() @@ -1419,22 +1431,21 @@ if db and ac and self.racEnabled and self.completionText: delta = len(self.text(line)) - oldLength self.dbs.remoteCompletion( - self.__getSelectedDebuggerId(), - self.completionText[:delta] + self.__getSelectedDebuggerId(), self.completionText[:delta] ) - + def __QScintillaDeleteBack(self): """ Private method to handle the Backspace key. """ self.__QScintillaLeftDeleteCommand(self.deleteBack) - + def __QScintillaDeleteWordLeft(self): """ Private method to handle the Delete Word Left command. """ self.__QScintillaLeftDeleteCommand(self.deleteWordLeft) - + def __QScintillaDelete(self): """ Private method to handle the delete command. @@ -1452,7 +1463,7 @@ self.delete() else: self.delete() - + def __QScintillaDeleteLineLeft(self): """ Private method to handle the Delete Line Left command. @@ -1460,7 +1471,7 @@ if self.__isCursorOnLastLine(): if self.isListActive(): self.cancelList() - + line, col = self.getCursorPosition() if self.text(line).startswith(sys.ps1): prompt = sys.ps1 @@ -1468,15 +1479,15 @@ prompt = sys.ps2 else: prompt = "" - + self.deleteLineLeft() self.insertAt(prompt, line, 0) self.setCursorPosition(line, len(prompt)) - + def __QScintillaNewline(self, cmd): """ Private method to handle the Return key. - + @param cmd QScintilla command """ if self.__isCursorOnLastLine(): @@ -1492,7 +1503,7 @@ buf = buf.replace(sys.ps1, "") if buf.startswith(sys.ps2): buf = buf.replace(sys.ps2, "") - self.insert('\n') + self.insert("\n") self.__executeCommand(buf) else: txt = "" @@ -1505,16 +1516,16 @@ txt = self.text(line)[:indexTo] else: txt = self.text(line)[col:].rstrip() - + if txt: line, col = self.__getEndPos() self.setCursorPosition(line, col) self.insert(txt) - + def __QScintillaLeftCommand(self, method, allLinesAllowed=False): """ Private method to handle a QScintilla command working to the left. - + @param method shell method to execute @param allLinesAllowed flag indicating that the command may be executed on any line (boolean) @@ -1531,58 +1542,58 @@ method() else: method() - + def __QScintillaCharLeft(self): """ Private method to handle the Cursor Left command. """ self.__QScintillaLeftCommand(self.moveCursorLeft) - + def __QScintillaWordLeft(self): """ Private method to handle the Cursor Word Left command. """ self.__QScintillaLeftCommand(self.moveCursorWordLeft) - + def __QScintillaRightCommand(self, method): """ Private method to handle a QScintilla command working to the right. - + @param method shell method to execute """ if self.__isCursorOnLastLine(): method() else: method() - + def __QScintillaCharRight(self): """ Private method to handle the Cursor Right command. """ self.__QScintillaRightCommand(self.moveCursorRight) - + def __QScintillaWordRight(self): """ Private method to handle the Cursor Word Right command. """ self.__QScintillaRightCommand(self.moveCursorWordRight) - + def __QScintillaDeleteWordRight(self): """ Private method to handle the Delete Word Right command. """ self.__QScintillaRightCommand(self.deleteWordRight) - + def __QScintillaDeleteLineRight(self): """ Private method to handle the Delete Line Right command. """ self.__QScintillaRightCommand(self.deleteLineRight) - + def __QScintillaVCHome(self, cmd): """ Private method to handle the Home key. - + @param cmd QScintilla command """ if self.isListActive(): @@ -1596,22 +1607,22 @@ else: col = 0 self.setCursorPosition(line, col) - + def __QScintillaLineEnd(self, cmd): """ Private method to handle the End key. - + @param cmd QScintilla command """ if self.isListActive(): self.SendScintilla(cmd) elif self.__isCursorOnLastLine(): self.moveCursorToEOL() - + def __QScintillaCursorCommand(self, cmd): """ Private method to handle the cursor commands. - + @param cmd QScintilla command """ if self.isListActive() or self.isCallTipActive(): @@ -1636,27 +1647,27 @@ self.__QScintillaHistoryUp(cmd) elif cmd == QsciScintilla.SCI_LINESCROLLDOWN: self.__QScintillaHistoryDown(cmd) - + def __QScintillaLineUp(self, cmd): """ Private method to handle the cursor up command. - + @param cmd QScintilla command """ self.SendScintilla(QsciScintilla.SCI_LINEUP) - + def __QScintillaLineDown(self, cmd): """ Private method to handle the cursor down command. - + @param cmd QScintilla command """ self.SendScintilla(QsciScintilla.SCI_LINEDOWN) - + def __QScintillaHistoryUp(self, cmd): """ Private method to handle the history up command. - + @param cmd QScintilla command """ if self.isHistoryEnabled(): @@ -1667,12 +1678,12 @@ if buf.startswith(sys.ps2): buf = buf.replace(sys.ps2, "") if buf and self.incrementalSearchActive: - if ( - self.incrementalSearchString and - buf.startswith(self.incrementalSearchString) + if self.incrementalSearchString and buf.startswith( + self.incrementalSearchString ): idx, found = self.__rsearchHistory( - self.incrementalSearchString, self.__histidx) + self.incrementalSearchString, self.__histidx + ) if found and idx >= 0: self.__setHistoryIndex(index=idx) self.__useHistory() @@ -1697,11 +1708,11 @@ elif self.__histidx > 0: self.__setHistoryIndex(index=self.__histidx - 1) self.__useHistory() - + def __QScintillaHistoryDown(self, cmd): """ Private method to handle the history down command. - + @param cmd QScintilla command """ if self.isHistoryEnabled(): @@ -1712,12 +1723,12 @@ if buf.startswith(sys.ps2): buf = buf.replace(sys.ps2, "") if buf and self.incrementalSearchActive: - if ( - self.incrementalSearchString and - buf.startswith(self.incrementalSearchString) + if self.incrementalSearchString and buf.startswith( + self.incrementalSearchString ): idx, found = self.__searchHistory( - self.incrementalSearchString, self.__histidx) + self.incrementalSearchString, self.__histidx + ) if found and idx >= 0: self.__setHistoryIndex(index=idx) self.__useHistory() @@ -1739,7 +1750,7 @@ if self.__isHistoryIndexValid(): self.__setHistoryIndex(index=self.__histidx + 1) self.__useHistory() - + def __QScintillaCancel(self): """ Private method to handle the ESC command. @@ -1750,19 +1761,19 @@ if self.incrementalSearchActive: self.__resetIncrementalHistorySearch() self.__insertHistory("") - + def __QScintillaCharLeftExtend(self): """ Private method to handle the Extend Selection Left command. """ self.__QScintillaLeftCommand(self.extendSelectionLeft, True) - + def __QScintillaWordLeftExtend(self): """ Private method to handle the Extend Selection Left one word command. """ self.__QScintillaLeftCommand(self.extendSelectionWordLeft, True) - + def __QScintillaVCHomeExtend(self): """ Private method to handle the Extend Selection to start of line command. @@ -1774,25 +1785,25 @@ col = len(sys.ps2) else: col = 0 - + self.extendSelectionToBOL() while col > 0: self.extendSelectionRight() col -= 1 - + def __QScintillaAutoCompletionCommand(self, cmd): """ Private method to handle a command for autocompletion only. - + @param cmd QScintilla command """ if self.isListActive() or self.isCallTipActive(): self.SendScintilla(cmd) - + def __executeCommand(self, cmd, historyIndex=None): """ Private slot to execute a command. - + @param cmd command to be executed by debug client @type str @param historyIndex history index to be set @@ -1803,12 +1814,13 @@ self.interruptCommandExecution = False if not cmd: # make sure cmd is a string - cmd = '' - + cmd = "" + # History Handling if self.isHistoryEnabled(): if cmd != "" and ( - len(self.__history) == 0 or self.__history[-1] != cmd): + len(self.__history) == 0 or self.__history[-1] != cmd + ): if len(self.__history) == self.__maxHistoryEntries: del self.__history[0] self.__history.append(cmd) @@ -1817,15 +1829,15 @@ elif self.__historyStyle == ShellHistoryStyle.WINDOWSSTYLE: if historyIndex is None: if ( - self.__histidx - 1 > 0 and - cmd != self.__history[self.__histidx - 1] + self.__histidx - 1 > 0 + and cmd != self.__history[self.__histidx - 1] ): self.__setHistoryIndex(index=-1) else: self.__setHistoryIndex(historyIndex) - + if cmd.startswith("%"): - if cmd == '%start' or cmd.startswith('%start '): + if cmd == "%start" or cmd.startswith("%start "): if not self.passive: cmdList = cmd.split(None, 1) if len(cmdList) < 2: @@ -1838,8 +1850,7 @@ self.dbs.startClient( False, forProject=True, - workingDir=self.__project - .getProjectPath() + workingDir=self.__project.getProjectPath(), ) self.__currentWorkingDirectory = ( self.__project.getProjectPath() @@ -1848,8 +1859,7 @@ self.dbs.startClient( False, venvName=self.__currentVenv, - workingDir=self - .__currentWorkingDirectory + workingDir=self.__currentWorkingDirectory, ) # same as reset else: @@ -1857,52 +1867,48 @@ self.__currentWorkingDirectory = "" self.__getBanner() return - elif cmd == '%clear': + elif cmd == "%clear": # Display the banner. self.__getBanner() if not self.passive: return else: - cmd = '' - elif cmd in ['%reset', '%restart']: + cmd = "" + elif cmd in ["%reset", "%restart"]: self.dbs.startClient( - False, venvName=self.__currentVenv, - workingDir=self.__currentWorkingDirectory) + False, + venvName=self.__currentVenv, + workingDir=self.__currentWorkingDirectory, + ) if self.passive: return else: - cmd = '' - elif cmd in ['%envs', '%environments']: + cmd = "" + elif cmd in ["%envs", "%environments"]: venvs = ( - ericApp().getObject("VirtualEnvManager") - .getVirtualenvNames() + ericApp().getObject("VirtualEnvManager").getVirtualenvNames() ) - s = ( - self.tr('Available Virtual Environments:\n{0}\n') - .format('\n'.join( - "- {0}".format(venv) - for venv in sorted(venvs) - )) + s = self.tr("Available Virtual Environments:\n{0}\n").format( + "\n".join("- {0}".format(venv) for venv in sorted(venvs)) ) self.__write(s) self.__clientStatement(False) return - elif cmd == '%which': + elif cmd == "%which": s = self.tr("Current Virtual Environment: '{0}'\n").format( - self.__currentVenv) + self.__currentVenv + ) self.__write(s) self.__clientStatement(False) return elif ( - cmd in ["%quit", "%quit()", "%exit", "%exit()"] and - self.__windowed + cmd in ["%quit", "%quit()", "%exit", "%exit()"] and self.__windowed ): # call main window quit() self.vm.quit() return else: - self.dbs.remoteStatement( - self.__getSelectedDebuggerId(), cmd) + self.dbs.remoteStatement(self.__getSelectedDebuggerId(), cmd) while self.inCommandExecution: with contextlib.suppress(KeyboardInterrupt): QApplication.processEvents() @@ -1911,25 +1917,26 @@ cmd = self.buff self.buff = "" elif cmd: - cmd = cmd[len(self.prompt):] + cmd = cmd[len(self.prompt) :] self.__inRawMode = False self.__echoInput = True - + self.dbs.remoteRawInput(self.__rawModeDebuggerId, cmd) - + if self.__rawModeQueue: debuggerId, prompt, echo = self.__rawModeQueue.pop(0) self.__raw_input(prompt, echo, debuggerId) - + def __showVenvName(self): """ Private method to show the name of the active virtual environment. """ s = "\n" + self.tr("Current Virtual Environment: '{0}'\n").format( - self.__currentVenv) + self.__currentVenv + ) self.__write(s) self.__clientStatement(False) - + def __useHistory(self): """ Private method to display a command from the history. @@ -1939,32 +1946,33 @@ else: cmd = "" self.__resetIncrementalHistorySearch() - + self.__insertHistory(cmd) def __insertHistory(self, cmd): """ Private method to insert a command selected from the history. - + @param cmd history entry to be inserted (string) """ self.setCursorPosition(self.prline, self.prcol) - self.setSelection(self.prline, self.prcol, - self.prline, self.lineLength(self.prline)) + self.setSelection( + self.prline, self.prcol, self.prline, self.lineLength(self.prline) + ) self.removeSelectedText() self.__insertText(cmd) - + def __resetIncrementalHistorySearch(self): """ Private method to reset the incremental history search. """ self.incrementalSearchString = "" self.incrementalSearchActive = False - + def __searchHistory(self, txt, startIdx=-1): """ Private method used to search the history. - + @param txt text to match at the beginning @type str @param startIdx index to start search from @@ -1974,19 +1982,15 @@ @rtype tuple of (int, bool) """ idx = 0 if startIdx == -1 else startIdx + 1 - while ( - idx < len(self.__history) and - not self.__history[idx].startswith(txt) - ): + while idx < len(self.__history) and not self.__history[idx].startswith(txt): idx += 1 - found = (idx < len(self.__history) and - self.__history[idx].startswith(txt)) + found = idx < len(self.__history) and self.__history[idx].startswith(txt) return idx, found - + def __rsearchHistory(self, txt, startIdx=-1): """ Private method used to reverse search the history. - + @param txt text to match at the beginning @type str @param startIdx index to start search from @@ -1996,79 +2000,78 @@ @rtype tuple of (int, bool) """ idx = len(self.__history) - 1 if startIdx == -1 else startIdx - 1 - while ( - idx >= 0 and - not self.__history[idx].startswith(txt) - ): + while idx >= 0 and not self.__history[idx].startswith(txt): idx -= 1 found = idx >= 0 and self.__history[idx].startswith(txt) return idx, found - + def focusNextPrevChild(self, nextChild): """ Public method to stop Tab moving to the next window. - + While the user is entering a multi-line command, the movement to the next window by the Tab key being pressed is suppressed. - + @param nextChild next window @return flag indicating the movement """ if nextChild and self.inContinue: return False - + return QsciScintillaCompat.focusNextPrevChild(self, nextChild) - + def contextMenuEvent(self, ev): """ Protected method to show our own context menu. - + @param ev context menu event (QContextMenuEvent) """ if not self.__windowed: self.menu.popup(ev.globalPos()) ev.accept() - + def clear(self): """ Public slot to clear the display. """ # Display the banner. self.__getBanner() - + def doClearRestart(self): """ Public slot to handle the 'restart and clear' context menu entry. """ self.doRestart() self.clear() - + def doRestart(self): """ Public slot to handle the 'restart' context menu entry. """ - self.dbs.startClient(False, venvName=self.__currentVenv, - workingDir=self.__currentWorkingDirectory) - + self.dbs.startClient( + False, + venvName=self.__currentVenv, + workingDir=self.__currentWorkingDirectory, + ) + def __startDebugClient(self, action): """ Private slot to start a debug client according to the action triggered. - + @param action context menu action that was triggered (QAction) """ venvName = action.text() if venvName == self.tr("Project"): if self.__project.isOpen(): - self.__currentWorkingDirectory = ( - self.__project.getProjectPath() - ) - self.dbs.startClient(False, forProject=True, - workingDir=self.__currentWorkingDirectory) + self.__currentWorkingDirectory = self.__project.getProjectPath() + self.dbs.startClient( + False, forProject=True, workingDir=self.__currentWorkingDirectory + ) else: self.dbs.startClient(False, venvName=venvName) self.__getBanner() - + def handlePreferencesChanged(self): """ Public slot to handle the preferencesChanged signal. @@ -2076,30 +2079,29 @@ # rebind the lexer self.__bindLexer(self.language) self.recolor() - + # set margin 0 configuration self.__setTextDisplay() self.__setMargin0() - + # set the autocompletion and calltips function self.__setAutoCompletion() self.__setCallTips() - + # do the history related stuff self.__maxHistoryEntries = Preferences.getShell("MaxHistoryEntries") for key in list(self.__historyLists.keys()): - self.__historyLists[key] = ( - self.__historyLists[key][-self.__maxHistoryEntries:] - ) + self.__historyLists[key] = self.__historyLists[key][ + -self.__maxHistoryEntries : + ] self.__historyStyle = Preferences.getShell("HistoryStyle") self.__historyWrap = Preferences.getShell("HistoryWrap") self.__setHistoryIndex() if not self.__windowed: self.hmenu.menuAction().setEnabled(self.isHistoryEnabled()) - self.__historyNavigateByCursor = Preferences.getShell( - "HistoryNavigateByCursor") + self.__historyNavigateByCursor = Preferences.getShell("HistoryNavigateByCursor") self.historyStyleChanged.emit(self.__historyStyle) - + # do stdout /stderr stuff showStdOutErr = Preferences.getShell("ShowStdOutErr") if self.__showStdOutErr != showStdOutErr: @@ -2110,18 +2112,18 @@ self.dbs.clientProcessStdout.disconnect(self.__writeStdOut) self.dbs.clientProcessStderr.disconnect(self.__writeStdErr) self.__showStdOutErr = showStdOutErr - + @pyqtSlot(list, str) def __showCompletions(self, completions, text): """ Private method to display the possible completions. - + @param completions list of possible completions (list of strings) @param text text that is about to be completed (string) """ if len(completions) == 0: return - + if len(completions) > 1: completions.sort() self.showUserList(1, completions) @@ -2132,11 +2134,11 @@ txt = txt.replace(text, "") self.__insertText(txt) self.completionText = "" - + def __completionListSelected(self, listId, txt): """ Private slot to handle the selection from the completion list. - + @param listId the ID of the user list (should be 1) (integer) @param txt the selected text (string) """ @@ -2145,41 +2147,38 @@ txt = txt.replace(self.completionText, "") self.__insertText(txt) self.completionText = "" - + ################################################################# ## Drag and Drop Support ################################################################# - + def dragEnterEvent(self, event): """ Protected method to handle the drag enter event. - + @param event the drag enter event (QDragEnterEvent) """ - self.inDragDrop = ( - event.mimeData().hasUrls() or - event.mimeData().hasText() - ) + self.inDragDrop = event.mimeData().hasUrls() or event.mimeData().hasText() if self.inDragDrop: event.acceptProposedAction() else: super().dragEnterEvent(event) - + def dragMoveEvent(self, event): """ Protected method to handle the drag move event. - + @param event the drag move event (QDragMoveEvent) """ if self.inDragDrop: event.accept() else: super().dragMoveEvent(event) - + def dragLeaveEvent(self, event): """ Protected method to handle the drag leave event. - + @param event the drag leave event (QDragLeaveEvent) """ if self.inDragDrop: @@ -2187,11 +2186,11 @@ event.accept() else: super().dragLeaveEvent(event) - + def dropEvent(self, event): """ Protected method to handle the drop event. - + @param event the drop event (QDropEvent) """ if event.mimeData().hasUrls() and not self.__windowed: @@ -2204,8 +2203,10 @@ EricMessageBox.information( self, self.tr("Drop Error"), - self.tr("""<p><b>{0}</b> is not a file.</p>""") - .format(fname)) + self.tr("""<p><b>{0}</b> is not a file.</p>""").format( + fname + ), + ) event.acceptProposedAction() elif event.mimeData().hasText(): s = event.mimeData().text() @@ -2215,13 +2216,13 @@ del s else: super().dropEvent(event) - + self.inDragDrop = False - + def focusInEvent(self, event): """ Protected method called when the shell receives focus. - + @param event the event object (QFocusEvent) """ if not self.__actionsAdded: @@ -2230,15 +2231,21 @@ self.addActions(self.vm.viewActGrp.actions()) if not self.__windowed: self.__searchShortcut = QShortcut( - self.vm.searchAct.shortcut(), self, - self.__find, self.__find) + self.vm.searchAct.shortcut(), self, self.__find, self.__find + ) self.__searchNextShortcut = QShortcut( - self.vm.searchNextAct.shortcut(), self, - self.__searchNext, self.__searchNext) + self.vm.searchNextAct.shortcut(), + self, + self.__searchNext, + self.__searchNext, + ) self.__searchPrevShortcut = QShortcut( - self.vm.searchPrevAct.shortcut(), self, - self.__searchPrev, self.__searchPrev) - + self.vm.searchPrevAct.shortcut(), + self, + self.__searchPrev, + self.__searchPrev, + ) + with contextlib.suppress(AttributeError): self.vm.editActGrp.setEnabled(False) self.vm.editorActGrp.setEnabled(True) @@ -2251,13 +2258,13 @@ self.__searchPrevShortcut.setEnabled(True) self.setCaretWidth(self.caretWidth) self.setCursorFlashTime(QApplication.cursorFlashTime()) - + super().focusInEvent(event) - + def focusOutEvent(self, event): """ Protected method called when the shell loses focus. - + @param event the event object (QFocusEvent) """ with contextlib.suppress(AttributeError): @@ -2268,13 +2275,13 @@ self.__searchPrevShortcut.setEnabled(False) self.setCaretWidth(0) super().focusOutEvent(event) - + def insert(self, txt): """ Public slot to insert text at the current cursor position. - + The cursor is advanced to the end of the inserted text. - + @param txt text to be inserted (string) """ txt = Utilities.filterAnsiSequences(txt) @@ -2284,31 +2291,31 @@ if re.search(self.linesepRegExp, txt) is not None: line += 1 self.setCursorPosition(line, col + length) - + def __configure(self): """ Private method to open the configuration dialog. """ ericApp().getObject("UserInterface").showPreferences("shellPage") - + def __find(self): """ Private slot to show the find widget. """ txt = self.selectedText() self.__mainWindow.showFind(txt) - + def __searchNext(self): """ Private method to search for the next occurrence. """ if self.__lastSearch: self.searchNext(*self.__lastSearch) - + def searchNext(self, txt, caseSensitive, wholeWord, regexp): """ Public method to search the next occurrence of the given text. - + @param txt text to search for @type str @param caseSensitive flag indicating to perform a case sensitive @@ -2324,21 +2331,28 @@ posixMode = Preferences.getEditor("SearchRegexpMode") == 0 and regexp cxx11Mode = Preferences.getEditor("SearchRegexpMode") == 1 and regexp ok = self.findFirst( - txt, regexp, caseSensitive, wholeWord, True, forward=True, - posix=posixMode, cxx11=cxx11Mode) + txt, + regexp, + caseSensitive, + wholeWord, + True, + forward=True, + posix=posixMode, + cxx11=cxx11Mode, + ) self.searchStringFound.emit(ok) - + def __searchPrev(self): """ Private method to search for the next occurrence. """ if self.__lastSearch: self.searchPrev(*self.__lastSearch) - + def searchPrev(self, txt, caseSensitive, wholeWord, regexp): """ Public method to search the previous occurrence of the given text. - + @param txt text to search for @type str @param caseSensitive flag indicating to perform a case sensitive @@ -2358,29 +2372,37 @@ posixMode = Preferences.getEditor("SearchRegexpMode") == 0 and regexp cxx11Mode = Preferences.getEditor("SearchRegexpMode") == 1 and regexp ok = self.findFirst( - txt, regexp, caseSensitive, wholeWord, True, - forward=False, line=line, index=index, posix=posixMode, - cxx11=cxx11Mode) + txt, + regexp, + caseSensitive, + wholeWord, + True, + forward=False, + line=line, + index=index, + posix=posixMode, + cxx11=cxx11Mode, + ) self.searchStringFound.emit(ok) - + def historyStyle(self): """ Public method to get the shell history style. - + @return shell history style @rtype ShellHistoryStyle """ return self.__historyStyle - + def isHistoryEnabled(self): """ Public method to check, if the history is enabled. - + @return flag indicating if history is enabled @rtype bool """ return self.__historyStyle != ShellHistoryStyle.DISABLED - + def saveContents(self): """ Public method to save the current contents to a file. @@ -2393,13 +2415,13 @@ Preferences.getMultiProject("Workspace"), self.tr("Text Files (*.txt);;All Files (*)"), None, - EricFileDialog.DontConfirmOverwrite + EricFileDialog.DontConfirmOverwrite, ) - + if fn: if fn.endswith("."): fn = fn[:-1] - + fpath = pathlib.Path(fn) if not fpath.suffix: ex = selectedFilter.split("(*")[1].split(")")[0] @@ -2409,9 +2431,12 @@ res = EricMessageBox.yesNo( self, self.tr("Save Shell Contents"), - self.tr("<p>The file <b>{0}</b> already exists." - " Overwrite it?</p>").format(fpath), - icon=EricMessageBox.Warning) + self.tr( + "<p>The file <b>{0}</b> already exists." + " Overwrite it?</p>" + ).format(fpath), + icon=EricMessageBox.Warning, + ) if not res: return try: @@ -2421,24 +2446,27 @@ EricMessageBox.critical( self, self.tr("Save Shell Contents"), - self.tr('<p>The file <b>{0}</b> could not be saved.<br/>' - 'Reason: {1}</p>') - .format(fpath, str(why))) - + self.tr( + "<p>The file <b>{0}</b> could not be saved.<br/>" + "Reason: {1}</p>" + ).format(fpath, str(why)), + ) + ################################################################# ## Project Support ################################################################# - + def __projectOpened(self): """ Private slot to start the shell for the opened project. """ if Preferences.getProject("RestartShellForProject"): - self.dbs.startClient(False, forProject=True, - workingDir=self.__project.getProjectPath()) + self.dbs.startClient( + False, forProject=True, workingDir=self.__project.getProjectPath() + ) self.__currentWorkingDirectory = self.__project.getProjectPath() self.__getBanner() - + def __projectClosed(self): """ Private slot to restart the default shell when the project is closed. @@ -2447,5 +2475,6 @@ self.dbs.startClient(False) self.__getBanner() + # # eflag: noqa = M601