diff -r 866adc8c315b -r 0acf98cd089a eric6/QScintilla/Shell.py --- a/eric6/QScintilla/Shell.py Sun Jan 17 13:53:08 2021 +0100 +++ b/eric6/QScintilla/Shell.py Mon Feb 01 10:38:16 2021 +0100 @@ -12,7 +12,7 @@ from enum import Enum -from PyQt5.QtCore import pyqtSignal, QFileInfo, Qt, QEvent +from PyQt5.QtCore import pyqtSignal, pyqtSlot, QFileInfo, Qt, QEvent from PyQt5.QtGui import QClipboard, QPalette, QFont from PyQt5.QtWidgets import ( QDialog, QInputDialog, QApplication, QMenu, QWidget, QHBoxLayout, @@ -240,6 +240,8 @@ dbs.clientSignal.connect(self.__clientSignal) self.dbs = dbs + self.__debugUI = None + # Initialize instance variables. self.__initialise() self.prline = 0 @@ -603,6 +605,7 @@ @param ui reference to the debugger UI object (DebugUI) """ ui.exceptionInterrupt.connect(self.__writePrompt) + self.__debugUI = ui def __initialise(self): """ @@ -610,8 +613,10 @@ """ self.buff = "" self.inContinue = False - self.inRawMode = False - self.echoInput = True + self.__inRawMode = False + self.__echoInput = True + self.__rawModeDebuggerId = None + self.__rawModeQueue = [] self.clientCapabilities = 0 self.inCommandExecution = False self.interruptCommandExecution = False @@ -817,7 +822,7 @@ else: self.dbs.remoteBanner() - def __writeBanner(self, version, platform, dbgclient, venvName): + def __writeBanner(self, version, platform, venvName): """ Private method to write a banner with info from the debug client. @@ -825,8 +830,6 @@ @type str @param platform platform of the remote interpreter @type str - @param dbgclient debug client variant used - @type str @param venvName name of the virtual environment @type str """ @@ -837,10 +840,8 @@ else: self.__currentVenv = venvName version = version.replace("#", self.tr("No.")) - if platform != "" and dbgclient != "": - self.__write( - self.tr('{0} on {1}, {2}') - .format(version, platform, dbgclient)) + if platform != "": + self.__write(self.tr('{0} on {1}').format(version, platform)) else: self.__write(version) if venvName: @@ -862,9 +863,10 @@ """ Private method to handle the response from the debugger client. - @param more flag indicating that more user input is required (boolean) + @param more flag indicating that more user input is required + @type bool """ - if not self.inRawMode: + if not self.__inRawMode: self.inContinue = more self.__writePrompt() self.inCommandExecution = False @@ -1037,38 +1039,48 @@ """ self.__write(self.tr("StdErr: {0}").format(s)) - def __raw_input(self, prompt, echo): + def __raw_input(self, prompt, echo, debuggerId): """ Private method to handle raw input. - @param prompt prompt to be displayed + @param prompt the input prompt @type str - @param echo Flag indicating echoing of the input + @param echo flag indicating an echoing of the input @type bool + @param debuggerId ID of the debugger backend + @type str """ - self.setFocus() - self.inRawMode = True - self.echoInput = echo - - # Get all text which is still waiting for output - QApplication.processEvents() - self.__flushQueuedText() + if self.__inRawMode: + # we are processing another raw input event already + self.__rawModeQueue.append((debuggerId, prompt, echo)) + else: + self.setFocus() + 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) + buf = self.text(line) + if buf.startswith(sys.ps1): + buf = buf.replace(sys.ps1, "") + if buf.startswith(sys.ps2): + buf = buf.replace(sys.ps2, "") + self.prompt = buf + # move cursor to end of line + self.moveCursorToEOL() - self.__write(prompt) - line, col = self.__getEndPos() - self.setCursorPosition(line, col) - buf = self.text(line) - if buf.startswith(sys.ps1): - buf = buf.replace(sys.ps1, "") - if buf.startswith(sys.ps2): - buf = buf.replace(sys.ps2, "") - self.prompt = buf - # move cursor to end of line - self.moveCursorToEOL() - - def paste(self): + def paste(self, lines=None): """ Public slot to handle the paste action. + + @param lines list of lines to be inserted + @type list of str """ if self.__isCursorOnLastLine(): line, col = self.getCursorPosition() @@ -1104,20 +1116,15 @@ self.setCursorPosition(line, len(prompt)) self.deleteLineRight() - lines = QApplication.clipboard().text() + 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 __middleMouseButton(self): - """ - Private method to handle the middle mouse button press. - """ - lines = QApplication.clipboard().text(QClipboard.Selection) - self.executeLines(lines) - + def executeLines(self, lines, historyIndex=None): """ Public method to execute a set of lines as multiple commands. @@ -1141,12 +1148,9 @@ else: line = line[indentLen:] - if line.endswith("\r\n"): + if line.endswith(("\r\n", "\r", "\n")): fullline = True - cmd = line[:-2] - elif line.endswith("\r") or line.endswith("\n"): - fullline = True - cmd = line[:-1] + cmd = line.rstrip() else: fullline = False @@ -1228,7 +1232,8 @@ """ self.setFocus() if event.button() == Qt.MidButton: - self.__middleMouseButton() + lines = QApplication.clipboard().text(QClipboard.Selection) + self.paste(lines) else: super(Shell, self).mousePressEvent(event) @@ -1320,12 +1325,15 @@ line, col = self.__getEndPos() self.setCursorPosition(line, col) self.prline, self.prcol = self.getCursorPosition() - if self.echoInput: + if self.__echoInput: ac = self.isListActive() super(Shell, self).keyPressEvent(ev) self.incrementalSearchActive = True if ac and self.racEnabled: - self.dbs.remoteCompletion(self.completionText + txt) + self.dbs.remoteCompletion( + self.__debugUI.getSelectedDebuggerId(), + self.completionText + txt + ) else: self.__insertTextNoEcho(txt) else: @@ -1357,7 +1365,10 @@ if self.inContinue and not buf[:index - len(sys.ps2)].strip(): self.SendScintilla(cmd) elif self.racEnabled: - self.dbs.remoteCompletion(buf) + self.dbs.remoteCompletion( + self.__debugUI.getSelectedDebuggerId(), + buf + ) def __QScintillaLeftDeleteCommand(self, method): """ @@ -1385,7 +1396,10 @@ db = 1 if db and ac and self.racEnabled and self.completionText: delta = len(self.text(line)) - oldLength - self.dbs.remoteCompletion(self.completionText[:delta]) + self.dbs.remoteCompletion( + self.__debugUI.getSelectedDebuggerId(), + self.completionText[:delta] + ) def __QScintillaDeleteBack(self): """ @@ -1762,7 +1776,7 @@ @param historyIndex history index to be set @type int """ - if not self.inRawMode: + if not self.__inRawMode: self.inCommandExecution = True self.interruptCommandExecution = False if not cmd: @@ -1852,22 +1866,27 @@ self.vm.quit() return - self.dbs.remoteStatement(cmd) + self.dbs.remoteStatement(self.__debugUI.getSelectedDebuggerId(), + cmd) while self.inCommandExecution: try: QApplication.processEvents() except KeyboardInterrupt: pass else: - if not self.echoInput: + if not self.__echoInput: cmd = self.buff self.buff = "" elif cmd: cmd = cmd[len(self.prompt):] - self.inRawMode = False - self.echoInput = True + self.__inRawMode = False + self.__echoInput = True - self.dbs.remoteRawInput(cmd) + 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): """ @@ -2064,7 +2083,8 @@ 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.