class Highlighter(QSyntaxHighlighter): def __init__(self, parent): super(Highlighter, self).__init__(parent) self.taskFormat = QTextCharFormat() self.taskFormat.setForeground(Qt.yellow) self.infoFormat = QTextCharFormat() self.infoFormat.setForeground(Qt.gray) self.buildFormat = QTextCharFormat() self.buildFormat.setForeground(Qt.magenta) self.connectedFormat = QTextCharFormat() self.connectedFormat.setForeground(Qt.cyan) self.errorFormat = QTextCharFormat() self.errorFormat.setForeground(Qt.red) def highlightBlock(self, text): if text.startswith('[TASK]'): self.setFormat(0, len(text), self.taskFormat) elif text.startswith('[INFO]'): self.setFormat(0, len(text), self.infoFormat) elif text.startswith('[BUILD]'): self.setFormat(0, len(text), self.buildFormat) elif text.startswith('[CONNECTED]'): self.setFormat(0, len(text), self.connectedFormat) elif text.startswith('[ERROR]'): self.setFormat(0, len(text), self.errorFormat)
class ShellHighlighter(QSyntaxHighlighter): def __init__(self, parent): super(ShellHighlighter, self).__init__(parent) self.input_format = QTextCharFormat() self.input_format.setForeground(Qt.red) def highlightBlock(self, text): if text.startswith('$: '): self.setFormat(0, len(text), self.input_format)
class Highlighter(QSyntaxHighlighter): def __init__(self, parent): super(Highlighter, self).__init__(parent) self.generator_format = QTextCharFormat() self.generator_format.setForeground(Qt.yellow) self.error_format = QTextCharFormat() self.error_format.setForeground(Qt.red) def highlightBlock(self, text): if text.startswith('<INFO>'): self.setFormat(0, len(text), self.generator_format) elif text.startswith('<ERROR>'): self.setFormat(0, len(text), self.error_format)
def _print_to_output(build_popup, msg, error=False): """ display message in the build output TextBrowser """ cursor = build_popup.textBrowser_output.textCursor() cursor.movePosition(cursor.End) scrollbar = build_popup.textBrowser_output.verticalScrollBar() scrolled_to_end = scrollbar.value() == scrollbar.maximum() char_format = QTextCharFormat() char_format.setForeground(QColor('red') if error else QColor('black')) cursor.setCharFormat(char_format) cursor.insertText(_fmt_message(build_popup, msg)) if scrolled_to_end: scrollbar.setValue(scrollbar.maximum())
def format(color, style=''): """Return a QTextCharFormat with the given attributes. """ _color = QColor() _color.setNamedColor(color) _format = QTextCharFormat() _format.setForeground(_color) if 'bold' in style: _format.setFontWeight(QFont.Bold) if 'italic' in style: _format.setFontItalic(True) return _format
def init_scheme(self): """初始化字体方案, 定义类型应该显示的模板块, 可以同外部的 text_format设定其中具体的类型模板""" base_formats = QTextCharFormat() base_formats.setFont(self.font) # 设置一个默认的字块 # set a default text block self.__block_format.update({'normal': base_formats}) # 设置配色 # set block scheme for scheme in self.rules_scheme['scheme']: block_scheme = QTextCharFormat(base_formats) block_scheme.setForeground(QColor(scheme.get('color', '#000000'))) if scheme['bold']: block_scheme.setFontWeight(QFont.Bold) if scheme['italic']: block_scheme.setFontItalic(True) self.__block_format.update({scheme['name']: block_scheme})
class ConsoleFontStyle(object): def __init__(self, foregroundcolor, backgroundcolor, bold, italic, underline): self.foregroundcolor = foregroundcolor self.backgroundcolor = backgroundcolor self.bold = bold self.italic = italic self.underline = underline self.format = None def apply_style(self, font, is_default): self.format = QTextCharFormat() self.format.setFont(font) foreground = QColor(self.foregroundcolor) self.format.setForeground(foreground) background = QColor(self.backgroundcolor) self.format.setBackground(background) font = self.format.font() font.setBold(self.bold) font.setItalic(self.italic) font.setUnderline(self.underline) self.format.setFont(font)
class ConsoleFontStyle(object): def __init__(self, foregroundcolor, backgroundcolor, bold, italic, underline): self.foregroundcolor = foregroundcolor self.backgroundcolor = backgroundcolor self.bold = bold self.italic = italic self.underline = underline self.format = None def apply_style(self, font, is_default): self.format = QTextCharFormat() self.format.setFont(font) foreground = QColor(self.foregroundcolor) self.format.setForeground(foreground) background = QColor(self.backgroundcolor) self.format.setBackground(background) font = self.format.font() font.setBold(self.bold) font.setItalic(self.italic) font.setUnderline(self.underline) self.format.setFont(font)
def __init__(self, document): super().__init__(document) self.rules = [] # keywords f = QTextCharFormat() f.setFontWeight(QFont.Bold) f.setForeground(Qt.darkBlue) for kw in keyword.kwlist: self.rules.append((QRegularExpression(rf"\b{kw}\b"), f)) # numerals f = QTextCharFormat() f.setForeground(Qt.blue) self.rules.append((QRegularExpression("[0-9]+"), f)) # strings f = QTextCharFormat() f.setForeground(Qt.darkCyan) self.rules.append((QRegularExpression("\".*\""), f)) self.rules.append((QRegularExpression("'.*'"), f))
class KeywordHighlighter(QSyntaxHighlighter): def __init__(self, document): QSyntaxHighlighter.__init__(self, document) self.clb = ConfigurationLineBuilder(ErtKeywords()) self.comment_format = QTextCharFormat() self.comment_format.setForeground(QColor(0, 128, 0)) self.comment_format.setFontItalic(True) self.keyword_format = QTextCharFormat() self.keyword_format.setForeground(QColor(200, 100, 0)) # self.keyword_format.setFontWeight(QFont.Bold) self.error_format = QTextCharFormat() # self.error_format.setForeground(QColor(255, 0, 0)) self.error_format.setUnderlineStyle(QTextCharFormat.WaveUnderline) self.error_format.setUnderlineColor(QColor(255, 0, 0)) self.search_format = QTextCharFormat() self.search_format.setBackground(QColor(220, 220, 220)) self.builtin_format = QTextCharFormat() self.builtin_format.setForeground(QColor(0, 170, 227)) self.search_string = "" def formatKeyword(self, keyword, validation_status): assert isinstance(keyword, Keyword) if keyword.hasKeywordDefinition(): keyword_format = QTextCharFormat(self.keyword_format) if not validation_status: keyword_format.merge(self.error_format) self.formatToken(keyword, keyword_format) else: self.formatToken(keyword, self.error_format) def highlightBlock(self, complete_block): try: block = unicode(complete_block) except NameError: block = complete_block self.clb.processLine(block) if self.clb.hasComment(): self.setFormat(self.clb.commentIndex(), len(block) - self.clb.commentIndex(), self.comment_format) if not self.clb.hasConfigurationLine(): count = len(block) if self.clb.hasComment(): count = self.clb.commentIndex() self.setFormat(0, count, self.error_format) if self.clb.hasConfigurationLine(): cl = self.clb.configurationLine() self.setCurrentBlockUserData(ConfigurationLineUserData(cl)) self.formatKeyword(cl.keyword(), cl.validationStatusForToken(cl.keyword())) arguments = cl.arguments() for argument in arguments: if not argument.hasArgumentDefinition(): pass elif argument.argumentDefinition().isBuiltIn(): self.formatToken(argument, self.builtin_format) if not cl.validationStatusForToken(argument): self.formatToken(argument, self.error_format) if self.search_string != "": for match in re.finditer("(%s)" % self.search_string, complete_block): self.setFormat(match.start(1), match.end(1) - match.start(1), self.search_format) def setSearchString(self, string): try: if self.search_string != unicode(string): self.search_string = unicode(string) self.rehighlight() except NameError: if self.search_string != string: self.search_string = string self.rehighlight() def formatToken(self, token, highlight_format): self.setFormat(token.fromIndex(), token.count(), highlight_format)
class QtANSIEscapeCodeHandler(ANSIEscapeCodeHandler): def __init__(self): ANSIEscapeCodeHandler.__init__(self) self.base_format = None self.current_format = None def set_color_scheme(self, foreground_color, background_color): """Set color scheme (foreground and background).""" if dark_color(foreground_color): self.default_foreground_color = 30 else: self.default_foreground_color = 37 if dark_color(background_color): self.default_background_color = 47 else: self.default_background_color = 40 def set_base_format(self, base_format): self.base_format = base_format def get_format(self): return self.current_format def set_style(self): """ Set font style with the following attributes: 'foreground_color', 'background_color', 'italic', 'bold' and 'underline' """ if self.current_format is None: assert self.base_format is not None self.current_format = QTextCharFormat(self.base_format) # Foreground color if self.foreground_color is None: qcolor = self.base_format.foreground() else: cstr = self.ANSI_COLORS[self.foreground_color - 30][self.intensity] qcolor = QColor(cstr) self.current_format.setForeground(qcolor) # Background color if self.background_color is None: qcolor = self.base_format.background() else: cstr = self.ANSI_COLORS[self.background_color - 40][self.intensity] qcolor = QColor(cstr) self.current_format.setBackground(qcolor) font = self.current_format.font() # Italic if self.italic is None: italic = self.base_format.fontItalic() else: italic = self.italic font.setItalic(italic) # Bold if self.bold is None: bold = self.base_format.font().bold() else: bold = self.bold font.setBold(bold) # Underline if self.underline is None: underline = self.base_format.font().underline() else: underline = self.underline font.setUnderline(underline) self.current_format.setFont(font)
class QtANSIEscapeCodeHandler(ANSIEscapeCodeHandler): def __init__(self): ANSIEscapeCodeHandler.__init__(self) self.base_format = None self.current_format = None def set_color_scheme(self, foreground_color, background_color): """Set color scheme (foreground and background).""" if dark_color(foreground_color): self.default_foreground_color = 30 else: self.default_foreground_color = 37 if dark_color(background_color): self.default_background_color = 47 else: self.default_background_color = 40 def set_base_format(self, base_format): self.base_format = base_format def get_format(self): return self.current_format def set_style(self): """ Set font style with the following attributes: 'foreground_color', 'background_color', 'italic', 'bold' and 'underline' """ if self.current_format is None: assert self.base_format is not None self.current_format = QTextCharFormat(self.base_format) # Foreground color if self.foreground_color is None: qcolor = self.base_format.foreground() else: cstr = self.ANSI_COLORS[self.foreground_color-30][self.intensity] qcolor = QColor(cstr) self.current_format.setForeground(qcolor) # Background color if self.background_color is None: qcolor = self.base_format.background() else: cstr = self.ANSI_COLORS[self.background_color-40][self.intensity] qcolor = QColor(cstr) self.current_format.setBackground(qcolor) font = self.current_format.font() # Italic if self.italic is None: italic = self.base_format.fontItalic() else: italic = self.italic font.setItalic(italic) # Bold if self.bold is None: bold = self.base_format.font().bold() else: bold = self.bold font.setBold(bold) # Underline if self.underline is None: underline = self.base_format.font().underline() else: underline = self.underline font.setUnderline(underline) self.current_format.setFont(font)
class Q7PythonEditorHighlighter(QSyntaxHighlighter): def __init__(self, *args): keywords = r"\bimport\b|\bas\b|\bfor\b|\bdef\b|\bpass\b" keywords += r"|\bclass\b|\bfrom\b|\bif\b|\bthen\b|\belse\b" keywords += r"|\belif\b|\btry\b|\bexcept\b|\bfinally\b|\braise\b" keywords += r"|\bprint\b|\bin\b|\bnot\b|\band\b|\bor\b|\bcontinue\b" keywords += r"|\bwhile\b|\breturn\b|\blambda\b|\bwith\b|\del\b" keywords += r"|\bglobal\b|\byield\b|\bexec\b|\bassert\b|\break\b" constants = r"\bNone\b|\bTrue\b|\bFalse\b|\bself\b" autovars = r"\bNODE\b|\bNAME\b|\bVALUE\b|\bSIDSTYPE\b|\bCHILDREN\b" autovars += r"|\bTREE\b|\bPATH\b|\bRESULT\b|\bARGS\b|\bPARENT\b" autovars += r"|\bLINKS\b|\bSKIPS\b" numbers = r'[-+]?\d+' + '|[-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?' comment = r'\#.*$' textstring = r'"[^"]*?"|\'[^\']*?\'' self.f_keywords = QTextCharFormat() self.f_keywords.setFontWeight(QFont.Bold) self.f_keywords.setForeground(QColor('Blue')) self.f_comment = QTextCharFormat() self.f_comment.setFontWeight(QFont.Light) self.f_comment.setForeground(QColor('Red')) self.f_constants = QTextCharFormat() self.f_constants.setFontWeight(QFont.Light) self.f_constants.setForeground(QColor('Navy')) self.f_autovars = QTextCharFormat() self.f_autovars.setFontWeight(QFont.Bold) self.f_autovars.setForeground(QColor('Green')) self.f_textstring = QTextCharFormat() self.f_textstring.setFontWeight(QFont.Bold) self.f_textstring.setForeground(QColor('Coral')) self.f_numbers = QTextCharFormat() self.f_numbers.setFontWeight(QFont.Light) self.f_numbers.setForeground(QColor('Gray')) self.r_keywords = re.compile(keywords) self.r_numbers = re.compile(numbers) self.r_comment = re.compile(comment) self.r_constants = re.compile(constants) self.r_autovars = re.compile(autovars) self.r_textstring = re.compile(textstring) self.in_comment = False self.in_string = False self.r_syntax = [] self.r_syntax.append((self.r_keywords, self.f_keywords)) self.r_syntax.append((self.r_numbers, self.f_numbers)) self.r_syntax.append((self.r_autovars, self.f_autovars)) self.r_syntax.append((self.r_constants, self.f_constants)) self.r_syntax.append((self.r_comment, self.f_comment)) self.r_syntax.append((self.r_textstring, self.f_textstring)) QSyntaxHighlighter.__init__(self, *args) def highlightBlock(self, textblock): text = str(textblock) fdef = self.format(0) fmax = len(text) for (rex, fmt) in self.r_syntax: mit = rex.finditer(text) for m in mit: self.setFormat(m.span()[0], m.span()[1], fmt) self.setFormat(m.span()[1], fmax, fdef)
class MainConsole(QWidget): """ Interpreter with interactive console. All console output will be redirected to this command line. It provides normal REPL functionality and additionally access to editor components such as the session object and nodes (by right-click on them). The input field below can also expand to a text edit to take whole code blocks. """ instance = None def __init__( self, window_theme, history: int = 100, # max lines in history buffer blockcount: int = 5000, # max lines in output buffer ): super(MainConsole, self).__init__() self.session = None # set by MainWindow self.window_theme = window_theme self.init_ui(history, blockcount) def init_ui(self, history, blockcount): self.content_layout = QGridLayout(self) self.content_layout.setContentsMargins(0, 0, 0, 0) # self.content_layout.setSpacing(0) self.input_layout = QGridLayout() self.input_layout.setContentsMargins(0, 0, 0, 0) self.input_layout.setSpacing(0) # display for output self.out_display = ConsoleDisplay(blockcount) self.content_layout.addWidget(self.out_display, 1, 0, 1, 2) # colors to differentiate input, output and stderr self.inpfmt = self.out_display.currentCharFormat() self.inpfmt.setForeground( QBrush(QColor(self.window_theme.colors['primaryColor']))) self.outfmt = QTextCharFormat(self.inpfmt) self.outfmt.setForeground( QBrush(QColor(self.window_theme.colors['secondaryTextColor']))) self.errfmt = QTextCharFormat(self.inpfmt) self.errfmt.setForeground( QBrush(QColor(self.window_theme.colors['danger']))) # display input prompt left besides input edit self.prompt_label = QLabel('> ', self) self.prompt_label.setFixedWidth(15) self.input_layout.addWidget(self.prompt_label, 0, 0, 1, 1) self.prompt_label.hide() # command "text edit" for large code input self.inptextedit = ConsoleInputTextEdit(self.window_theme) self.input_layout.addWidget(self.inptextedit, 1, 0, 2, 2) self.inptextedit.hide() # command line self.inpedit = ConsoleInputLineEdit(self.inptextedit, max_history=history) self.inpedit.returned.connect(self.push) self.input_layout.addWidget(self.inpedit, 0, 1, 1, 1) self.content_layout.addLayout(self.input_layout, 2, 0, 1, 2) self.interp = None self.reset_interpreter() self.buffer = [] self.num_added_object_contexts = 0 def setprompt(self, text: str): # self.prompt_label.setText(text) ... def add_obj_context(self, context_obj): """adds an object to the current context by initializing a new interpreter with a new context""" old_context = {} if self.interp is None else self.interp.locals name = 'obj' + (str(self.num_added_object_contexts + 1) if self.num_added_object_contexts > 0 else '') new_context = {name: context_obj} context = {**old_context, **new_context} # merge dicts self.interp = code.InteractiveConsole(context) print('added as ' + name) self.num_added_object_contexts += 1 def reset_interpreter(self): """Initializes a new plain interpreter""" # CONTEXT session = self.session def reset(): self.reset_interpreter() context = {**locals()} # ------- self.num_added_object_contexts = 0 # self.reset_scope_button.hide() self.interp = code.InteractiveConsole(context) def push(self, commands: str) -> None: """execute entered command which may span multiple lines when code was pasted""" if commands == 'clear': self.out_display.clear() else: lines = commands.split('\n') # usually just one entry # clean and print commands for line in lines: # # remove '> ' and '.' prefixes which may remain from copy&paste # if re.match('^[\>\.] ', line): # line = line[2:] # print input self.writeoutput( # self.prompt_label.text() + line, self.inpfmt) # prepare for multi-line input # self.setprompt('. ') self.buffer.append(line) # merge commands source = '\n'.join(self.buffer) more = self.interp.runsource(source, '<console>') if more: # self.setprompt('> ') if self.prompt_label.isHidden(): self.prompt_label.show() # add leading space for next input leading_space = re.match(r"\s*", self.buffer[-1]).group() self.inpedit.next_line = leading_space else: # no more input required self.prompt_label.hide() self.buffer = [] # reset buffer def write(self, line: str) -> None: """capture stdout and print to outdisplay""" if len(line) != 1 or ord(line[0]) != 10: self.writeoutput(line.rstrip()) # , self.outfmt) def errorwrite(self, line: str) -> None: """capture stderr and print to outdisplay""" self.writeoutput(line, self.errfmt) def writeoutput(self, line: str, fmt: QTextCharFormat = None) -> None: """prints to outdisplay""" if fmt: self.out_display.setCurrentCharFormat(fmt) self.out_display.appendPlainText(line.rstrip()) self.out_display.setCurrentCharFormat(self.outfmt)