src/eric7/QScintilla/Shell.py

branch
eric7
changeset 10191
dc47d7d2ff34
parent 10167
0a62a4bf749c
child 10232
fbfb347f7b5b
--- 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
     #################################################################

eric ide

mercurial