9 |
9 |
10 import sys |
10 import sys |
11 import re |
11 import re |
12 |
12 |
13 from PyQt4.QtCore import pyqtSignal, QFileInfo, Qt, QEvent |
13 from PyQt4.QtCore import pyqtSignal, QFileInfo, Qt, QEvent |
14 from PyQt4.QtGui import QDialog, QInputDialog, QApplication, QClipboard, QMenu, \ |
14 from PyQt4.QtGui import QDialog, QInputDialog, QApplication, QClipboard, \ |
15 QPalette, QFont, QWidget, QHBoxLayout, QVBoxLayout, QShortcut |
15 QMenu, QPalette, QFont, QWidget, QHBoxLayout, QVBoxLayout, QShortcut |
16 from PyQt4.Qsci import QsciScintilla |
16 from PyQt4.Qsci import QsciScintilla |
17 |
17 |
18 from E5Gui.E5Application import e5App |
18 from E5Gui.E5Application import e5App |
19 from E5Gui import E5MessageBox |
19 from E5Gui import E5MessageBox |
20 |
20 |
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 |
147 |
144 self.__showStdOutErr = Preferences.getShell("ShowStdOutErr") |
148 self.__showStdOutErr = Preferences.getShell("ShowStdOutErr") |
323 """ |
327 """ |
324 Private method to configure margin 0. |
328 Private method to configure margin 0. |
325 """ |
329 """ |
326 # set the settings for all margins |
330 # set the settings for all margins |
327 self.setMarginsFont(Preferences.getShell("MarginsFont")) |
331 self.setMarginsFont(Preferences.getShell("MarginsFont")) |
328 self.setMarginsForegroundColor(Preferences.getEditorColour("MarginsForeground")) |
332 self.setMarginsForegroundColor( |
329 self.setMarginsBackgroundColor(Preferences.getEditorColour("MarginsBackground")) |
333 Preferences.getEditorColour("MarginsForeground")) |
|
334 self.setMarginsBackgroundColor( |
|
335 Preferences.getEditorColour("MarginsBackground")) |
330 |
336 |
331 # set margin 0 settings |
337 # set margin 0 settings |
332 linenoMargin = Preferences.getShell("LinenoMargin") |
338 linenoMargin = Preferences.getShell("LinenoMargin") |
333 self.setMarginLineNumbers(0, linenoMargin) |
339 self.setMarginLineNumbers(0, linenoMargin) |
334 if linenoMargin: |
340 if linenoMargin: |
447 Preferences.getEditorColour("CallTipsBackground")) |
453 Preferences.getEditorColour("CallTipsBackground")) |
448 self.setCallTipsVisible(Preferences.getEditor("CallTipsVisible")) |
454 self.setCallTipsVisible(Preferences.getEditor("CallTipsVisible")) |
449 calltipsStyle = Preferences.getEditor("CallTipsStyle") |
455 calltipsStyle = Preferences.getEditor("CallTipsStyle") |
450 if calltipsStyle == QsciScintilla.CallTipsNoContext: |
456 if calltipsStyle == QsciScintilla.CallTipsNoContext: |
451 self.setCallTipsStyle(QsciScintilla.CallTipsNoContext) |
457 self.setCallTipsStyle(QsciScintilla.CallTipsNoContext) |
452 elif calltipsStyle == QsciScintilla.CallTipsNoAutoCompletionContext: |
458 elif calltipsStyle == \ |
453 self.setCallTipsStyle(QsciScintilla.CallTipsNoAutoCompletionContext) |
459 QsciScintilla.CallTipsNoAutoCompletionContext: |
|
460 self.setCallTipsStyle( |
|
461 QsciScintilla.CallTipsNoAutoCompletionContext) |
454 else: |
462 else: |
455 self.setCallTipsStyle(QsciScintilla.CallTipsContext) |
463 self.setCallTipsStyle(QsciScintilla.CallTipsContext) |
456 else: |
464 else: |
457 self.setCallTipsStyle(QsciScintilla.CallTipsNone) |
465 self.setCallTipsStyle(QsciScintilla.CallTipsNone) |
458 |
466 |
489 self.__bindLexer(clType) |
497 self.__bindLexer(clType) |
490 self.__setTextDisplay() |
498 self.__setTextDisplay() |
491 self.__setMargin0() |
499 self.__setMargin0() |
492 self.__setAutoCompletion(clType) |
500 self.__setAutoCompletion(clType) |
493 self.__setCallTips(clType) |
501 self.__setCallTips(clType) |
494 self.racEnabled = Preferences.getShell("AutoCompletionEnabled") and \ |
502 self.racEnabled = \ |
495 (cap & HasCompleter) > 0 |
503 Preferences.getShell("AutoCompletionEnabled") and \ |
|
504 (cap & HasCompleter) > 0 |
496 |
505 |
497 if clType not in self.historyLists: |
506 if clType not in self.historyLists: |
498 # load history list |
507 # load history list |
499 self.loadHistory(clType) |
508 self.loadHistory(clType) |
500 self.history = self.historyLists[clType] |
509 self.history = self.historyLists[clType] |
556 Private slot to select a history entry to execute. |
566 Private slot to select a history entry to execute. |
557 """ |
567 """ |
558 cmd, ok = QInputDialog.getItem( |
568 cmd, ok = QInputDialog.getItem( |
559 self, |
569 self, |
560 self.trUtf8("Select History"), |
570 self.trUtf8("Select History"), |
561 self.trUtf8("Select the history entry to execute (most recent shown last)."), |
571 self.trUtf8("Select the history entry to execute" |
|
572 " (most recent shown last)."), |
562 self.history, |
573 self.history, |
563 0, False) |
574 0, False) |
564 if ok: |
575 if ok: |
565 self.__insertHistory(cmd) |
576 self.__insertHistory(cmd) |
566 |
577 |
691 self.inRawMode = True |
702 self.inRawMode = True |
692 self.echoInput = echo |
703 self.echoInput = echo |
693 self.__write(s) |
704 self.__write(s) |
694 line, col = self.__getEndPos() |
705 line, col = self.__getEndPos() |
695 self.setCursorPosition(line, col) |
706 self.setCursorPosition(line, col) |
696 self.prompt = self.text(line)\ |
707 buf = self.text(line) |
697 .replace(sys.ps1, "").replace(sys.ps2, "") |
708 if buf.startswith(sys.ps1): |
|
709 buf = buf.replace(sys.ps1, "") |
|
710 if buf.startswith(sys.ps2): |
|
711 buf = buf.replace(sys.ps2, "") |
|
712 self.prompt = buf |
698 # move cursor to end of line |
713 # move cursor to end of line |
699 self.moveCursorToEOL() |
714 self.moveCursorToEOL() |
700 |
715 |
701 def paste(self): |
716 def paste(self): |
702 """ |
717 """ |
771 self.insert(s) |
786 self.insert(s) |
772 self.prline, self.prcol = self.getCursorPosition() |
787 self.prline, self.prcol = self.getCursorPosition() |
773 |
788 |
774 def __insertTextNoEcho(self, s): |
789 def __insertTextNoEcho(self, s): |
775 """ |
790 """ |
776 Private method to insert some text at the end of the buffer without echoing it. |
791 Private method to insert some text at the end of the buffer without |
|
792 echoing it. |
777 |
793 |
778 @param s text to be inserted (string) |
794 @param s text to be inserted (string) |
779 """ |
795 """ |
780 self.buff += s |
796 self.buff += s |
781 self.prline, self.prcol = self.getCursorPosition() |
797 self.prline, self.prcol = self.getCursorPosition() |
897 """ |
913 """ |
898 if self.isListActive(): |
914 if self.isListActive(): |
899 self.SendScintilla(cmd) |
915 self.SendScintilla(cmd) |
900 elif self.__isCursorOnLastLine(): |
916 elif self.__isCursorOnLastLine(): |
901 line, index = self.getCursorPosition() |
917 line, index = self.getCursorPosition() |
902 buf = self.text(line).replace(sys.ps1, "").replace(sys.ps2, "") |
918 buf = self.text(line) |
|
919 if buf.startswith(sys.ps1): |
|
920 buf = buf.replace(sys.ps1, "") |
|
921 if buf.startswith(sys.ps2): |
|
922 buf = buf.replace(sys.ps2, "") |
903 if self.inContinue and not buf[:index - len(sys.ps2)].strip(): |
923 if self.inContinue and not buf[:index - len(sys.ps2)].strip(): |
904 self.SendScintilla(cmd) |
924 self.SendScintilla(cmd) |
905 elif self.racEnabled: |
925 elif self.racEnabled: |
906 self.dbs.remoteCompletion(buf) |
926 self.dbs.remoteCompletion(buf) |
907 |
927 |
908 def __QScintillaLeftDeleteCommand(self, method): |
928 def __QScintillaLeftDeleteCommand(self, method): |
909 """ |
929 """ |
910 Private method to handle a QScintilla delete command working to the left. |
930 Private method to handle a QScintilla delete command working to |
|
931 the left. |
911 |
932 |
912 @param method shell method to execute |
933 @param method shell method to execute |
913 """ |
934 """ |
914 if self.__isCursorOnLastLine(): |
935 if self.__isCursorOnLastLine(): |
915 line, col = self.getCursorPosition() |
936 line, col = self.getCursorPosition() |
994 else: |
1015 else: |
995 self.incrementalSearchString = "" |
1016 self.incrementalSearchString = "" |
996 self.incrementalSearchActive = False |
1017 self.incrementalSearchActive = False |
997 line, col = self.__getEndPos() |
1018 line, col = self.__getEndPos() |
998 self.setCursorPosition(line, col) |
1019 self.setCursorPosition(line, col) |
999 buf = self.text(line).replace(sys.ps1, "").replace(sys.ps2, "") |
1020 buf = self.text(line) |
|
1021 if buf.startswith(sys.ps1): |
|
1022 buf = buf.replace(sys.ps1, "") |
|
1023 if buf.startswith(sys.ps2): |
|
1024 buf = buf.replace(sys.ps2, "") |
1000 self.insert('\n') |
1025 self.insert('\n') |
1001 self.__executeCommand(buf) |
1026 self.__executeCommand(buf) |
1002 |
1027 |
1003 def __QScintillaLeftCommand(self, method, allLinesAllowed=False): |
1028 def __QScintillaLeftCommand(self, method, allLinesAllowed=False): |
1004 """ |
1029 """ |
1101 """ |
1126 """ |
1102 if self.isListActive(): |
1127 if self.isListActive(): |
1103 self.SendScintilla(cmd) |
1128 self.SendScintilla(cmd) |
1104 else: |
1129 else: |
1105 line, col = self.__getEndPos() |
1130 line, col = self.__getEndPos() |
1106 buf = self.text(line).replace(sys.ps1, "").replace(sys.ps2, "") |
1131 buf = self.text(line) |
|
1132 if buf.startswith(sys.ps1): |
|
1133 buf = buf.replace(sys.ps1, "") |
|
1134 if buf.startswith(sys.ps2): |
|
1135 buf = buf.replace(sys.ps2, "") |
1107 if buf and self.incrementalSearchActive: |
1136 if buf and self.incrementalSearchActive: |
1108 if self.incrementalSearchString: |
1137 if self.incrementalSearchString: |
1109 idx = self.__rsearchHistory(self.incrementalSearchString, |
1138 idx = self.__rsearchHistory(self.incrementalSearchString, |
1110 self.histidx) |
1139 self.histidx) |
1111 if idx >= 0: |
1140 if idx >= 0: |
1132 """ |
1161 """ |
1133 if self.isListActive(): |
1162 if self.isListActive(): |
1134 self.SendScintilla(cmd) |
1163 self.SendScintilla(cmd) |
1135 else: |
1164 else: |
1136 line, col = self.__getEndPos() |
1165 line, col = self.__getEndPos() |
1137 buf = self.text(line).replace(sys.ps1, "").replace(sys.ps2, "") |
1166 buf = self.text(line) |
|
1167 if buf.startswith(sys.ps1): |
|
1168 buf = buf.replace(sys.ps1, "") |
|
1169 if buf.startswith(sys.ps2): |
|
1170 buf = buf.replace(sys.ps2, "") |
1138 if buf and self.incrementalSearchActive: |
1171 if buf and self.incrementalSearchActive: |
1139 if self.incrementalSearchString: |
1172 if self.incrementalSearchString: |
1140 idx = self.__searchHistory(self.incrementalSearchString, self.histidx) |
1173 idx = self.__searchHistory( |
|
1174 self.incrementalSearchString, self.histidx) |
1141 if idx >= 0: |
1175 if idx >= 0: |
1142 self.histidx = idx |
1176 self.histidx = idx |
1143 self.__useHistory() |
1177 self.__useHistory() |
1144 else: |
1178 else: |
1145 idx = self.__searchHistory(buf) |
1179 idx = self.__searchHistory(buf) |
1363 """ |
1398 """ |
1364 self.dbs.startClient(False) |
1399 self.dbs.startClient(False) |
1365 |
1400 |
1366 def __startDebugClient(self, action): |
1401 def __startDebugClient(self, action): |
1367 """ |
1402 """ |
1368 Private slot to start a debug client accoding to the action triggered[()]. |
1403 Private slot to start a debug client according to the action |
|
1404 triggered[()]. |
1369 |
1405 |
1370 @param action context menu action that was triggered (QAction) |
1406 @param action context menu action that was triggered (QAction) |
1371 """ |
1407 """ |
1372 language = action.data() |
1408 language = action.data() |
1373 self.dbs.startClient(False, language) |
1409 self.dbs.startClient(False, language) |
1515 """ |
1552 """ |
1516 if not self.__actionsAdded: |
1553 if not self.__actionsAdded: |
1517 self.addActions(self.vm.editorActGrp.actions()) |
1554 self.addActions(self.vm.editorActGrp.actions()) |
1518 self.addActions(self.vm.copyActGrp.actions()) |
1555 self.addActions(self.vm.copyActGrp.actions()) |
1519 self.addActions(self.vm.viewActGrp.actions()) |
1556 self.addActions(self.vm.viewActGrp.actions()) |
1520 self.__searchShortcut = QShortcut(self.vm.searchAct.shortcut(), self, |
1557 self.__searchShortcut = QShortcut( |
|
1558 self.vm.searchAct.shortcut(), self, |
1521 self.__find, self.__find) |
1559 self.__find, self.__find) |
1522 self.__searchNextShortcut = QShortcut(self.vm.searchNextAct.shortcut(), self, |
1560 self.__searchNextShortcut = QShortcut( |
|
1561 self.vm.searchNextAct.shortcut(), self, |
1523 self.__searchNext, self.__searchNext) |
1562 self.__searchNext, self.__searchNext) |
1524 self.__searchPrevShortcut = QShortcut(self.vm.searchPrevAct.shortcut(), self, |
1563 self.__searchPrevShortcut = QShortcut( |
|
1564 self.vm.searchPrevAct.shortcut(), self, |
1525 self.__searchPrev, self.__searchPrev) |
1565 self.__searchPrev, self.__searchPrev) |
1526 |
1566 |
1527 try: |
1567 try: |
1528 self.vm.editActGrp.setEnabled(False) |
1568 self.vm.editActGrp.setEnabled(False) |
1529 self.vm.editorActGrp.setEnabled(True) |
1569 self.vm.editorActGrp.setEnabled(True) |
1600 search (boolean) |
1640 search (boolean) |
1601 @param wholeWord flag indicating to search for whole words |
1641 @param wholeWord flag indicating to search for whole words |
1602 only (boolean) |
1642 only (boolean) |
1603 """ |
1643 """ |
1604 self.__lastSearch = (txt, caseSensitive, wholeWord) |
1644 self.__lastSearch = (txt, caseSensitive, wholeWord) |
1605 ok = self.findFirst(txt, False, caseSensitive, wholeWord, False, forward=True) |
1645 ok = self.findFirst(txt, False, caseSensitive, wholeWord, False, |
|
1646 forward=True) |
1606 self.searchStringFound.emit(ok) |
1647 self.searchStringFound.emit(ok) |
1607 |
1648 |
1608 def __searchPrev(self): |
1649 def __searchPrev(self): |
1609 """ |
1650 """ |
1610 Private method to search for the next occurrence. |
1651 Private method to search for the next occurrence. |
1625 self.__lastSearch = (txt, caseSensitive, wholeWord) |
1666 self.__lastSearch = (txt, caseSensitive, wholeWord) |
1626 if self.hasSelectedText(): |
1667 if self.hasSelectedText(): |
1627 line, index = self.getSelection()[:2] |
1668 line, index = self.getSelection()[:2] |
1628 else: |
1669 else: |
1629 line, index = -1, -1 |
1670 line, index = -1, -1 |
1630 ok = self.findFirst(txt, False, caseSensitive, wholeWord, False, forward=False, |
1671 ok = self.findFirst(txt, False, caseSensitive, wholeWord, False, |
|
1672 forward=False, |
1631 line=line, index=index) |
1673 line=line, index=index) |
1632 self.searchStringFound.emit(ok) |
1674 self.searchStringFound.emit(ok) |