eric6/MicroPython/MicroPythonReplWidget.py

branch
micropython
changeset 7067
3fc4082fc6ba
parent 7066
e3d034e65afc
child 7069
a09a30251d4e
equal deleted inserted replaced
7066:e3d034e65afc 7067:3fc4082fc6ba
12 import re 12 import re
13 13
14 from PyQt5.QtCore import ( 14 from PyQt5.QtCore import (
15 pyqtSlot, pyqtSignal, Qt, QPoint, QEvent, QIODevice, QTimer 15 pyqtSlot, pyqtSignal, Qt, QPoint, QEvent, QIODevice, QTimer
16 ) 16 )
17 from PyQt5.QtGui import QColor, QKeySequence, QTextCursor, QBrush 17 from PyQt5.QtGui import (
18 QColor, QKeySequence, QTextCursor, QBrush, QTextCharFormat
19 )
18 from PyQt5.QtWidgets import ( 20 from PyQt5.QtWidgets import (
19 QWidget, QMenu, QApplication, QHBoxLayout, QSpacerItem, QSizePolicy) 21 QWidget, QMenu, QApplication, QHBoxLayout, QSpacerItem, QSizePolicy
22 )
20 try: 23 try:
21 from PyQt5.QtSerialPort import QSerialPort 24 from PyQt5.QtSerialPort import QSerialPort
22 HAS_QTSERIALPORT = True 25 HAS_QTSERIALPORT = True
23 except ImportError: 26 except ImportError:
24 HAS_QTSERIALPORT = False 27 HAS_QTSERIALPORT = False
36 except ImportError: 39 except ImportError:
37 HAS_QTCHART = False 40 HAS_QTCHART = False
38 41
39 import Globals 42 import Globals
40 import UI.PixmapCache 43 import UI.PixmapCache
44 import Preferences
41 45
42 46
43 class MicroPythonReplWidget(QWidget, Ui_MicroPythonReplWidget): 47 class MicroPythonReplWidget(QWidget, Ui_MicroPythonReplWidget):
44 """ 48 """
45 Class implementing the MicroPython REPL widget. 49 Class implementing the MicroPython REPL widget.
55 59
56 dataReceived = pyqtSignal(bytes) 60 dataReceived = pyqtSignal(bytes)
57 61
58 # ANSI Colors 62 # ANSI Colors
59 AnsiColors = { 63 AnsiColors = {
60 (1, 30): QBrush(Qt.darkGray), 64 0: QBrush(Qt.black),
61 (1, 31): QBrush(Qt.red), 65 1: QBrush(Qt.darkRed),
62 (1, 32): QBrush(Qt.green), 66 2: QBrush(Qt.darkGreen),
63 (1, 33): QBrush(Qt.yellow), 67 3: QBrush(Qt.darkYellow),
64 (1, 34): QBrush(Qt.blue), 68 4: QBrush(Qt.darkBlue),
65 (1, 35): QBrush(Qt.magenta), 69 5: QBrush(Qt.darkMagenta),
66 (1, 36): QBrush(Qt.cyan), 70 6: QBrush(Qt.darkCyan),
67 (1, 37): QBrush(Qt.white), 71 7: QBrush(Qt.lightGray),
68 (2, 30): QBrush(Qt.black), 72 10: QBrush(Qt.darkGray),
69 (2, 31): QBrush(Qt.darkRed), 73 11: QBrush(Qt.red),
70 (2, 32): QBrush(Qt.darkGreen), 74 12: QBrush(Qt.green),
71 (2, 33): QBrush(Qt.darkYellow), 75 13: QBrush(Qt.yellow),
72 (2, 34): QBrush(Qt.darkBlue), 76 14: QBrush(Qt.blue),
73 (2, 35): QBrush(Qt.darkMagenta), 77 15: QBrush(Qt.magenta),
74 (2, 36): QBrush(Qt.darkCyan), 78 16: QBrush(Qt.cyan),
75 (2, 37): QBrush(Qt.lightGray), 79 17: QBrush(Qt.white),
76 } 80 }
77 81
78 def __init__(self, parent=None): 82 def __init__(self, parent=None):
79 """ 83 """
80 Constructor 84 Constructor
133 "MicroPython support is deactivated.</h3>")) 137 "MicroPython support is deactivated.</h3>"))
134 self.setEnabled(False) 138 self.setEnabled(False)
135 return 139 return
136 140
137 self.__vt100Re = re.compile( 141 self.__vt100Re = re.compile(
138 r'(?P<count>\d*);?(?P<color>\d*)(?P<action>[ABCDKm])') 142 r'(?P<count>\d*)(?P<color>(?:;?\d*)*)(?P<action>[ABCDKm])')
139 143
140 self.__populateDeviceTypeComboBox() 144 self.__populateDeviceTypeComboBox()
141 145
142 self.replEdit.setAcceptRichText(False) 146 self.replEdit.setAcceptRichText(False)
143 self.replEdit.setUndoRedoEnabled(False) 147 self.replEdit.setUndoRedoEnabled(False)
146 self.replEdit.installEventFilter(self) 150 self.replEdit.installEventFilter(self)
147 151
148 self.replEdit.customContextMenuRequested.connect( 152 self.replEdit.customContextMenuRequested.connect(
149 self.__showContextMenu) 153 self.__showContextMenu)
150 154
151 defaultCharFormat = self.replEdit.textCursor().charFormat() 155 font = Preferences.getEditorOtherFonts("MonospacedFont")
152 self.DefaultForeground = defaultCharFormat.foreground() 156 self.replEdit.setFontFamily(font.family())
153 self.DefaultBackground = defaultCharFormat.background() 157 self.replEdit.setFontPointSize(font.pointSize())
158 self.DefaultCharFormat = self.replEdit.currentCharFormat()
159 self.DefaultForeground = self.DefaultCharFormat.foreground()
160 self.DefaultBackground = self.DefaultCharFormat.background()
154 161
155 def __populateDeviceTypeComboBox(self): 162 def __populateDeviceTypeComboBox(self):
156 """ 163 """
157 Private method to populate the device type selector. 164 Private method to populate the device type selector.
158 """ 165 """
453 tc.movePosition(QTextCursor.EndOfLine, 460 tc.movePosition(QTextCursor.EndOfLine,
454 mode=QTextCursor.KeepAnchor) 461 mode=QTextCursor.KeepAnchor)
455 tc.removeSelectedText() 462 tc.removeSelectedText()
456 self.replEdit.setTextCursor(tc) 463 self.replEdit.setTextCursor(tc)
457 elif action == "m": 464 elif action == "m":
458 print(match.group("count"), match.group("color")) 465 self.__setCharFormat(match.group(0)[:-1].split(";"),
459 charFormat = tc.charFormat() 466 tc)
460 if count == 0 and match.group("color") == "":
461 # reset color
462 charFormat.setForeground(self.DefaultForeground)
463 charFormat.setBackground(self.DefaultBackground)
464 elif count in (0, 1, 2):
465 if match.group("color") != "":
466 color = int(match.group("color"))
467 if count == 0:
468 count = 1
469 if 30 <= color <= 37:
470 charFormat.setForeground(
471 self.AnsiColors[(count, color)])
472 elif 40 <= color <= 47:
473 charFormat.setBackground(
474 self.AnsiColors[(count, color - 10)])
475 tc.setCharFormat(charFormat)
476 self.replEdit.setTextCursor(tc)
477 elif data[index] == 10: # \n 467 elif data[index] == 10: # \n
478 tc.movePosition(QTextCursor.End) 468 tc.movePosition(QTextCursor.End)
479 self.replEdit.setTextCursor(tc) 469 self.replEdit.setTextCursor(tc)
480 self.replEdit.insertPlainText(chr(data[index])) 470 self.replEdit.insertPlainText(chr(data[index]))
471 self.__setCharFormat(["0"], tc) # reset format after a \n
481 else: 472 else:
482 tc.deleteChar() 473 tc.deleteChar()
483 self.replEdit.setTextCursor(tc) 474 self.replEdit.setTextCursor(tc)
484 self.replEdit.insertPlainText(chr(data[index])) 475 self.replEdit.insertPlainText(chr(data[index]))
485 476
486 index += 1 477 index += 1
487 478
488 self.replEdit.ensureCursorVisible() 479 self.replEdit.ensureCursorVisible()
480
481 def __setCharFormat(self, formatCodes, textCursor):
482 """
483 Private method setting the current text format of the REPL pane based
484 on the passed ANSI codes.
485
486 Following codes are used:
487 <ul>
488 <li>0: Reset</li>
489 <li>1: Bold font (weight 75)</li>
490 <li>2: Light font (weight 25)</li>
491 <li>3: Italic font</li>
492 <li>4: Underlined font</li>
493 <li>9: Strikeout font</li>
494 <li>21: Bold off (weight 50)</li>
495 <li>22: Light off (weight 50)</li>
496 <li>23: Italic off</li>
497 <li>24: Underline off</li>
498 <li>29: Strikeout off</li>
499 <li>30: foreground Black</li>
500 <li>31: foreground Dark Red</li>
501 <li>32: foreground Dark Green</li>
502 <li>33: foreground Dark Yellow</li>
503 <li>34: foreground Dark Blue</li>
504 <li>35: foreground Dark Magenta</li>
505 <li>36: foreground Dark Cyan</li>
506 <li>37: foreground Light Gray</li>
507 <li>40: background Black</li>
508 <li>41: background Dark Red</li>
509 <li>42: background Dark Green</li>
510 <li>43: background Dark Yellow</li>
511 <li>44: background Dark Blue</li>
512 <li>45: background Dark Magenta</li>
513 <li>46: background Dark Cyan</li>
514 <li>47: background Light Gray</li>
515 <li>53: Overlined font</li>
516 <li>55: Overline off</li>
517 <li>90: bright foreground Dark Gray</li>
518 <li>91: bright foreground Red</li>
519 <li>92: bright foreground Green</li>
520 <li>93: bright foreground Yellow</li>
521 <li>94: bright foreground Blue</li>
522 <li>95: bright foreground Magenta</li>
523 <li>96: bright foreground Cyan</li>
524 <li>97: bright foreground White</li>
525 <li>100: bright background Dark Gray</li>
526 <li>101: bright background Red</li>
527 <li>102: bright background Green</li>
528 <li>103: bright background Yellow</li>
529 <li>104: bright background Blue</li>
530 <li>105: bright background Magenta</li>
531 <li>106: bright background Cyan</li>
532 <li>107: bright background White</li>
533 </ul>
534
535 @param formatCodes list of format codes
536 @type list of str
537 @param textCursor reference to the text cursor
538 @type QTextCursor
539 """
540 if not formatCodes:
541 # empty format codes list is treated as a reset
542 formatCodes = ["0"]
543
544 charFormat = textCursor.charFormat()
545 for formatCode in formatCodes:
546 try:
547 formatCode = int(formatCode)
548 except ValueError:
549 # ignore non digit values
550 continue
551
552 if formatCode == 0:
553 charFormat.setFontWeight(50)
554 charFormat.setFontItalic(False)
555 charFormat.setFontUnderline(False)
556 charFormat.setFontStrikeOut(False)
557 charFormat.setFontOverline(False)
558 charFormat.setForeground(self.DefaultForeground)
559 charFormat.setBackground(self.DefaultBackground)
560 elif formatCode == 1:
561 charFormat.setFontWeight(75)
562 elif formatCode == 2:
563 charFormat.setFontWeight(25)
564 elif formatCode == 3:
565 charFormat.setFontItalic(True)
566 elif formatCode == 4:
567 charFormat.setFontUnderline(True)
568 elif formatCode == 9:
569 charFormat.setFontStrikeOut(True)
570 elif formatCode in (21, 22):
571 charFormat.setFontWeight(50)
572 elif formatCode == 23:
573 charFormat.setFontItalic(False)
574 elif formatCode == 24:
575 charFormat.setFontUnderline(False)
576 elif formatCode == 29:
577 charFormat.setFontStrikeOut(False)
578 elif formatCode == 53:
579 charFormat.setFontOverline(True)
580 elif formatCode == 55:
581 charFormat.setFontOverline(False)
582 elif formatCode in (30, 31, 32, 33, 34, 35, 36, 37):
583 charFormat.setForeground(self.AnsiColors[formatCode - 30])
584 elif formatCode in (40, 41, 42, 43, 44, 45, 46, 47):
585 charFormat.setBackground(self.AnsiColors[formatCode - 40])
586 elif formatCode in (90, 91, 92, 93, 94, 95, 96, 97):
587 charFormat.setForeground(self.AnsiColors[formatCode - 80])
588 elif formatCode in (100, 101, 102, 103, 104, 105, 106, 107):
589 charFormat.setBackground(self.AnsiColors[formatCode - 90])
590
591 textCursor.setCharFormat(charFormat)
489 592
490 def __doZoom(self, value): 593 def __doZoom(self, value):
491 """ 594 """
492 Private slot to zoom the REPL pane. 595 Private slot to zoom the REPL pane.
493 596

eric ide

mercurial