eric6/QScintilla/Shell.py

branch
maintenance
changeset 7286
7eb04391adf7
parent 6989
8b8cadf8d7e9
parent 7267
aedc309827c7
child 7362
028bf21bb5a2
equal deleted inserted replaced
7226:babe80d84a3e 7286:7eb04391adf7
5 5
6 """ 6 """
7 Module implementing a graphical Python shell. 7 Module implementing a graphical Python shell.
8 """ 8 """
9 9
10 from __future__ import unicode_literals
11 10
12 import sys 11 import sys
13 import re 12 import re
14 13
15 try: 14 try:
17 except ImportError: 16 except ImportError:
18 from ThirdParty.enum import Enum 17 from ThirdParty.enum import Enum
19 18
20 from PyQt5.QtCore import pyqtSignal, QFileInfo, Qt, QEvent 19 from PyQt5.QtCore import pyqtSignal, QFileInfo, Qt, QEvent
21 from PyQt5.QtGui import QClipboard, QPalette, QFont 20 from PyQt5.QtGui import QClipboard, QPalette, QFont
22 from PyQt5.QtWidgets import QDialog, QInputDialog, QApplication, QMenu, \ 21 from PyQt5.QtWidgets import (
23 QWidget, QHBoxLayout, QVBoxLayout, QShortcut, QSizePolicy 22 QDialog, QInputDialog, QApplication, QMenu, QWidget, QHBoxLayout,
23 QVBoxLayout, QShortcut, QSizePolicy
24 )
24 from PyQt5.Qsci import QsciScintilla 25 from PyQt5.Qsci import QsciScintilla
25 26
26 from E5Gui.E5Application import e5App 27 from E5Gui.E5Application import e5App
27 from E5Gui import E5MessageBox 28 from E5Gui import E5MessageBox
28 29
29 from .QsciScintillaCompat import QsciScintillaCompat 30 from .QsciScintillaCompat import QsciScintillaCompat
30 31
31 import Preferences 32 import Preferences
32 import Utilities 33 import Utilities
33 from Globals import qVersionTuple
34 34
35 import UI.PixmapCache 35 import UI.PixmapCache
36 36
37 from Debugger.DebugClientCapabilities import HasCompleter 37 from Debugger.DebugClientCapabilities import HasCompleter
38 38
367 QsciScintilla.SCI_LINEENDEXTEND: self.extendSelectionToEOL, 367 QsciScintilla.SCI_LINEENDEXTEND: self.extendSelectionToEOL,
368 368
369 QsciScintilla.SCI_CANCEL: self.__QScintillaCancel, 369 QsciScintilla.SCI_CANCEL: self.__QScintillaCancel,
370 } 370 }
371 371
372 self.__historyNavigateByCursor = \ 372 self.__historyNavigateByCursor = (
373 Preferences.getShell("HistoryNavigateByCursor") 373 Preferences.getShell("HistoryNavigateByCursor")
374 )
374 375
375 self.__queuedText = '' 376 self.__queuedText = ''
376 self.__blockTextProcessing = False 377 self.__blockTextProcessing = False
377 self.queueText.connect(self.__concatenateText, Qt.QueuedConnection) 378 self.queueText.connect(self.__concatenateText, Qt.QueuedConnection)
378 379
582 Preferences.getEditorColour("CallTipsBackground")) 583 Preferences.getEditorColour("CallTipsBackground"))
583 self.setCallTipsVisible(Preferences.getEditor("CallTipsVisible")) 584 self.setCallTipsVisible(Preferences.getEditor("CallTipsVisible"))
584 calltipsStyle = Preferences.getEditor("CallTipsStyle") 585 calltipsStyle = Preferences.getEditor("CallTipsStyle")
585 if calltipsStyle == QsciScintilla.CallTipsNoContext: 586 if calltipsStyle == QsciScintilla.CallTipsNoContext:
586 self.setCallTipsStyle(QsciScintilla.CallTipsNoContext) 587 self.setCallTipsStyle(QsciScintilla.CallTipsNoContext)
587 elif calltipsStyle == \ 588 elif (
588 QsciScintilla.CallTipsNoAutoCompletionContext: 589 calltipsStyle ==
590 QsciScintilla.CallTipsNoAutoCompletionContext
591 ):
589 self.setCallTipsStyle( 592 self.setCallTipsStyle(
590 QsciScintilla.CallTipsNoAutoCompletionContext) 593 QsciScintilla.CallTipsNoAutoCompletionContext)
591 else: 594 else:
592 self.setCallTipsStyle(QsciScintilla.CallTipsContext) 595 self.setCallTipsStyle(QsciScintilla.CallTipsContext)
593 else: 596 else:
631 self.__bindLexer(self.clientType) 634 self.__bindLexer(self.clientType)
632 self.__setTextDisplay() 635 self.__setTextDisplay()
633 self.__setMargin0() 636 self.__setMargin0()
634 self.__setAutoCompletion(self.clientType) 637 self.__setAutoCompletion(self.clientType)
635 self.__setCallTips(self.clientType) 638 self.__setCallTips(self.clientType)
636 self.racEnabled = \ 639 self.racEnabled = (
637 Preferences.getShell("AutoCompletionEnabled") and \ 640 Preferences.getShell("AutoCompletionEnabled") and
638 (cap & HasCompleter) > 0 641 (cap & HasCompleter) > 0
642 )
639 643
640 if self.clientType not in self.__historyLists: 644 if self.clientType not in self.__historyLists:
641 # load history list 645 # load history list
642 self.loadHistory(self.clientType) 646 self.loadHistory(self.clientType)
643 self.__history = self.__historyLists[self.clientType] 647 self.__history = self.__historyLists[self.clientType]
653 @param index index value to be set 657 @param index index value to be set
654 @type int or None 658 @type int or None
655 """ 659 """
656 if index is None: 660 if index is None:
657 # determine based on history style 661 # determine based on history style
658 if self.clientType and \ 662 if (
659 self.__historyStyle == ShellHistoryStyle.WindowsStyle: 663 self.clientType and
664 self.__historyStyle == ShellHistoryStyle.WindowsStyle
665 ):
660 idx = int(Preferences.Prefs.settings.value( 666 idx = int(Preferences.Prefs.settings.value(
661 "Shell/HistoryIndexes/" + self.clientType, -1)) 667 "Shell/HistoryIndexes/" + self.clientType, -1))
662 if idx >= len(self.__history): 668 if idx >= len(self.__history):
663 idx = -1 669 idx = -1
664 self.__histidx = idx 670 self.__histidx = idx
666 self.__histidx = -1 672 self.__histidx = -1
667 else: 673 else:
668 self.__histidx = index 674 self.__histidx = index
669 if self.__histidx >= len(self.__history): 675 if self.__histidx >= len(self.__history):
670 self.__histidx = -1 676 self.__histidx = -1
671 if self.clientType and \ 677 if (
672 self.__historyStyle == ShellHistoryStyle.WindowsStyle: 678 self.clientType and
679 self.__historyStyle == ShellHistoryStyle.WindowsStyle
680 ):
673 Preferences.Prefs.settings.setValue( 681 Preferences.Prefs.settings.setValue(
674 "Shell/HistoryIndexes/" + self.clientType, self.__histidx) 682 "Shell/HistoryIndexes/" + self.clientType, self.__histidx)
675 683
676 def __isHistoryIndexValid(self): 684 def __isHistoryIndexValid(self):
677 """ 685 """
869 @param exceptionMessage message given by the exception (string) 877 @param exceptionMessage message given by the exception (string)
870 @param stackTrace list of stack entries (list of string) 878 @param stackTrace list of stack entries (list of string)
871 """ 879 """
872 self .__clientError() 880 self .__clientError()
873 881
874 if not self.__windowed and \ 882 if (
875 Preferences.getDebugger("ShowExceptionInShell"): 883 not self.__windowed and
884 Preferences.getDebugger("ShowExceptionInShell")
885 ):
876 if exceptionType: 886 if exceptionType:
877 if stackTrace: 887 if stackTrace:
878 self.__write( 888 self.__write(
879 self.tr('Exception "{0}"\n{1}\nFile: {2}, Line: {3}\n') 889 self.tr('Exception "{0}"\n{1}\nFile: {2}, Line: {3}\n')
880 .format( 890 .format(
903 @param characterNo character number of the syntax error position 913 @param characterNo character number of the syntax error position
904 (integer) 914 (integer)
905 """ 915 """
906 self .__clientError() 916 self .__clientError()
907 917
908 if not self.__windowed and \ 918 if (
909 Preferences.getDebugger("ShowExceptionInShell"): 919 not self.__windowed and
920 Preferences.getDebugger("ShowExceptionInShell")
921 ):
910 if message is None: 922 if message is None:
911 self.__write(self.tr("Unspecified syntax error.\n")) 923 self.__write(self.tr("Unspecified syntax error.\n"))
912 else: 924 else:
913 self.__write( 925 self.__write(
914 self.tr('Syntax error "{1}" in file {0} at line {2},' 926 self.tr('Syntax error "{1}" in file {0} at line {2},'
1215 Protected method to handle wheel events. 1227 Protected method to handle wheel events.
1216 1228
1217 @param evt reference to the wheel event (QWheelEvent) 1229 @param evt reference to the wheel event (QWheelEvent)
1218 """ 1230 """
1219 if evt.modifiers() & Qt.ControlModifier: 1231 if evt.modifiers() & Qt.ControlModifier:
1220 if qVersionTuple() >= (5, 0, 0): 1232 delta = evt.angleDelta().y()
1221 delta = evt.angleDelta().y()
1222 else:
1223 delta = evt.delta()
1224 if delta < 0: 1233 if delta < 0:
1225 self.zoomOut() 1234 self.zoomOut()
1226 elif delta > 0: 1235 elif delta > 0:
1227 self.zoomIn() 1236 self.zoomIn()
1228 evt.accept() 1237 evt.accept()
1303 self.prline, self.prcol = self.getCursorPosition() 1312 self.prline, self.prcol = self.getCursorPosition()
1304 if self.echoInput: 1313 if self.echoInput:
1305 ac = self.isListActive() 1314 ac = self.isListActive()
1306 super(Shell, self).keyPressEvent(ev) 1315 super(Shell, self).keyPressEvent(ev)
1307 self.incrementalSearchActive = True 1316 self.incrementalSearchActive = True
1308 if ac and \ 1317 if ac and self.racEnabled:
1309 self.racEnabled:
1310 self.dbs.remoteCompletion(self.completionText + txt) 1318 self.dbs.remoteCompletion(self.completionText + txt)
1311 else: 1319 else:
1312 self.__insertTextNoEcho(txt) 1320 self.__insertTextNoEcho(txt)
1313 else: 1321 else:
1314 ev.ignore() 1322 ev.ignore()
1611 if buf.startswith(sys.ps1): 1619 if buf.startswith(sys.ps1):
1612 buf = buf.replace(sys.ps1, "") 1620 buf = buf.replace(sys.ps1, "")
1613 if buf.startswith(sys.ps2): 1621 if buf.startswith(sys.ps2):
1614 buf = buf.replace(sys.ps2, "") 1622 buf = buf.replace(sys.ps2, "")
1615 if buf and self.incrementalSearchActive: 1623 if buf and self.incrementalSearchActive:
1616 if self.incrementalSearchString and \ 1624 if (
1617 buf.startswith(self.incrementalSearchString): 1625 self.incrementalSearchString and
1626 buf.startswith(self.incrementalSearchString)
1627 ):
1618 idx, found = self.__rsearchHistory( 1628 idx, found = self.__rsearchHistory(
1619 self.incrementalSearchString, self.__histidx) 1629 self.incrementalSearchString, self.__histidx)
1620 if found and idx >= 0: 1630 if found and idx >= 0:
1621 self.__setHistoryIndex(index=idx) 1631 self.__setHistoryIndex(index=idx)
1622 self.__useHistory() 1632 self.__useHistory()
1654 if buf.startswith(sys.ps1): 1664 if buf.startswith(sys.ps1):
1655 buf = buf.replace(sys.ps1, "") 1665 buf = buf.replace(sys.ps1, "")
1656 if buf.startswith(sys.ps2): 1666 if buf.startswith(sys.ps2):
1657 buf = buf.replace(sys.ps2, "") 1667 buf = buf.replace(sys.ps2, "")
1658 if buf and self.incrementalSearchActive: 1668 if buf and self.incrementalSearchActive:
1659 if self.incrementalSearchString and \ 1669 if (
1660 buf.startswith(self.incrementalSearchString): 1670 self.incrementalSearchString and
1671 buf.startswith(self.incrementalSearchString)
1672 ):
1661 idx, found = self.__searchHistory( 1673 idx, found = self.__searchHistory(
1662 self.incrementalSearchString, self.__histidx) 1674 self.incrementalSearchString, self.__histidx)
1663 if found and idx >= 0: 1675 if found and idx >= 0:
1664 self.__setHistoryIndex(index=idx) 1676 self.__setHistoryIndex(index=idx)
1665 self.__useHistory() 1677 self.__useHistory()
1756 self.__history.append(cmd) 1768 self.__history.append(cmd)
1757 if self.__historyStyle == ShellHistoryStyle.LinuxStyle: 1769 if self.__historyStyle == ShellHistoryStyle.LinuxStyle:
1758 self.__setHistoryIndex(index=-1) 1770 self.__setHistoryIndex(index=-1)
1759 elif self.__historyStyle == ShellHistoryStyle.WindowsStyle: 1771 elif self.__historyStyle == ShellHistoryStyle.WindowsStyle:
1760 if historyIndex is None: 1772 if historyIndex is None:
1761 if self.__histidx - 1 > 0 and \ 1773 if (
1762 cmd != self.__history[self.__histidx - 1]: 1774 self.__histidx - 1 > 0 and
1775 cmd != self.__history[self.__histidx - 1]
1776 ):
1763 self.__setHistoryIndex(index=-1) 1777 self.__setHistoryIndex(index=-1)
1764 else: 1778 else:
1765 self.__setHistoryIndex(historyIndex) 1779 self.__setHistoryIndex(historyIndex)
1766 1780
1767 if cmd == 'start' or cmd.startswith('start '): 1781 if cmd == 'start' or cmd.startswith('start '):
1774 if venvName == self.tr("Project"): 1788 if venvName == self.tr("Project"):
1775 if self.__project.isOpen(): 1789 if self.__project.isOpen():
1776 self.dbs.startClient( 1790 self.dbs.startClient(
1777 False, forProject=True, 1791 False, forProject=True,
1778 workingDir=self.__project.getProjectPath()) 1792 workingDir=self.__project.getProjectPath())
1779 self.__currentWorkingDirectory = \ 1793 self.__currentWorkingDirectory = (
1780 self.__project.getProjectPath() 1794 self.__project.getProjectPath()
1795 )
1781 else: 1796 else:
1782 self.dbs.startClient( 1797 self.dbs.startClient(
1783 False, venvName=self.__currentVenv, 1798 False, venvName=self.__currentVenv,
1784 workingDir=self.__currentWorkingDirectory) 1799 workingDir=self.__currentWorkingDirectory)
1785 # same as reset 1800 # same as reset
1801 if self.passive: 1816 if self.passive:
1802 return 1817 return
1803 else: 1818 else:
1804 cmd = '' 1819 cmd = ''
1805 elif cmd in ['envs', 'environments']: 1820 elif cmd in ['envs', 'environments']:
1806 venvs = e5App().getObject("VirtualEnvManager")\ 1821 venvs = (
1822 e5App().getObject("VirtualEnvManager")
1807 .getVirtualenvNames() 1823 .getVirtualenvNames()
1824 )
1808 s = self.tr('Available Virtual Environments:\n{0}\n').format( 1825 s = self.tr('Available Virtual Environments:\n{0}\n').format(
1809 '\n'.join("- {0}".format(venv) for venv in sorted(venvs)) 1826 '\n'.join("- {0}".format(venv) for venv in sorted(venvs))
1810 ) 1827 )
1811 self.__write(s) 1828 self.__write(s)
1812 self.__clientStatement(False) 1829 self.__clientStatement(False)
1815 s = self.tr("Current Virtual Environment: '{0}'\n").format( 1832 s = self.tr("Current Virtual Environment: '{0}'\n").format(
1816 self.__currentVenv) 1833 self.__currentVenv)
1817 self.__write(s) 1834 self.__write(s)
1818 self.__clientStatement(False) 1835 self.__clientStatement(False)
1819 return 1836 return
1820 elif cmd in ["quit", "quit()", "exit", "exit()"] and \ 1837 elif (
1821 self.__windowed: 1838 cmd in ["quit", "quit()", "exit", "exit()"] and
1839 self.__windowed
1840 ):
1822 # call main window quit() 1841 # call main window quit()
1823 self.vm.quit() 1842 self.vm.quit()
1824 return 1843 return
1825 1844
1826 self.dbs.remoteStatement(cmd) 1845 self.dbs.remoteStatement(cmd)
1894 """ 1913 """
1895 if startIdx == -1: 1914 if startIdx == -1:
1896 idx = 0 1915 idx = 0
1897 else: 1916 else:
1898 idx = startIdx + 1 1917 idx = startIdx + 1
1899 while idx < len(self.__history) and \ 1918 while (
1900 not self.__history[idx].startswith(txt): 1919 idx < len(self.__history) and
1920 not self.__history[idx].startswith(txt)
1921 ):
1901 idx += 1 1922 idx += 1
1902 found = (idx < len(self.__history) and 1923 found = (idx < len(self.__history) and
1903 self.__history[idx].startswith(txt)) 1924 self.__history[idx].startswith(txt))
1904 return idx, found 1925 return idx, found
1905 1926
1917 """ 1938 """
1918 if startIdx == -1: 1939 if startIdx == -1:
1919 idx = len(self.__history) - 1 1940 idx = len(self.__history) - 1
1920 else: 1941 else:
1921 idx = startIdx - 1 1942 idx = startIdx - 1
1922 while idx >= 0 and \ 1943 while (
1923 not self.__history[idx].startswith(txt): 1944 idx >= 0 and
1945 not self.__history[idx].startswith(txt)
1946 ):
1924 idx -= 1 1947 idx -= 1
1925 found = idx >= 0 and self.__history[idx].startswith(txt) 1948 found = idx >= 0 and self.__history[idx].startswith(txt)
1926 return idx, found 1949 return idx, found
1927 1950
1928 def focusNextPrevChild(self, nextChild): 1951 def focusNextPrevChild(self, nextChild):
1979 @param action context menu action that was triggered (QAction) 2002 @param action context menu action that was triggered (QAction)
1980 """ 2003 """
1981 venvName = action.text() 2004 venvName = action.text()
1982 if venvName == self.tr("Project"): 2005 if venvName == self.tr("Project"):
1983 if self.__project.isOpen(): 2006 if self.__project.isOpen():
1984 self.__currentWorkingDirectory = \ 2007 self.__currentWorkingDirectory = (
1985 self.__project.getProjectPath() 2008 self.__project.getProjectPath()
2009 )
1986 self.dbs.startClient(False, forProject=True, 2010 self.dbs.startClient(False, forProject=True,
1987 workingDir=self.__currentWorkingDirectory) 2011 workingDir=self.__currentWorkingDirectory)
1988 else: 2012 else:
1989 self.dbs.startClient(False, venvName=venvName) 2013 self.dbs.startClient(False, venvName=venvName)
1990 self.__getBanner() 2014 self.__getBanner()
2006 self.__setCallTips() 2030 self.__setCallTips()
2007 2031
2008 # do the history related stuff 2032 # do the history related stuff
2009 self.__maxHistoryEntries = Preferences.getShell("MaxHistoryEntries") 2033 self.__maxHistoryEntries = Preferences.getShell("MaxHistoryEntries")
2010 for key in list(self.__historyLists.keys()): 2034 for key in list(self.__historyLists.keys()):
2011 self.__historyLists[key] = \ 2035 self.__historyLists[key] = (
2012 self.__historyLists[key][-self.__maxHistoryEntries:] 2036 self.__historyLists[key][-self.__maxHistoryEntries:]
2037 )
2013 self.__historyStyle = Preferences.getShell("HistoryStyle") 2038 self.__historyStyle = Preferences.getShell("HistoryStyle")
2014 self.__historyWrap = Preferences.getShell("HistoryWrap") 2039 self.__historyWrap = Preferences.getShell("HistoryWrap")
2015 self.__setHistoryIndex() 2040 self.__setHistoryIndex()
2016 if not self.__windowed: 2041 if not self.__windowed:
2017 self.hmenu.menuAction().setEnabled(self.isHistoryEnabled()) 2042 self.hmenu.menuAction().setEnabled(self.isHistoryEnabled())
2018 self.__historyNavigateByCursor = \ 2043 self.__historyNavigateByCursor = Preferences.getShell(
2019 Preferences.getShell("HistoryNavigateByCursor") 2044 "HistoryNavigateByCursor")
2020 self.historyStyleChanged.emit(self.__historyStyle) 2045 self.historyStyleChanged.emit(self.__historyStyle)
2021 2046
2022 # do stdout /stderr stuff 2047 # do stdout /stderr stuff
2023 showStdOutErr = Preferences.getShell("ShowStdOutErr") 2048 showStdOutErr = Preferences.getShell("ShowStdOutErr")
2024 if self.__showStdOutErr != showStdOutErr: 2049 if self.__showStdOutErr != showStdOutErr:
2072 """ 2097 """
2073 Protected method to handle the drag enter event. 2098 Protected method to handle the drag enter event.
2074 2099
2075 @param event the drag enter event (QDragEnterEvent) 2100 @param event the drag enter event (QDragEnterEvent)
2076 """ 2101 """
2077 self.inDragDrop = event.mimeData().hasUrls() or \ 2102 self.inDragDrop = (
2103 event.mimeData().hasUrls() or
2078 event.mimeData().hasText() 2104 event.mimeData().hasText()
2105 )
2079 if self.inDragDrop: 2106 if self.inDragDrop:
2080 event.acceptProposedAction() 2107 event.acceptProposedAction()
2081 else: 2108 else:
2082 super(Shell, self).dragEnterEvent(event) 2109 super(Shell, self).dragEnterEvent(event)
2083 2110

eric ide

mercurial