QScintilla/Shell.py

branch
maintenance
changeset 5730
6422afc7adc4
parent 5680
b93cb6353cc0
parent 5712
f0d08bdeacf4
child 5752
1860eca908e4
--- a/QScintilla/Shell.py	Sun Apr 09 16:52:55 2017 +0200
+++ b/QScintilla/Shell.py	Sat May 06 13:43:21 2017 +0200
@@ -47,7 +47,7 @@
         """
         super(ShellAssembly, self).__init__(parent)
         
-        self.__shell = Shell(dbs, vm, self)
+        self.__shell = Shell(dbs, vm, False, self)
         
         from UI.SearchWidget import SearchWidget
         self.__searchWidget = SearchWidget(self.__shell, self, horizontal)
@@ -95,12 +95,14 @@
     """
     searchStringFound = pyqtSignal(bool)
     
-    def __init__(self, dbs, vm, parent=None):
+    def __init__(self, dbs, vm, windowedVariant, parent=None):
         """
         Constructor
         
         @param dbs reference to the debug server object
         @param vm reference to the viewmanager object
+        @param windowedVariant flag indicating the shell window variant
+            (boolean)
         @param parent parent widget (QWidget)
         """
         super(Shell, self).__init__(parent)
@@ -109,47 +111,75 @@
         self.vm = vm
         self.__mainWindow = parent
         self.__lastSearch = ()
+        self.__windowed = windowedVariant
         
         self.linesepRegExp = r"\r\n|\n|\r"
         
-        self.passive = Preferences.getDebugger("PassiveDbgEnabled")
+        self.passive = ((not self.__windowed) and
+                        Preferences.getDebugger("PassiveDbgEnabled"))
         if self.passive:
             self.setWindowTitle(self.tr('Shell - Passive'))
         else:
             self.setWindowTitle(self.tr('Shell'))
         
-        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. Pressing the up or down key after"""
-            """ some text has been entered will start an incremental search."""
-            """</p>"""
-            """<p>The shell has some special commands. 'reset' kills the"""
-            """ shell and starts a new one. 'clear' clears the display of"""
-            """ the shell window. 'start' is used to switch the shell"""
-            """ language and must be followed by a supported language."""
-            """ Supported languages are listed by the 'languages' command."""
-            """ These commands (except 'languages') 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 commandline completions. The"""
-            """ relevant entry may be selected from this list. If only one"""
-            """ entry is available, this will 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>"""
-        ))
+        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. Pressing the up or"""
+                """ down key after some text has been entered will start an"""
+                """ incremental search.</p>"""
+                """<p>The shell has some special commands. 'reset' kills the"""
+                """ shell and starts a new one. 'clear' clears the display"""
+                """ of the shell window. 'start' is used to switch the shell"""
+                """ language and must be followed by a supported language."""
+                """ Supported languages are listed by the 'languages'"""
+                """ command. 'quit' is used to exit the application.These"""
+                """ commands (except 'languages') 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. Pressing the up or"""
+                """ down key after some text has been entered will start an"""
+                """ incremental search.</p>"""
+                """<p>The shell has some special commands. 'reset' kills the"""
+                """ shell and starts a new one. 'clear' clears the display"""
+                """ of the shell window. 'start' is used to switch the shell"""
+                """ language and must be followed by a supported language."""
+                """ Supported languages are listed by the 'languages'"""
+                """ command. These commands (except 'languages') 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)
         
-        self.__showStdOutErr = Preferences.getShell("ShowStdOutErr")
+        if self.__windowed:
+            self.__showStdOutErr = True
+        else:
+            self.__showStdOutErr = Preferences.getShell("ShowStdOutErr")
         if self.__showStdOutErr:
             dbs.clientProcessStdout.connect(self.__writeStdOut)
             dbs.clientProcessStderr.connect(self.__writeStdErr)
@@ -206,34 +236,35 @@
         if self.passive:
             self.__getBanner()
         
-        # Create a little language context menu
-        self.lmenu = QMenu(self.tr('Start'))
-        self.lmenu.aboutToShow.connect(self.__showLanguageMenu)
-        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)
-        
-        # 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.addMenu(self.hmenu)
-        self.menu.addSeparator()
-        self.menu.addAction(self.tr('Find'), self.__find)
-        self.menu.addSeparator()
-        self.menu.addAction(self.tr('Clear'), self.clear)
-        self.menu.addAction(self.tr('Reset'), self.__reset)
-        self.menu.addAction(
-            self.tr('Reset and Clear'), self.__resetAndClear)
-        self.menu.addSeparator()
-        self.menu.addMenu(self.lmenu)
-        self.menu.addSeparator()
-        self.menu.addAction(self.tr("Configure..."), self.__configure)
+        if not self.__windowed:
+            # Create a little language context menu
+            self.lmenu = QMenu(self.tr('Start'))
+            self.lmenu.aboutToShow.connect(self.__showLanguageMenu)
+            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)
+            
+            # 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.addMenu(self.hmenu)
+            self.menu.addSeparator()
+            self.menu.addAction(self.tr('Find'), self.__find)
+            self.menu.addSeparator()
+            self.menu.addAction(self.tr('Clear'), self.clear)
+            self.menu.addAction(self.tr('Reset'), self.__reset)
+            self.menu.addAction(
+                self.tr('Reset and Clear'), self.__resetAndClear)
+            self.menu.addSeparator()
+            self.menu.addMenu(self.lmenu)
+            self.menu.addSeparator()
+            self.menu.addAction(self.tr("Configure..."), self.__configure)
         
         self.__bindLexer()
         self.__setTextDisplay()
@@ -266,8 +297,10 @@
             QsciScintilla.SCI_WORDRIGHT: self.__QScintillaWordRight,
             QsciScintilla.SCI_VCHOME: self.__QScintillaVCHome,
             QsciScintilla.SCI_LINEEND: self.__QScintillaLineEnd,
-            QsciScintilla.SCI_LINEUP: self.__QScintillaLineUp,
-            QsciScintilla.SCI_LINEDOWN: self.__QScintillaLineDown,
+            QsciScintilla.SCI_LINEUP: self.__QScintillaCommand,
+            QsciScintilla.SCI_LINEDOWN: self.__QScintillaCommand,
+            QsciScintilla.SCI_LINESCROLLUP: self.__QScintillaHistoryUp,
+            QsciScintilla.SCI_LINESCROLLDOWN: self.__QScintillaHistoryDown,
             
             QsciScintilla.SCI_PAGEUP: self.__QScintillaAutoCompletionCommand,
             QsciScintilla.SCI_PAGEDOWN: self.__QScintillaAutoCompletionCommand,
@@ -577,9 +610,9 @@
         else:
             return []
         
-    def __clearHistory(self):
+    def clearHistory(self):
         """
-        Private slot to clear the current history.
+        Public slot to clear the current history.
         """
         if self.clientType:
             self.historyLists[self.clientType] = []
@@ -588,9 +621,9 @@
             self.history = []
         self.histidx = -1
         
-    def __selectHistory(self):
+    def selectHistory(self):
         """
-        Private slot to select a history entry to execute.
+        Public slot to select a history entry to execute.
         """
         cmd, ok = QInputDialog.getItem(
             self,
@@ -602,9 +635,9 @@
         if ok:
             self.__insertHistory(cmd)
         
-    def __showHistory(self):
+    def showHistory(self):
         """
-        Private slot to show the shell history dialog.
+        Public slot to show the shell history dialog.
         """
         from .ShellHistoryDialog import ShellHistoryDialog
         dlg = ShellHistoryDialog(self.history, self.vm, self)
@@ -623,7 +656,7 @@
             self.saveHistory(clientType)
         Preferences.Prefs.settings.endGroup()
         
-        self.__clearHistory()
+        self.clearHistory()
         
     def getClientType(self):
         """
@@ -674,6 +707,9 @@
         Private method to write the prompt.
         """
         self.__write(self.inContinue and sys.ps2 or sys.ps1)
+        # little trick to get the cursor position registered within QScintilla
+        self.SendScintilla(QsciScintilla.SCI_CHARLEFT)
+        self.SendScintilla(QsciScintilla.SCI_CHARRIGHT)
         
     def __clientStatement(self, more):
         """
@@ -696,7 +732,8 @@
         """
         self .__clientError()
         
-        if Preferences.getDebugger("ShowExceptionInShell"):
+        if not self.__windowed and \
+           Preferences.getDebugger("ShowExceptionInShell"):
             if exceptionType:
                 if stackTrace:
                     self.__write(
@@ -729,7 +766,8 @@
         """
         self .__clientError()
         
-        if Preferences.getDebugger("ShowExceptionInShell"):
+        if not self.__windowed and \
+           Preferences.getDebugger("ShowExceptionInShell"):
             if message is None:
                 self.__write(self.tr("Unspecified syntax error.\n"))
             else:
@@ -1058,6 +1096,14 @@
         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.
@@ -1177,6 +1223,22 @@
                     buf = buf.replace(sys.ps2, "")
                 self.insert('\n')
                 self.__executeCommand(buf)
+        else:
+            txt = ""
+            line, col = self.getCursorPosition()
+            if self.hasSelectedText():
+                lineFrom, indexFrom, lineTo, indexTo = self.getSelection()
+                if line == lineFrom:
+                    txt = self.text(line)[indexFrom:].rstrip()
+                elif line == lineTo:
+                    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):
         """
@@ -1196,6 +1258,8 @@
                     method()
             elif col > 0:
                 method()
+        else:
+            method()
         
     def __QScintillaCharLeft(self):
         """
@@ -1217,6 +1281,8 @@
         """
         if self.__isCursorOnLastLine():
             method()
+        else:
+            method()
         
     def __QScintillaCharRight(self):
         """
@@ -1271,73 +1337,67 @@
         elif self.__isCursorOnLastLine():
             self.moveCursorToEOL()
         
-    def __QScintillaLineUp(self, cmd):
+    def __QScintillaHistoryUp(self, cmd):
         """
-        Private method to handle the Up key.
+        Private method to handle the Ctrl+Up key.
         
         @param cmd QScintilla command
         """
