QScintilla/Shell.py

branch
maintenance
changeset 5825
9487c08b6a23
parent 5752
1860eca908e4
parent 5800
c3379bf35654
child 6004
548a9ba8c970
equal deleted inserted replaced
5790:6411ee48fe91 5825:9487c08b6a23
9 9
10 from __future__ import unicode_literals 10 from __future__ import unicode_literals
11 11
12 import sys 12 import sys
13 import re 13 import re
14
15 try:
16 from enum import Enum
17 except ImportError:
18 from ThirdParty.enum import Enum
14 19
15 from PyQt5.QtCore import pyqtSignal, QFileInfo, Qt, QEvent 20 from PyQt5.QtCore import pyqtSignal, QFileInfo, Qt, QEvent
16 from PyQt5.QtGui import QClipboard, QPalette, QFont 21 from PyQt5.QtGui import QClipboard, QPalette, QFont
17 from PyQt5.QtWidgets import QDialog, QInputDialog, QApplication, QMenu, \ 22 from PyQt5.QtWidgets import QDialog, QInputDialog, QApplication, QMenu, \
18 QWidget, QHBoxLayout, QVBoxLayout, QShortcut 23 QWidget, QHBoxLayout, QVBoxLayout, QShortcut
81 @return reference to the shell widget (Shell) 86 @return reference to the shell widget (Shell)
82 """ 87 """
83 return self.__shell 88 return self.__shell
84 89
85 90
91 class ShellHistoryStyle(Enum):
92 """
93 Class defining the shell history styles.
94 """
95 Disabled = 0
96 LinuxStyle = 1
97 WindowsStyle = 2
98
99
86 class Shell(QsciScintillaCompat): 100 class Shell(QsciScintillaCompat):
87 """ 101 """
88 Class implementing a graphical Python shell. 102 Class implementing a graphical Python shell.
89 103
90 A user can enter commands that are executed in the remote 104 A user can enter commands that are executed in the remote
91 Python interpreter. 105 Python interpreter.
92 106
93 @signal searchStringFound(found) emitted to indicate the search 107 @signal searchStringFound(bool) emitted to indicate the search
94 result (boolean) 108 result
109 @signal historyStyleChanged(ShellHistoryStyle) emitted to indicate a
110 change of the history style
95 """ 111 """
96 searchStringFound = pyqtSignal(bool) 112 searchStringFound = pyqtSignal(bool)
113 historyStyleChanged = pyqtSignal(ShellHistoryStyle)
97 114
98 def __init__(self, dbs, vm, windowedVariant, parent=None): 115 def __init__(self, dbs, vm, windowedVariant, parent=None):
99 """ 116 """
100 Constructor 117 Constructor
101 118
125 if self.__windowed: 142 if self.__windowed:
126 self.setWhatsThis(self.tr( 143 self.setWhatsThis(self.tr(
127 """<b>The Shell Window</b>""" 144 """<b>The Shell Window</b>"""
128 """<p>You can use the cursor keys while entering commands.""" 145 """<p>You can use the cursor keys while entering commands."""
129 """ There is also a history of commands that can be recalled""" 146 """ There is also a history of commands that can be recalled"""
130 """ using the up and down cursor keys. Pressing the up or""" 147 """ using the up and down cursor keys while holding down the"""
131 """ down key after some text has been entered will start an""" 148 """ Ctrl-key. This can be switched to just the up and down"""
132 """ incremental search.</p>""" 149 """ cursor keys on the Shell page of the configuration"""
150 """ dialog. Pressing these keys after some text has been"""
151 """ entered will start an incremental search.</p>"""
133 """<p>The shell has some special commands. 'reset' kills the""" 152 """<p>The shell has some special commands. 'reset' kills the"""
134 """ shell and starts a new one. 'clear' clears the display""" 153 """ shell and starts a new one. 'clear' clears the display"""
135 """ of the shell window. 'start' is used to switch the shell""" 154 """ of the shell window. 'start' is used to switch the shell"""
136 """ language and must be followed by a supported language.""" 155 """ language and must be followed by a supported language."""
137 """ Supported languages are listed by the 'languages'""" 156 """ Supported languages are listed by the 'languages'"""
150 """ interpreter is the one that is used to run the program""" 169 """ interpreter is the one that is used to run the program"""
151 """ being debugged. This means that you can execute any""" 170 """ being debugged. This means that you can execute any"""
152 """ command while the program being debugged is running.</p>""" 171 """ command while the program being debugged is running.</p>"""
153 """<p>You can use the cursor keys while entering commands.""" 172 """<p>You can use the cursor keys while entering commands."""
154 """ There is also a history of commands that can be recalled""" 173 """ There is also a history of commands that can be recalled"""
155 """ using the up and down cursor keys. Pressing the up or""" 174 """ using the up and down cursor keys while holding down the"""
156 """ down key after some text has been entered will start an""" 175 """ Ctrl-key. This can be switched to just the up and down"""
157 """ incremental search.</p>""" 176 """ cursor keys on the Shell page of the configuration"""
177 """ dialog. Pressing these keys after some text has been"""
178 """ entered will start an incremental search.</p>"""
158 """<p>The shell has some special commands. 'reset' kills the""" 179 """<p>The shell has some special commands. 'reset' kills the"""
159 """ shell and starts a new one. 'clear' clears the display""" 180 """ shell and starts a new one. 'clear' clears the display"""
160 """ of the shell window. 'start' is used to switch the shell""" 181 """ of the shell window. 'start' is used to switch the shell"""
161 """ language and must be followed by a supported language.""" 182 """ language and must be followed by a supported language."""
162 """ Supported languages are listed by the 'languages'""" 183 """ Supported languages are listed by the 'languages'"""
201 self.prcol = 0 222 self.prcol = 0
202 self.inDragDrop = False 223 self.inDragDrop = False
203 self.lexer_ = None 224 self.lexer_ = None
204 self.completionText = "" 225 self.completionText = ""
205 226
227 self.clientType = ''
228
206 # Initialize history 229 # Initialize history
207 self.historyLists = {} 230 self.__historyLists = {}
208 self.maxHistoryEntries = Preferences.getShell("MaxHistoryEntries") 231 self.__maxHistoryEntries = Preferences.getShell("MaxHistoryEntries")
209 self.history = [] 232 self.__historyStyle = Preferences.getShell("HistoryStyle")
210 self.histidx = -1 233 self.__historyWrap = Preferences.getShell("HistoryWrap")
234 self.__history = []
235 self.__setHistoryIndex()
211 # remove obsolete shell histories (Python and Ruby) 236 # remove obsolete shell histories (Python and Ruby)
212 for clientType in ["Python", "Ruby"]: 237 for clientType in ["Python", "Ruby"]:
213 Preferences.Prefs.settings.remove("Shell/Histories/" + clientType) 238 Preferences.Prefs.settings.remove("Shell/Histories/" + clientType)
214
215 self.clientType = ''
216 239
217 # clear QScintilla defined keyboard commands 240 # clear QScintilla defined keyboard commands
218 # we do our own handling through the view manager 241 # we do our own handling through the view manager
219 self.clearAlternateKeys() 242 self.clearAlternateKeys()
220 self.clearKeys() 243 self.clearKeys()
251 # Create a little context menu 274 # Create a little context menu
252 self.menu = QMenu(self) 275 self.menu = QMenu(self)
253 self.menu.addAction(self.tr('Cut'), self.cut) 276 self.menu.addAction(self.tr('Cut'), self.cut)
254 self.menu.addAction(self.tr('Copy'), self.copy) 277 self.menu.addAction(self.tr('Copy'), self.copy)
255 self.menu.addAction(self.tr('Paste'), self.paste) 278 self.menu.addAction(self.tr('Paste'), self.paste)
256 self.menu.addMenu(self.hmenu) 279 self.menu.addMenu(self.hmenu).setEnabled(self.isHistoryEnabled())
280
257 self.menu.addSeparator() 281 self.menu.addSeparator()
258 self.menu.addAction(self.tr('Find'), self.__find) 282 self.menu.addAction(self.tr('Find'), self.__find)
259 self.menu.addSeparator() 283 self.menu.addSeparator()
260 self.menu.addAction(self.tr('Clear'), self.clear) 284 self.menu.addAction(self.tr('Clear'), self.clear)
261 self.menu.addAction(self.tr('Reset'), self.__reset) 285 self.menu.addAction(self.tr('Reset'), self.__reset)
295 QsciScintilla.SCI_CHARRIGHT: self.__QScintillaCharRight, 319 QsciScintilla.SCI_CHARRIGHT: self.__QScintillaCharRight,
296 QsciScintilla.SCI_WORDLEFT: self.__QScintillaWordLeft, 320 QsciScintilla.SCI_WORDLEFT: self.__QScintillaWordLeft,
297 QsciScintilla.SCI_WORDRIGHT: self.__QScintillaWordRight, 321 QsciScintilla.SCI_WORDRIGHT: self.__QScintillaWordRight,
298 QsciScintilla.SCI_VCHOME: self.__QScintillaVCHome, 322 QsciScintilla.SCI_VCHOME: self.__QScintillaVCHome,
299 QsciScintilla.SCI_LINEEND: self.__QScintillaLineEnd, 323 QsciScintilla.SCI_LINEEND: self.__QScintillaLineEnd,
300 QsciScintilla.SCI_LINEUP: self.__QScintillaCommand,
301 QsciScintilla.SCI_LINEDOWN: self.__QScintillaCommand,
302 QsciScintilla.SCI_LINESCROLLUP: self.__QScintillaHistoryUp,
303 QsciScintilla.SCI_LINESCROLLDOWN: self.__QScintillaHistoryDown,
304 324
305 QsciScintilla.SCI_PAGEUP: self.__QScintillaAutoCompletionCommand, 325 QsciScintilla.SCI_PAGEUP: self.__QScintillaAutoCompletionCommand,
306 QsciScintilla.SCI_PAGEDOWN: self.__QScintillaAutoCompletionCommand, 326 QsciScintilla.SCI_PAGEDOWN: self.__QScintillaAutoCompletionCommand,
307 QsciScintilla.SCI_CANCEL: self.__QScintillaAutoCompletionCommand, 327 QsciScintilla.SCI_CANCEL: self.__QScintillaAutoCompletionCommand,
308 328
310 QsciScintilla.SCI_CHARRIGHTEXTEND: self.extendSelectionRight, 330 QsciScintilla.SCI_CHARRIGHTEXTEND: self.extendSelectionRight,
311 QsciScintilla.SCI_WORDLEFTEXTEND: self.__QScintillaWordLeftExtend, 331 QsciScintilla.SCI_WORDLEFTEXTEND: self.__QScintillaWordLeftExtend,
312 QsciScintilla.SCI_WORDRIGHTEXTEND: self.extendSelectionWordRight, 332 QsciScintilla.SCI_WORDRIGHTEXTEND: self.extendSelectionWordRight,
313 QsciScintilla.SCI_VCHOMEEXTEND: self.__QScintillaVCHomeExtend, 333 QsciScintilla.SCI_VCHOMEEXTEND: self.__QScintillaVCHomeExtend,
314 QsciScintilla.SCI_LINEENDEXTEND: self.extendSelectionToEOL, 334 QsciScintilla.SCI_LINEENDEXTEND: self.extendSelectionToEOL,
335
336 QsciScintilla.SCI_CANCEL: self.__QScintillaCancel,
315 } 337 }
338 self.__setupCursorKeys()
316 339
317 self.grabGesture(Qt.PinchGesture) 340 self.grabGesture(Qt.PinchGesture)
318 341
342 def __setupCursorKeys(self):
343 """
344 Private method to setup the cursor up and down mode.
345 """
346 if Preferences.getShell("HistoryNavigateByCursor"):
347 self.supportedEditorCommands.update({
348 QsciScintilla.SCI_LINEUP: self.__QScintillaHistoryUp,
349 QsciScintilla.SCI_LINEDOWN: self.__QScintillaHistoryDown,
350 QsciScintilla.SCI_LINESCROLLUP: self.__QScintillaLineUp,
351 QsciScintilla.SCI_LINESCROLLDOWN: self.__QScintillaLineDown,
352 })
353 else:
354 self.supportedEditorCommands.update({
355 QsciScintilla.SCI_LINEUP: self.__QScintillaLineUp,
356 QsciScintilla.SCI_LINEDOWN: self.__QScintillaLineDown,
357 QsciScintilla.SCI_LINESCROLLUP: self.__QScintillaHistoryUp,
358 QsciScintilla.SCI_LINESCROLLDOWN: self.__QScintillaHistoryDown,
359 })
360
319 def __showLanguageMenu(self): 361 def __showLanguageMenu(self):
320 """ 362 """
321 Private slot to prepare the language submenu. 363 Private slot to prepare the language submenu.
322 """ 364 """
323 self.lmenu.clear() 365 self.lmenu.clear()
336 378
337 def closeShell(self): 379 def closeShell(self):
338 """ 380 """
339 Public method to shutdown the shell. 381 Public method to shutdown the shell.
340 """ 382 """
341 for clientType in self.historyLists: 383 for clientType in self.__historyLists:
342 self.saveHistory(clientType) 384 self.saveHistory(clientType)
343 385
344 def __bindLexer(self, language='Python3'): 386 def __bindLexer(self, language='Python3'):
345 """ 387 """
346 Private slot to set the lexer. 388 Private slot to set the lexer.
547 @param clType type of the debug client (string) 589 @param clType type of the debug client (string)
548 """ 590 """
549 self.clientCapabilities = cap 591 self.clientCapabilities = cap
550 if clType != self.clientType: 592 if clType != self.clientType:
551 self.clientType = clType 593 self.clientType = clType
552 self.__bindLexer(clType) 594 self.__bindLexer(self.clientType)
553 self.__setTextDisplay() 595 self.__setTextDisplay()
554 self.__setMargin0() 596 self.__setMargin0()
555 self.__setAutoCompletion(clType) 597 self.__setAutoCompletion(self.clientType)
556 self.__setCallTips(clType) 598 self.__setCallTips(self.clientType)
557 self.racEnabled = \ 599 self.racEnabled = \
558 Preferences.getShell("AutoCompletionEnabled") and \ 600 Preferences.getShell("AutoCompletionEnabled") and \
559 (cap & HasCompleter) > 0 601 (cap & HasCompleter) > 0
560 602
561 if clType not in self.historyLists: 603 if self.clientType not in self.__historyLists:
562 # load history list 604 # load history list
563 self.loadHistory(clType) 605 self.loadHistory(self.clientType)
564 self.history = self.historyLists[clType] 606 self.__history = self.__historyLists[self.clientType]
565 self.histidx = -1 607 self.__setHistoryIndex()
566 608
609 def __setHistoryIndex(self, index=None):
610 """
611 Private method to set the initial history index.
612
613 @param index index value to be set
614 @type int or None
615 """
616 if index is None:
617 # determine based on history style
618 if self.clientType and \
619 self.__historyStyle == ShellHistoryStyle.WindowsStyle:
620 idx = int(Preferences.Prefs.settings.value(
621 "Shell/HistoryIndexes/" + self.clientType, -1))
622 if idx >= len(self.__history):
623 idx = -1
624 self.__histidx = idx
625 else:
626 self.__histidx = -1
627 else:
628 self.__histidx = index
629 if self.__histidx >= len(self.__history):
630 self.__histidx = -1
631 if self.clientType and \
632 self.__historyStyle == ShellHistoryStyle.WindowsStyle:
633 Preferences.Prefs.settings.setValue(
634 "Shell/HistoryIndexes/" + self.clientType, self.__histidx)
635
636 def __isHistoryIndexValid(self):
637 """
638 Private method to test, if the history index is valid.
639
640 @return flag indicating validity
641 @rtype bool
642 """
643 return (0 <= self.__histidx < len(self.__history))
644
645 def getHistoryIndex(self):
646 """
647 Public method to get the current value of the history index.
648
649 @return history index
650 @rtype int
651 """
652 return self.__histidx
653
567 def loadHistory(self, clientType): 654 def loadHistory(self, clientType):
568 """ 655 """
569 Public method to load the history for the given client type. 656 Public method to load the history for the given client type.
570 657
571 @param clientType type of the debug client (string) 658 @param clientType type of the debug client (string)
572 """ 659 """
573 hl = Preferences.Prefs.settings.value("Shell/Histories/" + clientType) 660 hl = Preferences.Prefs.settings.value("Shell/Histories/" + clientType)
574 if hl is not None: 661 if hl is not None:
575 self.historyLists[clientType] = hl[-self.maxHistoryEntries:] 662 self.__historyLists[clientType] = hl[-self.__maxHistoryEntries:]
576 else: 663 else:
577 self.historyLists[clientType] = [] 664 self.__historyLists[clientType] = []
578 665
579 def reloadHistory(self): 666 def reloadHistory(self):
580 """ 667 """
581 Public method to reload the history of the currently selected client 668 Public method to reload the history of the currently selected client
582 type. 669 type.
583 """ 670 """
584 self.loadHistory(self.clientType) 671 self.loadHistory(self.clientType)
585 self.history = self.historyLists[self.clientType] 672 self.__history = self.__historyLists[self.clientType]
586 self.histidx = -1 673 self.__setHistoryIndex()
587 674
588 def saveHistory(self, clientType): 675 def saveHistory(self, clientType):
589 """ 676 """
590 Public method to save the history for the given client type. 677 Public method to save the history for the given client type.
591 678
592 @param clientType type of the debug client (string) 679 @param clientType type of the debug client (string)
593 """ 680 """
594 if clientType in self.historyLists: 681 if clientType in self.__historyLists:
595 Preferences.Prefs.settings.setValue( 682 Preferences.Prefs.settings.setValue(
596 "Shell/Histories/" + clientType, self.historyLists[clientType]) 683 "Shell/Histories/" + clientType,
684 self.__historyLists[clientType])
597 685
598 def getHistory(self, clientType): 686 def getHistory(self, clientType):
599 """ 687 """
600 Public method to get the history for the given client type. 688 Public method to get the history for the given client type.
601 689
602 @param clientType type of the debug client (string). 690 @param clientType type of the debug client (string).
603 If it is None, the current history is returned. 691 If it is None, the current history is returned.
604 @return reference to the history list (list of strings) 692 @return reference to the history list (list of strings)
605 """ 693 """
606 if clientType is None: 694 if clientType is None:
607 return self.history 695 return self.__history
608 elif clientType in self.historyLists: 696 elif clientType in self.__historyLists:
609 return self.historyLists[clientType] 697 return self.__historyLists[clientType]
610 else: 698 else:
611 return [] 699 return []
612 700
613 def clearHistory(self): 701 def clearHistory(self):
614 """ 702 """
615 Public slot to clear the current history. 703 Public slot to clear the current history.
616 """ 704 """
617 if self.clientType: 705 if self.clientType:
618 self.historyLists[self.clientType] = [] 706 self.__historyLists[self.clientType] = []
619 self.history = self.historyLists[self.clientType] 707 self.__history = self.__historyLists[self.clientType]
620 else: 708 else:
621 self.history = [] 709 self.__history = []
622 self.histidx = -1 710 self.__setHistoryIndex(index=-1)
623 711
624 def selectHistory(self): 712 def selectHistory(self):
625 """ 713 """
626 Public slot to select a history entry to execute. 714 Public slot to select a history entry to execute.
627 """ 715 """
716 current = self.__histidx
717 if current == -1:
718 current = len(self.__history) - 1
628 cmd, ok = QInputDialog.getItem( 719 cmd, ok = QInputDialog.getItem(
629 self, 720 self,
630 self.tr("Select History"), 721 self.tr("Select History"),
631 self.tr("Select the history entry to execute" 722 self.tr("Select the history entry to execute"
632 " (most recent shown last)."), 723 " (most recent shown last)."),
633 self.history, 724 self.__history,
634 0, False) 725 current, False)
635 if ok: 726 if ok:
636 self.__insertHistory(cmd) 727 self.__insertHistory(cmd)
637 728
638 def showHistory(self): 729 def showHistory(self):
639 """ 730 """
640 Public slot to show the shell history dialog. 731 Public slot to show the shell history dialog.
641 """ 732 """
642 from .ShellHistoryDialog import ShellHistoryDialog 733 from .ShellHistoryDialog import ShellHistoryDialog
643 dlg = ShellHistoryDialog(self.history, self.vm, self) 734 dlg = ShellHistoryDialog(self.__history, self.vm, self)
644 if dlg.exec_() == QDialog.Accepted: 735 if dlg.exec_() == QDialog.Accepted:
645 self.historyLists[self.clientType] = dlg.getHistory() 736 self.__historyLists[self.clientType], idx = dlg.getHistory()
646 self.history = self.historyLists[self.clientType] 737 self.__history = self.__historyLists[self.clientType]
647 self.histidx = -1 738 self.__setHistoryIndex(index=idx)
648 739
649 def clearAllHistories(self): 740 def clearAllHistories(self):
650 """ 741 """
651 Public method to clear all available histories and sync them. 742 Public method to clear all available histories and sync them.
652 """ 743 """
653 Preferences.Prefs.settings.beginGroup("Shell/Histories") 744 Preferences.Prefs.settings.beginGroup("Shell/Histories")
654 for clientType in Preferences.Prefs.settings.childKeys(): 745 for clientType in Preferences.Prefs.settings.childKeys():
655 self.historyLists[clientType] = [] 746 self.__historyLists[clientType] = []
656 self.saveHistory(clientType) 747 self.saveHistory(clientType)
657 Preferences.Prefs.settings.endGroup() 748 Preferences.Prefs.settings.endGroup()
658 749
659 self.clearHistory() 750 self.clearHistory()
660 751
903 Private method to handle the middle mouse button press. 994 Private method to handle the middle mouse button press.
904 """ 995 """
905 lines = QApplication.clipboard().text(QClipboard.Selection) 996 lines = QApplication.clipboard().text(QClipboard.Selection)
906 self.executeLines(lines) 997 self.executeLines(lines)
907 998
908 def executeLines(self, lines): 999 def executeLines(self, lines, historyIndex=None):
909 """ 1000 """
910 Public method to execute a set of lines as multiple commands. 1001 Public method to execute a set of lines as multiple commands.
911 1002
912 @param lines multiple lines of text to be executed as single 1003 @param lines multiple lines of text to be executed as
913 commands (string) 1004 single commands
1005 @type str
1006 @param historyIndex history index to be set
1007 @type int
914 """ 1008 """
915 for line in lines.splitlines(True): 1009 for line in lines.splitlines(True):
916 if line.endswith("\r\n"): 1010 if line.endswith("\r\n"):
917 fullline = True 1011 fullline = True
918 cmd = line[:-2] 1012 cmd = line[:-2]
929 if cmd.startswith(sys.ps1): 1023 if cmd.startswith(sys.ps1):
930 cmd = cmd[len(sys.ps1):] 1024 cmd = cmd[len(sys.ps1):]
931 elif cmd.startswith(sys.ps2): 1025 elif cmd.startswith(sys.ps2):
932 cmd = cmd[len(sys.ps2):] 1026 cmd = cmd[len(sys.ps2):]
933 1027
934 self.__executeCommand(cmd) 1028 self.__executeCommand(cmd, historyIndex=historyIndex)
935 if self.interruptCommandExecution: 1029 if self.interruptCommandExecution:
936 self.__executeCommand("") 1030 self.__executeCommand("")
937 break 1031 break
938 1032
939 def __clearCurrentLine(self): 1033 def __clearCurrentLine(self):
1334 """ 1428 """
1335 if self.isListActive(): 1429 if self.isListActive():
1336 self.SendScintilla(cmd) 1430 self.SendScintilla(cmd)
1337 elif self.__isCursorOnLastLine(): 1431 elif self.__isCursorOnLastLine():
1338 self.moveCursorToEOL() 1432 self.moveCursorToEOL()
1339 1433
1434 def __QScintillaLineUp(self, cmd):
1435 """
1436 Private method to handle the cursor up command.
1437
1438 @param cmd QScintilla command
1439 """
1440 self.SendScintilla(QsciScintilla.SCI_LINEUP)
1441
1442 def __QScintillaLineDown(self, cmd):
1443 """
1444 Private method to handle the cursor down command.
1445
1446 @param cmd QScintilla command
1447 """
1448 self.SendScintilla(QsciScintilla.SCI_LINEDOWN)
1449
1340 def __QScintillaHistoryUp(self, cmd): 1450 def __QScintillaHistoryUp(self, cmd):
1341 """ 1451 """
1342 Private method to handle the Ctrl+Up key. 1452 Private method to handle the history up command.
1343 1453
1344 @param cmd QScintilla command 1454 @param cmd QScintilla command
1345 """ 1455 """
1346 line, col = self.__getEndPos() 1456 if self.isHistoryEnabled():
1347 buf = self.text(line) 1457 line, col = self.__getEndPos()
1348 if buf.startswith(sys.ps1): 1458 buf = self.text(line)
1349 buf = buf.replace(sys.ps1, "") 1459 if buf.startswith(sys.ps1):
1350 if buf.startswith(sys.ps2): 1460 buf = buf.replace(sys.ps1, "")
1351 buf = buf.replace(sys.ps2, "") 1461 if buf.startswith(sys.ps2):
1352 if buf and self.incrementalSearchActive: 1462 buf = buf.replace(sys.ps2, "")
1353 if self.incrementalSearchString: 1463 if buf and self.incrementalSearchActive:
1354 idx = self.__rsearchHistory(self.incrementalSearchString, 1464 if self.incrementalSearchString and \
1355 self.histidx) 1465 buf.startswith(self.incrementalSearchString):
1356 if idx >= 0: 1466 idx, found = self.__rsearchHistory(
1357 self.histidx = idx 1467 self.incrementalSearchString, self.__histidx)
1468 if found and idx >= 0:
1469 self.__setHistoryIndex(index=idx)
1470 self.__useHistory()
1471 else:
1472 idx, found = self.__rsearchHistory(buf)
1473 if found and idx >= 0:
1474 self.__setHistoryIndex(index=idx)
1475 self.incrementalSearchString = buf
1476 self.__useHistory()
1477 else:
1478 if self.__historyWrap:
1479 if self.__histidx < 0:
1480 # wrap around
1481 self.__setHistoryIndex(index=len(self.__history) - 1)
1482 else:
1483 self.__setHistoryIndex(index=self.__histidx - 1)
1358 self.__useHistory() 1484 self.__useHistory()
1485 else:
1486 if self.__histidx < 0:
1487 self.__setHistoryIndex(index=len(self.__history) - 1)
1488 self.__useHistory()
1489 elif self.__histidx > 0:
1490 self.__setHistoryIndex(index=self.__histidx - 1)
1491 self.__useHistory()
1492
1493 def __QScintillaHistoryDown(self, cmd):
1494 """
1495 Private method to handle the history down command.
1496
1497 @param cmd QScintilla command
1498 """
1499 if self.isHistoryEnabled():
1500 line, col = self.__getEndPos()
1501 buf = self.text(line)
1502 if buf.startswith(sys.ps1):
1503 buf = buf.replace(sys.ps1, "")
1504 if buf.startswith(sys.ps2):
1505 buf = buf.replace(sys.ps2, "")
1506 if buf and self.incrementalSearchActive:
1507 if self.incrementalSearchString and \
1508 buf.startswith(self.incrementalSearchString):
1509 idx, found = self.__searchHistory(
1510 self.incrementalSearchString, self.__histidx)
1511 if found and idx >= 0:
1512 self.__setHistoryIndex(index=idx)
1513 self.__useHistory()
1514 else:
1515 idx, found = self.__searchHistory(buf)
1516 if found and idx >= 0:
1517 self.__setHistoryIndex(index=idx)
1518 self.incrementalSearchString = buf
1519 self.__useHistory()
1359 else: 1520 else:
1360 idx = self.__rsearchHistory(buf) 1521 if self.__historyWrap:
1361 if idx >= 0: 1522 if self.__histidx >= len(self.__history) - 1:
1362 self.histidx = idx 1523 # wrap around
1363 self.incrementalSearchString = buf 1524 self.__setHistoryIndex(index=0)
1525 else:
1526 self.__setHistoryIndex(index=self.__histidx + 1)
1364 self.__useHistory() 1527 self.__useHistory()
1365 else: 1528 else:
1366 if self.histidx < 0: 1529 if self.__isHistoryIndexValid():
1367 self.histidx = len(self.history) 1530 self.__setHistoryIndex(index=self.__histidx + 1)
1368 if self.histidx > 0: 1531 self.__useHistory()
1369 self.histidx = self.histidx - 1 1532
1370 self.__useHistory() 1533 def __QScintillaCancel(self):
1371 1534 """
1372 def __QScintillaHistoryDown(self, cmd): 1535 Private method to handle the ESC command.
1373 """ 1536 """
1374 Private method to handle the Ctrl+Down key. 1537 if self.incrementalSearchActive:
1375 1538 self.__resetIncrementalHistorySearch()
1376 @param cmd QScintilla command 1539 self.__insertHistory("")
1377 """ 1540
1378 line, col = self.__getEndPos()
1379 buf = self.text(line)
1380 if buf.startswith(sys.ps1):
1381 buf = buf.replace(sys.ps1, "")
1382 if buf.startswith(sys.ps2):
1383 buf = buf.replace(sys.ps2, "")
1384 if buf and self.incrementalSearchActive:
1385 if self.incrementalSearchString:
1386 idx = self.__searchHistory(
1387 self.incrementalSearchString, self.histidx)
1388 if idx >= 0:
1389 self.histidx = idx
1390 self.__useHistory()
1391 else:
1392 idx = self.__searchHistory(buf)
1393 if idx >= 0:
1394 self.histidx = idx
1395 self.incrementalSearchString = buf
1396 self.__useHistory()
1397 else:
1398 if self.histidx >= 0 and self.histidx < len(self.history):
1399 self.histidx += 1
1400 self.__useHistory()
1401
1402 def __QScintillaCharLeftExtend(self): 1541 def __QScintillaCharLeftExtend(self):
1403 """ 1542 """
1404 Private method to handle the Extend Selection Left command. 1543 Private method to handle the Extend Selection Left command.
1405 """ 1544 """
1406 self.__QScintillaLeftCommand(self.extendSelectionLeft, True) 1545 self.__QScintillaLeftCommand(self.extendSelectionLeft, True)
1435 @param cmd QScintilla command 1574 @param cmd QScintilla command
1436 """ 1575 """
1437 if self.isListActive() or self.isCallTipActive(): 1576 if self.isListActive() or self.isCallTipActive():
1438 self.SendScintilla(cmd) 1577 self.SendScintilla(cmd)
1439 1578
1440 def __executeCommand(self, cmd): 1579 def __executeCommand(self, cmd, historyIndex=None):
1441 """ 1580 """
1442 Private slot to execute a command. 1581 Private slot to execute a command.
1443 1582
1444 @param cmd command to be executed by debug client (string) 1583 @param cmd command to be executed by debug client
1584 @type str
1585 @param historyIndex history index to be set
1586 @type int
1445 """ 1587 """
1446 if not self.inRawMode: 1588 if not self.inRawMode:
1447 self.inCommandExecution = True 1589 self.inCommandExecution = True
1448 self.interruptCommandExecution = False 1590 self.interruptCommandExecution = False
1449 if not cmd: 1591 if not cmd:
1592 # make sure cmd is a string
1450 cmd = '' 1593 cmd = ''
1451 if len(self.history) == 0 or self.history[-1] != cmd: 1594
1452 if len(self.history) == self.maxHistoryEntries: 1595 # History Handling
1453 del self.history[0] 1596 if self.isHistoryEnabled():
1454 self.history.append(cmd) 1597 if cmd != "" and (
1455 self.histidx = -1 1598 len(self.__history) == 0 or self.__history[-1] != cmd):
1599 if len(self.__history) == self.__maxHistoryEntries:
1600 del self.__history[0]
1601 self.__history.append(cmd)
1602 if self.__historyStyle == ShellHistoryStyle.LinuxStyle:
1603 self.__setHistoryIndex(index=-1)
1604 elif self.__historyStyle == ShellHistoryStyle.WindowsStyle:
1605 if historyIndex is None:
1606 if cmd != self.__history[self.__histidx - 1]:
1607 self.__setHistoryIndex(index=-1)
1608 else:
1609 self.__setHistoryIndex(historyIndex)
1610
1456 if cmd.startswith('start '): 1611 if cmd.startswith('start '):
1457 if not self.passive: 1612 if not self.passive:
1458 cmdList = cmd.split(None, 1) 1613 cmdList = cmd.split(None, 1)
1459 if len(cmdList) < 2: 1614 if len(cmdList) < 2:
1460 self.dbs.startClient(False) # same as reset 1615 self.dbs.startClient(False) # same as reset
1520 1675
1521 def __useHistory(self): 1676 def __useHistory(self):
1522 """ 1677 """
1523 Private method to display a command from the history. 1678 Private method to display a command from the history.
1524 """ 1679 """
1525 if self.histidx < len(self.history): 1680 if self.__isHistoryIndexValid():
1526 cmd = self.history[self.histidx] 1681 cmd = self.__history[self.__histidx]
1527 else: 1682 else:
1528 cmd = "" 1683 cmd = ""
1529 self.incrementalSearchString = "" 1684 self.__resetIncrementalHistorySearch()
1530 self.incrementalSearchActive = False
1531 1685
1532 self.__insertHistory(cmd) 1686 self.__insertHistory(cmd)
1533 1687
1534 def __insertHistory(self, cmd): 1688 def __insertHistory(self, cmd):
1535 """ 1689 """
1540 self.setCursorPosition(self.prline, self.prcol) 1694 self.setCursorPosition(self.prline, self.prcol)
1541 self.setSelection(self.prline, self.prcol, 1695 self.setSelection(self.prline, self.prcol,
1542 self.prline, self.lineLength(self.prline)) 1696 self.prline, self.lineLength(self.prline))
1543 self.removeSelectedText() 1697 self.removeSelectedText()
1544 self.__insertText(cmd) 1698 self.__insertText(cmd)
1545 1699
1700 def __resetIncrementalHistorySearch(self):
1701 """
1702 Private method to reset the incremental history search.
1703 """
1704 self.incrementalSearchString = ""
1705 self.incrementalSearchActive = False
1706
1546 def __searchHistory(self, txt, startIdx=-1): 1707 def __searchHistory(self, txt, startIdx=-1):
1547 """ 1708 """
1548 Private method used to search the history. 1709 Private method used to search the history.
1549 1710
1550 @param txt text to match at the beginning (string) 1711 @param txt text to match at the beginning
1551 @param startIdx index to start search from (integer) 1712 @type str
1552 @return index of found entry (integer) 1713 @param startIdx index to start search from
1714 @type int
1715 @return tuple containing the index of found entry and a flag indicating
1716 that something was found
1717 @rtype tuple of (int, bool)
1553 """ 1718 """
1554 if startIdx == -1: 1719 if startIdx == -1:
1555 idx = 0 1720 idx = 0
1556 else: 1721 else:
1557 idx = startIdx + 1 1722 idx = startIdx + 1
1558 while idx < len(self.history) and \ 1723 while idx < len(self.__history) and \
1559 not self.history[idx].startswith(txt): 1724 not self.__history[idx].startswith(txt):
1560 idx += 1 1725 idx += 1
1561 return idx 1726 found = (idx < len(self.__history) and
1727 self.__history[idx].startswith(txt))
1728 return idx, found
1562 1729
1563 def __rsearchHistory(self, txt, startIdx=-1): 1730 def __rsearchHistory(self, txt, startIdx=-1):
1564 """ 1731 """
1565 Private method used to reverse search the history. 1732 Private method used to reverse search the history.
1566 1733
1567 @param txt text to match at the beginning (string) 1734 @param txt text to match at the beginning
1568 @param startIdx index to start search from (integer) 1735 @type str
1569 @return index of found entry (integer) 1736 @param startIdx index to start search from
1737 @type int
1738 @return tuple containing the index of found entry and a flag indicating
1739 that something was found
1740 @rtype tuple of (int, bool)
1570 """ 1741 """
1571 if startIdx == -1: 1742 if startIdx == -1:
1572 idx = len(self.history) - 1 1743 idx = len(self.__history) - 1
1573 else: 1744 else:
1574 idx = startIdx - 1 1745 idx = startIdx - 1
1575 while idx >= 0 and \ 1746 while idx >= 0 and \
1576 not self.history[idx].startswith(txt): 1747 not self.__history[idx].startswith(txt):
1577 idx -= 1 1748 idx -= 1
1578 return idx 1749 found = idx >= 0 and self.__history[idx].startswith(txt)
1750 return idx, found
1579 1751
1580 def focusNextPrevChild(self, nextChild): 1752 def focusNextPrevChild(self, nextChild):
1581 """ 1753 """
1582 Public method to stop Tab moving to the next window. 1754 Public method to stop Tab moving to the next window.
1583 1755
1647 # set the autocompletion and calltips function 1819 # set the autocompletion and calltips function
1648 self.__setAutoCompletion() 1820 self.__setAutoCompletion()
1649 self.__setCallTips() 1821 self.__setCallTips()
1650 1822
1651 # do the history related stuff 1823 # do the history related stuff
1652 self.maxHistoryEntries = Preferences.getShell("MaxHistoryEntries") 1824 self.__maxHistoryEntries = Preferences.getShell("MaxHistoryEntries")
1653 for key in list(self.historyLists.keys()): 1825 for key in list(self.__historyLists.keys()):
1654 self.historyLists[key] = \ 1826 self.__historyLists[key] = \
1655 self.historyLists[key][-self.maxHistoryEntries:] 1827 self.__historyLists[key][-self.__maxHistoryEntries:]
1828 self.__historyStyle = Preferences.getShell("HistoryStyle")
1829 self.__historyWrap = Preferences.getShell("HistoryWrap")
1830 self.__setHistoryIndex()
1831 if not self.__windowed:
1832 self.hmenu.menuAction().setEnabled(self.isHistoryEnabled())
1833 self.__setupCursorKeys()
1834 self.historyStyleChanged.emit(self.__historyStyle)
1656 1835
1657 # do stdout /stderr stuff 1836 # do stdout /stderr stuff
1658 showStdOutErr = Preferences.getShell("ShowStdOutErr") 1837 showStdOutErr = Preferences.getShell("ShowStdOutErr")
1659 if self.__showStdOutErr != showStdOutErr: 1838 if self.__showStdOutErr != showStdOutErr:
1660 if showStdOutErr: 1839 if showStdOutErr:
1896 line, index = -1, -1 2075 line, index = -1, -1
1897 ok = self.findFirst( 2076 ok = self.findFirst(
1898 txt, False, caseSensitive, wholeWord, False, 2077 txt, False, caseSensitive, wholeWord, False,
1899 forward=False, line=line, index=index) 2078 forward=False, line=line, index=index)
1900 self.searchStringFound.emit(ok) 2079 self.searchStringFound.emit(ok)
2080
2081 def historyStyle(self):
2082 """
2083 Public method to get the shell history style.
2084
2085 @return shell history style
2086 @rtype ShellHistoryStyle
2087 """
2088 return self.__historyStyle
2089
2090 def isHistoryEnabled(self):
2091 """
2092 Public method to check, if the history is enabled.
2093
2094 @return flag indicating if history is enabled
2095 @rtype bool
2096 """
2097 return self.__historyStyle != ShellHistoryStyle.Disabled

eric ide

mercurial