QScintilla/Shell.py

branch
Py2 comp.
changeset 3056
9986ec0e559a
parent 2677
3d4277929fb3
parent 2940
e9348df06994
child 3057
10516539f238
equal deleted inserted replaced
2911:ce77f0b1ee67 3056:9986ec0e559a
11 11
12 import sys 12 import sys
13 import re 13 import re
14 14
15 from PyQt4.QtCore import pyqtSignal, QFileInfo, Qt, QEvent 15 from PyQt4.QtCore import pyqtSignal, QFileInfo, Qt, QEvent
16 from PyQt4.QtGui import QDialog, QInputDialog, QApplication, QClipboard, QMenu, \ 16 from PyQt4.QtGui import QDialog, QInputDialog, QApplication, QClipboard, \
17 QPalette, QFont, QWidget, QHBoxLayout, QVBoxLayout, QShortcut 17 QMenu, QPalette, QFont, QWidget, QHBoxLayout, QVBoxLayout, QShortcut
18 from PyQt4.Qsci import QsciScintilla 18 from PyQt4.Qsci import QsciScintilla
19 19
20 from E5Gui.E5Application import e5App 20 from E5Gui.E5Application import e5App
21 from E5Gui import E5MessageBox 21 from E5Gui import E5MessageBox
22 22
58 self.__layout.addWidget(self.__shell) 58 self.__layout.addWidget(self.__shell)
59 self.__layout.addWidget(self.__searchWidget) 59 self.__layout.addWidget(self.__searchWidget)
60 60
61 self.__searchWidget.searchNext.connect(self.__shell.searchNext) 61 self.__searchWidget.searchNext.connect(self.__shell.searchNext)
62 self.__searchWidget.searchPrevious.connect(self.__shell.searchPrev) 62 self.__searchWidget.searchPrevious.connect(self.__shell.searchPrev)
63 self.__shell.searchStringFound.connect(self.__searchWidget.searchStringFound) 63 self.__shell.searchStringFound.connect(
64 self.__searchWidget.searchStringFound)
64 65
65 def showFind(self, txt=""): 66 def showFind(self, txt=""):
66 """ 67 """
67 Public method to display the search widget. 68 Public method to display the search widget.
68 69
84 Class implementing a graphical Python shell. 85 Class implementing a graphical Python shell.
85 86
86 A user can enter commands that are executed in the remote 87 A user can enter commands that are executed in the remote
87 Python interpreter. 88 Python interpreter.
88 89
89 @signal searchStringFound(found) emitted to indicate the search result (boolean) 90 @signal searchStringFound(found) emitted to indicate the search
91 result (boolean)
90 """ 92 """
91 searchStringFound = pyqtSignal(bool) 93 searchStringFound = pyqtSignal(bool)
92 94
93 def __init__(self, dbs, vm, parent=None): 95 def __init__(self, dbs, vm, parent=None):
94 """ 96 """
114 self.setWindowTitle(self.trUtf8('Shell')) 116 self.setWindowTitle(self.trUtf8('Shell'))
115 117
116 self.setWhatsThis(self.trUtf8( 118 self.setWhatsThis(self.trUtf8(
117 """<b>The Shell Window</b>""" 119 """<b>The Shell Window</b>"""
118 """<p>This is simply an interpreter running in a window. The""" 120 """<p>This is simply an interpreter running in a window. The"""
119 """ interpreter is the one that is used to run the program being debugged.""" 121 """ interpreter is the one that is used to run the program"""
120 """ This means that you can execute any command while the program""" 122 """ being debugged. This means that you can execute any command"""
121 """ being debugged is running.</p>""" 123 """ while the program being debugged is running.</p>"""
122 """<p>You can use the cursor keys while entering commands. There is also a""" 124 """<p>You can use the cursor keys while entering commands. There"""
123 """ history of commands that can be recalled using the up and down cursor""" 125 """ is also a history of commands that can be recalled using the"""
124 """ keys. Pressing the up or down key after some text has been entered will""" 126 """ up and down cursor keys. Pressing the up or down key after"""
125 """ start an incremental search.</p>""" 127 """ some text has been entered will start an incremental search."""
126 """<p>The shell has some special commands. 'reset' kills the shell""" 128 """</p>"""
127 """ and starts a new one. 'clear' clears the display of the shell window.""" 129 """<p>The shell has some special commands. 'reset' kills the"""
128 """ 'start' is used to switch the shell language and must be followed by""" 130 """ shell and starts a new one. 'clear' clears the display of"""
129 """ a supported language. Supported languages are listed by the 'languages'""" 131 """ the shell window. 'start' is used to switch the shell"""
130 """ command. These commands (except 'languages') are available through the""" 132 """ language and must be followed by a supported language."""
131 """ context menu as well.</p>""" 133 """ Supported languages are listed by the 'languages' command."""
132 """<p>Pressing the Tab key after some text has been entered will show""" 134 """ These commands (except 'languages') are available through"""
133 """ a list of possible commandline completions. The relevant entry may""" 135 """ the context menu as well.</p>"""
134 """ be selected from this list. If only one entry is available, this will""" 136 """<p>Pressing the Tab key after some text has been entered will"""
135 """ inserted automatically.</p>""" 137 """ show a list of possible commandline completions. The"""
136 """<p>In passive debugging mode the shell is only available after the""" 138 """ relevant entry may be selected from this list. If only one"""
137 """ program to be debugged has connected to the IDE until it has finished.""" 139 """ entry is available, this will inserted automatically.</p>"""
138 """ This is indicated by a different prompt and by an indication in the""" 140 """<p>In passive debugging mode the shell is only available"""
139 """ window caption.</p>""" 141 """ after the program to be debugged has connected to the IDE"""
142 """ until it has finished. This is indicated by a different"""
143 """ prompt and by an indication in the window caption.</p>"""
140 )) 144 ))
141 145
142 self.userListActivated.connect(self.__completionListSelected) 146 self.userListActivated.connect(self.__completionListSelected)
143 self.linesChanged.connect(self.__resizeLinenoMargin) 147 self.linesChanged.connect(self.__resizeLinenoMargin)
144 148
333 """ 337 """
334 Private method to configure margin 0. 338 Private method to configure margin 0.
335 """ 339 """
336 # set the settings for all margins 340 # set the settings for all margins
337 self.setMarginsFont(Preferences.getShell("MarginsFont")) 341 self.setMarginsFont(Preferences.getShell("MarginsFont"))
338 self.setMarginsForegroundColor(Preferences.getEditorColour("MarginsForeground")) 342 self.setMarginsForegroundColor(
339 self.setMarginsBackgroundColor(Preferences.getEditorColour("MarginsBackground")) 343 Preferences.getEditorColour("MarginsForeground"))
344 self.setMarginsBackgroundColor(
345 Preferences.getEditorColour("MarginsBackground"))
340 346
341 # set margin 0 settings 347 # set margin 0 settings
342 linenoMargin = Preferences.getShell("LinenoMargin") 348 linenoMargin = Preferences.getShell("LinenoMargin")
343 self.setMarginLineNumbers(0, linenoMargin) 349 self.setMarginLineNumbers(0, linenoMargin)
344 if linenoMargin: 350 if linenoMargin:
457 Preferences.getEditorColour("CallTipsBackground")) 463 Preferences.getEditorColour("CallTipsBackground"))
458 self.setCallTipsVisible(Preferences.getEditor("CallTipsVisible")) 464 self.setCallTipsVisible(Preferences.getEditor("CallTipsVisible"))
459 calltipsStyle = Preferences.getEditor("CallTipsStyle") 465 calltipsStyle = Preferences.getEditor("CallTipsStyle")
460 if calltipsStyle == QsciScintilla.CallTipsNoContext: 466 if calltipsStyle == QsciScintilla.CallTipsNoContext:
461 self.setCallTipsStyle(QsciScintilla.CallTipsNoContext) 467 self.setCallTipsStyle(QsciScintilla.CallTipsNoContext)
462 elif calltipsStyle == QsciScintilla.CallTipsNoAutoCompletionContext: 468 elif calltipsStyle == \
463 self.setCallTipsStyle(QsciScintilla.CallTipsNoAutoCompletionContext) 469 QsciScintilla.CallTipsNoAutoCompletionContext:
470 self.setCallTipsStyle(
471 QsciScintilla.CallTipsNoAutoCompletionContext)
464 else: 472 else:
465 self.setCallTipsStyle(QsciScintilla.CallTipsContext) 473 self.setCallTipsStyle(QsciScintilla.CallTipsContext)
466 else: 474 else:
467 self.setCallTipsStyle(QsciScintilla.CallTipsNone) 475 self.setCallTipsStyle(QsciScintilla.CallTipsNone)
468 476
499 self.__bindLexer(clType) 507 self.__bindLexer(clType)
500 self.__setTextDisplay() 508 self.__setTextDisplay()
501 self.__setMargin0() 509 self.__setMargin0()
502 self.__setAutoCompletion(clType) 510 self.__setAutoCompletion(clType)
503 self.__setCallTips(clType) 511 self.__setCallTips(clType)
504 self.racEnabled = Preferences.getShell("AutoCompletionEnabled") and \ 512 self.racEnabled = \
505 (cap & HasCompleter) > 0 513 Preferences.getShell("AutoCompletionEnabled") and \
514 (cap & HasCompleter) > 0
506 515
507 if clType not in self.historyLists: 516 if clType not in self.historyLists:
508 # load history list 517 # load history list
509 self.loadHistory(clType) 518 self.loadHistory(clType)
510 self.history = self.historyLists[clType] 519 self.history = self.historyLists[clType]
522 else: 531 else:
523 self.historyLists[clientType] = [] 532 self.historyLists[clientType] = []
524 533
525 def reloadHistory(self): 534 def reloadHistory(self):
526 """ 535 """
527 Public method to reload the history of the currently selected client type. 536 Public method to reload the history of the currently selected client
537 type.
528 """ 538 """
529 self.loadHistory(self.clientType) 539 self.loadHistory(self.clientType)
530 self.history = self.historyLists[self.clientType] 540 self.history = self.historyLists[self.clientType]
531 self.histidx = -1 541 self.histidx = -1
532 542
566 Private slot to select a history entry to execute. 576 Private slot to select a history entry to execute.
567 """ 577 """
568 cmd, ok = QInputDialog.getItem( 578 cmd, ok = QInputDialog.getItem(
569 self, 579 self,
570 self.trUtf8("Select History"), 580 self.trUtf8("Select History"),
571 self.trUtf8("Select the history entry to execute (most recent shown last)."), 581 self.trUtf8("Select the history entry to execute"
582 " (most recent shown last)."),
572 self.history, 583 self.history,
573 0, False) 584 0, False)
574 if ok: 585 if ok:
575 self.__insertHistory(cmd) 586 self.__insertHistory(cmd)
576 587
702 self.inRawMode = True 713 self.inRawMode = True
703 self.echoInput = echo 714 self.echoInput = echo
704 self.__write(s) 715 self.__write(s)
705 line, col = self.__getEndPos() 716 line, col = self.__getEndPos()
706 self.setCursorPosition(line, col) 717 self.setCursorPosition(line, col)
707 self.prompt = self.text(line)\ 718 buf = self.text(line)
708 .replace(sys.ps1, "").replace(sys.ps2, "") 719 if buf.startswith(sys.ps1):
720 buf = buf.replace(sys.ps1, "")
721 if buf.startswith(sys.ps2):
722 buf = buf.replace(sys.ps2, "")
723 self.prompt = buf
709 # move cursor to end of line 724 # move cursor to end of line
710 self.moveCursorToEOL() 725 self.moveCursorToEOL()
711 726
712 def paste(self): 727 def paste(self):
713 """ 728 """
782 self.insert(s) 797 self.insert(s)
783 self.prline, self.prcol = self.getCursorPosition() 798 self.prline, self.prcol = self.getCursorPosition()
784 799
785 def __insertTextNoEcho(self, s): 800 def __insertTextNoEcho(self, s):
786 """ 801 """
787 Private method to insert some text at the end of the buffer without echoing it. 802 Private method to insert some text at the end of the buffer without
803 echoing it.
788 804
789 @param s text to be inserted (string) 805 @param s text to be inserted (string)
790 """ 806 """
791 self.buff += s 807 self.buff += s
792 self.prline, self.prcol = self.getCursorPosition() 808 self.prline, self.prcol = self.getCursorPosition()
908 """ 924 """
909 if self.isListActive(): 925 if self.isListActive():
910 self.SendScintilla(cmd) 926 self.SendScintilla(cmd)
911 elif self.__isCursorOnLastLine(): 927 elif self.__isCursorOnLastLine():
912 line, index = self.getCursorPosition() 928 line, index = self.getCursorPosition()
913 buf = self.text(line).replace(sys.ps1, "").replace(sys.ps2, "") 929 buf = self.text(line)
930 if buf.startswith(sys.ps1):
931 buf = buf.replace(sys.ps1, "")
932 if buf.startswith(sys.ps2):
933 buf = buf.replace(sys.ps2, "")
914 if self.inContinue and not buf[:index - len(sys.ps2)].strip(): 934 if self.inContinue and not buf[:index - len(sys.ps2)].strip():
915 self.SendScintilla(cmd) 935 self.SendScintilla(cmd)
916 elif self.racEnabled: 936 elif self.racEnabled:
917 self.dbs.remoteCompletion(buf) 937 self.dbs.remoteCompletion(buf)
918 938
919 def __QScintillaLeftDeleteCommand(self, method): 939 def __QScintillaLeftDeleteCommand(self, method):
920 """ 940 """
921 Private method to handle a QScintilla delete command working to the left. 941 Private method to handle a QScintilla delete command working to
942 the left.
922 943
923 @param method shell method to execute 944 @param method shell method to execute
924 """ 945 """
925 if self.__isCursorOnLastLine(): 946 if self.__isCursorOnLastLine():
926 line, col = self.getCursorPosition() 947 line, col = self.getCursorPosition()
1005 else: 1026 else:
1006 self.incrementalSearchString = "" 1027 self.incrementalSearchString = ""
1007 self.incrementalSearchActive = False 1028 self.incrementalSearchActive = False
1008 line, col = self.__getEndPos() 1029 line, col = self.__getEndPos()
1009 self.setCursorPosition(line, col) 1030 self.setCursorPosition(line, col)
1010 buf = self.text(line).replace(sys.ps1, "").replace(sys.ps2, "") 1031 buf = self.text(line)
1032 if buf.startswith(sys.ps1):
1033 buf = buf.replace(sys.ps1, "")
1034 if buf.startswith(sys.ps2):
1035 buf = buf.replace(sys.ps2, "")
1011 self.insert('\n') 1036 self.insert('\n')
1012 self.__executeCommand(buf) 1037 self.__executeCommand(buf)
1013 1038
1014 def __QScintillaLeftCommand(self, method, allLinesAllowed=False): 1039 def __QScintillaLeftCommand(self, method, allLinesAllowed=False):
1015 """ 1040 """
1112 """ 1137 """
1113 if self.isListActive(): 1138 if self.isListActive():
1114 self.SendScintilla(cmd) 1139 self.SendScintilla(cmd)
1115 else: 1140 else:
1116 line, col = self.__getEndPos() 1141 line, col = self.__getEndPos()
1117 buf = self.text(line).replace(sys.ps1, "").replace(sys.ps2, "") 1142 buf = self.text(line)
1143 if buf.startswith(sys.ps1):
1144 buf = buf.replace(sys.ps1, "")
1145 if buf.startswith(sys.ps2):
1146 buf = buf.replace(sys.ps2, "")
1118 if buf and self.incrementalSearchActive: 1147 if buf and self.incrementalSearchActive:
1119 if self.incrementalSearchString: 1148 if self.incrementalSearchString:
1120 idx = self.__rsearchHistory(self.incrementalSearchString, 1149 idx = self.__rsearchHistory(self.incrementalSearchString,
1121 self.histidx) 1150 self.histidx)
1122 if idx >= 0: 1151 if idx >= 0:
1143 """ 1172 """
1144 if self.isListActive(): 1173 if self.isListActive():
1145 self.SendScintilla(cmd) 1174 self.SendScintilla(cmd)
1146 else: 1175 else:
1147 line, col = self.__getEndPos() 1176 line, col = self.__getEndPos()
1148 buf = self.text(line).replace(sys.ps1, "").replace(sys.ps2, "") 1177 buf = self.text(line)
1178 if buf.startswith(sys.ps1):
1179 buf = buf.replace(sys.ps1, "")
1180 if buf.startswith(sys.ps2):
1181 buf = buf.replace(sys.ps2, "")
1149 if buf and self.incrementalSearchActive: 1182 if buf and self.incrementalSearchActive:
1150 if self.incrementalSearchString: 1183 if self.incrementalSearchString:
1151 idx = self.__searchHistory(self.incrementalSearchString, self.histidx) 1184 idx = self.__searchHistory(
1185 self.incrementalSearchString, self.histidx)
1152 if idx >= 0: 1186 if idx >= 0:
1153 self.histidx = idx 1187 self.histidx = idx
1154 self.__useHistory() 1188 self.__useHistory()
1155 else: 1189 else:
1156 idx = self.__searchHistory(buf) 1190 idx = self.__searchHistory(buf)
1231 if language: 1265 if language:
1232 self.dbs.startClient(False, language) 1266 self.dbs.startClient(False, language)
1233 else: 1267 else:
1234 # language not supported or typo 1268 # language not supported or typo
1235 self.__write( 1269 self.__write(
1236 self.trUtf8('Shell language "{0}" not supported.\n')\ 1270 self.trUtf8(
1271 'Shell language "{0}" not supported.\n')
1237 .format(cmdList[1])) 1272 .format(cmdList[1]))
1238 self.__clientStatement(False) 1273 self.__clientStatement(False)
1239 return 1274 return
1240 cmd = '' 1275 cmd = ''
1241 elif cmd == 'languages': 1276 elif cmd == 'languages':
1374 """ 1409 """
1375 self.dbs.startClient(False) 1410 self.dbs.startClient(False)
1376 1411
1377 def __startDebugClient(self, action): 1412 def __startDebugClient(self, action):
1378 """ 1413 """
1379 Private slot to start a debug client accoding to the action triggered[()]. 1414 Private slot to start a debug client according to the action
1415 triggered[()].
1380 1416
1381 @param action context menu action that was triggered (QAction) 1417 @param action context menu action that was triggered (QAction)
1382 """ 1418 """
1383 language = action.data() 1419 language = action.data()
1384 self.dbs.startClient(False, language) 1420 self.dbs.startClient(False, language)
1458 """ 1494 """
1459 Protected method to handle the drag enter event. 1495 Protected method to handle the drag enter event.
1460 1496
1461 @param event the drag enter event (QDragEnterEvent) 1497 @param event the drag enter event (QDragEnterEvent)
1462 """ 1498 """
1463 self.inDragDrop = event.mimeData().hasUrls() or event.mimeData().hasText() 1499 self.inDragDrop = event.mimeData().hasUrls() or \
1500 event.mimeData().hasText()
1464 if self.inDragDrop: 1501 if self.inDragDrop:
1465 event.acceptProposedAction() 1502 event.acceptProposedAction()
1466 else: 1503 else:
1467 super(Shell, self).dragEnterEvent(event) 1504 super(Shell, self).dragEnterEvent(event)
1468 1505
1526 """ 1563 """
1527 if not self.__actionsAdded: 1564 if not self.__actionsAdded:
1528 self.addActions(self.vm.editorActGrp.actions()) 1565 self.addActions(self.vm.editorActGrp.actions())
1529 self.addActions(self.vm.copyActGrp.actions()) 1566 self.addActions(self.vm.copyActGrp.actions())
1530 self.addActions(self.vm.viewActGrp.actions()) 1567 self.addActions(self.vm.viewActGrp.actions())
1531 self.__searchShortcut = QShortcut(self.vm.searchAct.shortcut(), self, 1568 self.__searchShortcut = QShortcut(
1569 self.vm.searchAct.shortcut(), self,
1532 self.__find, self.__find) 1570 self.__find, self.__find)
1533 self.__searchNextShortcut = QShortcut(self.vm.searchNextAct.shortcut(), self, 1571 self.__searchNextShortcut = QShortcut(
1572 self.vm.searchNextAct.shortcut(), self,
1534 self.__searchNext, self.__searchNext) 1573 self.__searchNext, self.__searchNext)
1535 self.__searchPrevShortcut = QShortcut(self.vm.searchPrevAct.shortcut(), self, 1574 self.__searchPrevShortcut = QShortcut(
1575 self.vm.searchPrevAct.shortcut(), self,
1536 self.__searchPrev, self.__searchPrev) 1576 self.__searchPrev, self.__searchPrev)
1537 1577
1538 try: 1578 try:
1539 self.vm.editActGrp.setEnabled(False) 1579 self.vm.editActGrp.setEnabled(False)
1540 self.vm.editorActGrp.setEnabled(True) 1580 self.vm.editorActGrp.setEnabled(True)
1611 search (boolean) 1651 search (boolean)
1612 @param wholeWord flag indicating to search for whole words 1652 @param wholeWord flag indicating to search for whole words
1613 only (boolean) 1653 only (boolean)
1614 """ 1654 """
1615 self.__lastSearch = (txt, caseSensitive, wholeWord) 1655 self.__lastSearch = (txt, caseSensitive, wholeWord)
1616 ok = self.findFirst(txt, False, caseSensitive, wholeWord, False, forward=True) 1656 ok = self.findFirst(txt, False, caseSensitive, wholeWord, False,
1657 forward=True)
1617 self.searchStringFound.emit(ok) 1658 self.searchStringFound.emit(ok)
1618 1659
1619 def __searchPrev(self): 1660 def __searchPrev(self):
1620 """ 1661 """
1621 Private method to search for the next occurrence. 1662 Private method to search for the next occurrence.
1636 self.__lastSearch = (txt, caseSensitive, wholeWord) 1677 self.__lastSearch = (txt, caseSensitive, wholeWord)
1637 if self.hasSelectedText(): 1678 if self.hasSelectedText():
1638 line, index = self.getSelection()[:2] 1679 line, index = self.getSelection()[:2]
1639 else: 1680 else:
1640 line, index = -1, -1 1681 line, index = -1, -1
1641 ok = self.findFirst(txt, False, caseSensitive, wholeWord, False, forward=False, 1682 ok = self.findFirst(txt, False, caseSensitive, wholeWord, False,
1683 forward=False,
1642 line=line, index=index) 1684 line=line, index=index)
1643 self.searchStringFound.emit(ok) 1685 self.searchStringFound.emit(ok)

eric ide

mercurial