-        if self.isListActive():
-            self.SendScintilla(cmd)
+        line, col = self.__getEndPos()
+        buf = self.text(line)
+        if buf.startswith(sys.ps1):
+            buf = buf.replace(sys.ps1, "")
+        if buf.startswith(sys.ps2):
+            buf = buf.replace(sys.ps2, "")
+        if buf and self.incrementalSearchActive:
+            if self.incrementalSearchString:
+                idx = self.__rsearchHistory(self.incrementalSearchString,
+                                            self.histidx)
+                if idx >= 0:
+                    self.histidx = idx
+                    self.__useHistory()
+            else:
+                idx = self.__rsearchHistory(buf)
+                if idx >= 0:
+                    self.histidx = idx
+                    self.incrementalSearchString = buf
+                    self.__useHistory()
         else:
-            line, col = self.__getEndPos()
-            buf = self.text(line)
-            if buf.startswith(sys.ps1):
-                buf = buf.replace(sys.ps1, "")
-            if buf.startswith(sys.ps2):
-                buf = buf.replace(sys.ps2, "")
-            if buf and self.incrementalSearchActive:
-                if self.incrementalSearchString:
-                    idx = self.__rsearchHistory(self.incrementalSearchString,
-                                                self.histidx)
-                    if idx >= 0:
-                        self.histidx = idx
-                        self.__useHistory()
-                else:
-                    idx = self.__rsearchHistory(buf)
-                    if idx >= 0:
-                        self.histidx = idx
-                        self.incrementalSearchString = buf
-                        self.__useHistory()
-            else:
-                if self.histidx < 0:
-                    self.histidx = len(self.history)
-                if self.histidx > 0:
-                    self.histidx = self.histidx - 1
-                    self.__useHistory()
+            if self.histidx < 0:
+                self.histidx = len(self.history)
+            if self.histidx > 0:
+                self.histidx = self.histidx - 1
+                self.__useHistory()
         
-    def __QScintillaLineDown(self, cmd):
+    def __QScintillaHistoryDown(self, cmd):
         """
-        Private method to handle the Down key.
+        Private method to handle the Ctrl+Down key.
         
         @param cmd QScintilla command
         """
-        if self.isListActive():
-            self.SendScintilla(cmd)
+        line, col = self.__getEndPos()
+        buf = self.text(line)
+        if buf.startswith(sys.ps1):
+            buf = buf.replace(sys.ps1, "")
+        if buf.startswith(sys.ps2):
+            buf = buf.replace(sys.ps2, "")
+        if buf and self.incrementalSearchActive:
+            if self.incrementalSearchString:
+                idx = self.__searchHistory(
+                    self.incrementalSearchString, self.histidx)
+                if idx >= 0:
+                    self.histidx = idx
+                    self.__useHistory()
+            else:
+                idx = self.__searchHistory(buf)
+                if idx >= 0:
+                    self.histidx = idx
+                    self.incrementalSearchString = buf
+                    self.__useHistory()
         else:
-            line, col = self.__getEndPos()
-            buf = self.text(line)
-            if buf.startswith(sys.ps1):
-                buf = buf.replace(sys.ps1, "")
-            if buf.startswith(sys.ps2):
-                buf = buf.replace(sys.ps2, "")
-            if buf and self.incrementalSearchActive:
-                if self.incrementalSearchString:
-                    idx = self.__searchHistory(
-                        self.incrementalSearchString, self.histidx)
-                    if idx >= 0:
-                        self.histidx = idx
-                        self.__useHistory()
-                else:
-                    idx = self.__searchHistory(buf)
-                    if idx >= 0:
-                        self.histidx = idx
-                        self.incrementalSearchString = buf
-                        self.__useHistory()
-            else:
-                if self.histidx >= 0 and self.histidx < len(self.history):
-                    self.histidx += 1
-                    self.__useHistory()
+            if self.histidx >= 0 and self.histidx < len(self.history):
+                self.histidx += 1
+                self.__useHistory()
         
     def __QScintillaCharLeftExtend(self):
         """
@@ -1436,6 +1496,10 @@
                     return
                 else:
                     cmd = ''
+            elif cmd in ["quit", "quit()"] and self.__windowed:
+                # call main window quit()
+                self.vm.quit()
+                return
             
             self.dbs.remoteStatement(cmd)
             while self.inCommandExecution:
@@ -1534,8 +1598,9 @@
         
         @param ev context menu event (QContextMenuEvent)
         """
-        self.menu.popup(ev.globalPos())
-        ev.accept()
+        if not self.__windowed:
+            self.menu.popup(ev.globalPos())
+            ev.accept()
         
     def clear(self):
         """
@@ -1680,7 +1745,7 @@
         
         @param event the drop event (QDropEvent)
         """
-        if event.mimeData().hasUrls():
+        if event.mimeData().hasUrls() and not self.__windowed:
             for url in event.mimeData().urls():
                 fname = url.toLocalFile()
                 if fname:

eric ide

mercurial