diff -r 9a71bd9e2e37 -r 6422afc7adc4 QScintilla/Shell.py --- 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: