--- a/src/eric7/QScintilla/Shell.py Sun Sep 03 13:54:22 2023 +0200 +++ b/src/eric7/QScintilla/Shell.py Sun Sep 03 17:35:15 2023 +0200 @@ -32,6 +32,7 @@ from eric7.EricGui import EricPixmapCache from eric7.EricWidgets import EricFileDialog, EricMessageBox from eric7.EricWidgets.EricApplication import ericApp +from eric7.EricWidgets.EricSimpleHelpDialog import EricSimpleHelpDialog from eric7.UI.SearchWidget import SearchWidget from . import Lexers @@ -152,6 +153,7 @@ self.__windowed = windowedVariant self.__currentVenv = "" self.__currentWorkingDirectory = "" + self.__helpDialog = None self.linesepRegExp = r"\r\n|\n|\r" @@ -174,19 +176,8 @@ """ 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>The shell has some special commands. Type '%help' to get""" + """ a list of these commands.</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""" @@ -208,17 +199,8 @@ """ 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>The shell has some special commands. Type '%help' to get""" + """ a list of these commands.</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""" @@ -318,7 +300,6 @@ 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.addSeparator() @@ -332,6 +313,8 @@ self.menu.addAction(self.tr("Save Contents..."), self.saveContents) self.menu.addSeparator() self.menu.addAction(self.tr("Configure..."), self.__configure) + self.menu.addSeparator() + self.menu.addAction(self.tr("Special Commands Help"), self.__showHelp) self.customContextMenuRequested.connect(self.__showContextMenu) self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) @@ -783,10 +766,23 @@ else: return [] - def clearHistory(self): + @pyqtSlot() + def clearHistory(self, ask=True): """ Public slot to clear the current history. + + @param ask flag indicating to ask for confirmation (defaults to True) + @type bool (optional) """ + if ask: + ok = EricMessageBox.yesNo( + self, + self.tr("Clear History"), + self.tr("""Shall the current history really be cleared?"""), + ) + if not ok: + return + if self.clientType: self.__historyLists[self.clientType] = [] self.__history = self.__historyLists[self.clientType] @@ -794,6 +790,7 @@ self.__history = [] self.__setHistoryIndex(index=-1) + @pyqtSlot() def selectHistory(self): """ Public slot to select a history entry to execute. @@ -812,14 +809,23 @@ if ok: self.__insertHistory(cmd) - def showHistory(self): + @pyqtSlot() + def showHistory(self, histSize=None): """ Public slot to show the shell history dialog. + + @param histSize number of history entries to be shown (None = show all + entrys) (defaults to None) + @type int (optional) """ from .ShellHistoryDialog import ShellHistoryDialog - dlg = ShellHistoryDialog(self.__history, self.vm, self) - if dlg.exec() == QDialog.DialogCode.Accepted: + dlg = ( + ShellHistoryDialog(self.__history, self.vm, self) + if histSize is None + else ShellHistoryDialog(self.__history[-histSize:], self.vm, self) + ) + if dlg.exec() == QDialog.DialogCode.Accepted and histSize is None: self.__historyLists[self.clientType], idx = dlg.getHistory() self.__history = self.__historyLists[self.clientType] self.__setHistoryIndex(index=idx) @@ -834,7 +840,7 @@ self.saveHistory(clientType) Preferences.getSettings().endGroup() - self.clearHistory() + self.clearHistory(ask=False) def getClientType(self): """ @@ -1085,7 +1091,7 @@ # we are processing another raw input event already self.__rawModeQueue.append((debuggerId, prompt, echo)) else: - self.setFocus() + self.setFocus(Qt.FocusReason.OtherFocusReason) self.__inRawMode = True self.__echoInput = echo self.__rawModeDebuggerId = debuggerId @@ -1261,7 +1267,7 @@ @param event the mouse press event (QMouseEvent) """ - self.setFocus() + self.setFocus(Qt.FocusReason.MouseFocusReason) if event.button() == Qt.MouseButton.MiddleButton: lines = QApplication.clipboard().text(QClipboard.Mode.Selection) self.paste(lines) @@ -1829,9 +1835,6 @@ else: self.__setHistoryIndex(historyIndex) - # TODO: add a '%help' command listing available % commands - # TODO: add '%history [n]' command to show the 'n' most recently used - # commands (default: n = 10) if cmd.startswith("%"): if cmd == "%start" or cmd.startswith("%start "): if not self.passive: @@ -1866,25 +1869,16 @@ else: self.dbs.startClient(False, venvName=venvName) self.__currentWorkingDirectory = "" - self.__getBanner() - return + self.__getBanner() elif cmd == "%clear": # Display the banner. self.__getBanner() - if not self.passive: - return - else: - cmd = "" elif cmd in ["%reset", "%restart"]: self.dbs.startClient( False, venvName=self.__currentVenv, workingDir=self.__currentWorkingDirectory, ) - if self.passive: - return - else: - cmd = "" elif cmd in ["%envs", "%environments"]: venvs = ( ericApp().getObject("VirtualEnvManager").getVirtualenvNames() @@ -1894,20 +1888,46 @@ ) self.__write(s) self.__clientStatement(False) - return elif cmd == "%which": s = self.tr("Current Virtual Environment: '{0}'\n").format( self.__currentVenv ) self.__write(s) self.__clientStatement(False) - return elif ( cmd in ["%quit", "%quit()", "%exit", "%exit()"] and self.__windowed ): # call main window quit() self.vm.quit() - return + elif cmd in ("%hist", "%history") or cmd.startswith( + ("%hist ", "%history ") + ): + cmdList = cmd.split(None, 1) + if len(cmdList) == 2: + try: + histSize = int(cmdList[1]) + except ValueError: + s = self.tr("Error: Argument must be an integer value.\n") + self.__write(s) + self.__clientStatement(False) + return + else: + histSize = None + self.showHistory(histSize) + self.__clientStatement(False) + elif cmd in ("%shist", "%shistory", "%select_history"): + self.selectHistory() + elif cmd in ("%chist", "%chistory", "%clear_history"): + self.clearHistory() + self.__clientStatement(False) + elif cmd == "%help": + self.__showHelp() + self.__clientStatement(False) + else: + s = self.tr("Error: Command '{0}' is not supported.\n").format(cmd) + self.__write(s) + self.__clientStatement(False) + self.setFocus(Qt.FocusReason.OtherFocusReason) else: self.dbs.remoteStatement(self.__getSelectedDebuggerId(), cmd) while self.inCommandExecution: @@ -2455,6 +2475,58 @@ ).format(fpath, str(why)), ) + @pyqtSlot() + def __showHelp(self): + """ + Private slot to show the list of supported special commands (i.e. those + starting with a '%' character. + """ + if self.__helpDialog is None: + helpStr = "<table>" + helpStr += self.tr( + "<tr><td>%restart</td>" + "<td>Kill the shell and start a new one.</td></tr>" + "<tr><td>%clear</td>" + "<td>Clear the display of the shell window.</td></tr>" + "<tr><td>%start [environment]</td>" + "<td>Start a shell for a virtual environment with the given name." + " If no name if given, a default shell is started.</td></tr>" + "<tr><td>%envs<br/>%environments</td>" + "<td>Show a list of known virtual environment names.</td></tr>" + "<tr><td>%which</td>" + "<td>Show the name of the active virtual environment.</td></tr>" + "<tr><td>%hist [n]<br/>%history [n]</td>" + "<td>Show the most recent 'n' entries of the history. If 'n' is" + " not given, show all entries.</td></tr>" + "<tr><td>%shist<br/>%shistory<br/>%select_history</td>" + "<td>Select a command from the history.</td></tr>" + "<tr><td>%chist<br/>%chistory<br/>%clear_history</td>" + "<td>Clear the current history after confirmation.</td></tr>" + "<tr><td>%help</td><td>Show this help text.</td></tr>" + ) + if self.__windowed: + helpStr += self.tr( + "<tr><td>%quit<br/>%quit()<br/>%exit<br/>%exit()</td>" + "<td>Exit the application.</td></tr>" + "</table>" + "<p>These commands are available through the window menus as well." + "</p>" + ) + else: + helpStr += self.tr( + "</table>" + "<p>These commands are available through the context menu as well." + "</p>" + ) + + self.__helpDialog = EricSimpleHelpDialog( + title=self.tr("Shell Special Commands"), + label=self.tr("The shell supports these special commands:"), + helpStr=helpStr, + parent=self, + ) + self.__helpDialog.show() + ################################################################# ## Project Support #################################################################