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] |
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) |
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) |
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) |