1
votes

I am creating a simple text editor in PyQt4 through Pygments syntex highlighter. I have the following code.

from PyQt4 import QtCore, QtGui
import time,sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from pygments import highlight
from pygments.lexers import PythonLexer,get_lexer_by_name
from pygments.formatters import HtmlFormatter
def highlighter():
        text = area.toPlainText()
        result = highlight(text, lexer, formatter)
        area.setText(result)

code = 'print ("Hello World")\n# Test Program'

lexer = get_lexer_by_name("python3", stripall=True)
formatter = HtmlFormatter(linenos=False,style='colorful')
formatter.noclasses = True
result = highlight(code, lexer, formatter)

app = QApplication(sys.argv)
w=QWidget()
w.setGeometry(500,400,350,350)

area = QTextEdit(w)
area.setGeometry(0,10,350,340)
area.setText(result)
area.textChanged.connect(highlighter)

w.show()
sys.exit(app.exec_())

When the first time it loads it outputs correctly, but if i type a single word in QTextEdit it waits for 1-2 seconds and shows the following error:

Traceback (most recent call last):   File "C:\Users\Home\Desktop\code_highlighter - Copy.py", line 10, in highlight er
    result = highlight(text, lexer, formatter)   File "C:\Python34\lib\site-packages\pygments\__init__.py", line 85, in highlig ht
    return format(lex(code, lexer), formatter, outfile)   File "C:\Python34\lib\site-packages\pygments\__init__.py", line 64, in format
    formatter.format(tokens, realoutfile)   File "C:\Python34\lib\site-packages\pygments\formatter.py", line 95, in format

    return self.format_unencoded(tokensource, outfile)   File "C:\Python34\lib\site-packages\pygments\formatters\html.py", line 850, in  format_unencoded
    for t, piece in source:   File "C:\Python34\lib\site-packages\pygments\formatters\html.py", line 690, in  _wrap_div
    for tup in inner:   File "C:\Python34\lib\site-packages\pygments\formatters\html.py", line 708, in  _wrap_pre
    for tup in inner:   File "C:\Python34\lib\site-packages\pygments\formatters\html.py", line 727, in  _format_lines
    for ttype, value in tokensource:   File "C:\Python34\lib\site-packages\pygments\lexer.py", line 191, in streamer
    for _, t, v in self.get_tokens_unprocessed(text):   File "C:\Python34\lib\site-packages\pygments\lexer.py", line 624, in get_token s_unprocessed
    statestack = list(stack) RuntimeError: maximum recursion depth exceeded while calling a Python object Traceback (most recent call last):   File "C:\Users\Home\Desktop\code_highlighter - Copy.py", line 10, in highlight er
    result = highlight(text, lexer, formatter)   File "C:\Python34\lib\site-packages\pygments\__init__.py", line 85, in highlig ht
    return format(lex(code, lexer), formatter, outfile)   File "C:\Python34\lib\site-packages\pygments\__init__.py", line 64, in format
    formatter.format(tokens, realoutfile)   File "C:\Python34\lib\site-packages\pygments\formatter.py", line 95, in format

    return self.format_unencoded(tokensource, outfile)   File "C:\Python34\lib\site-packages\pygments\formatters\html.py", line 850, in  format_unencoded
    for t, piece in source:   File "C:\Python34\lib\site-packages\pygments\formatters\html.py", line 690, in  _wrap_div
    for tup in inner:   File "C:\Python34\lib\site-packages\pygments\formatters\html.py", line 708, in  _wrap_pre
    for tup in inner:   File "C:\Python34\lib\site-packages\pygments\formatters\html.py", line 727, in  _format_lines
    for ttype, value in tokensource:   File "C:\Python34\lib\site-packages\pygments\lexer.py", line 191, in streamer
    for _, t, v in self.get_tokens_unprocessed(text):   File "C:\Python34\lib\site-packages\pygments\lexer.py", line 624, in get_token s_unprocessed
    statestack = list(stack) RuntimeError: maximum recursion depth exceeded while calling a Python object 

Did many things can't help myself. I don't know where i am doing wrong. PLease help me.

1

1 Answers

2
votes

Your highlighter() function calls area.setText(), which will emit the textChanged signal which is connected to highlighter, which calls area.setText() which... and so on.

For a QTextEdit the textChaged signal is always emitted when the setText() method is called, even if the visible text content didn't actually change, because its internal representation does change.

A simple workaround in your case would be to block the delivery of signals when you call setText():

def highlighter():
        text = area.toPlainText()
        result = highlight(text, lexer, formatter)
        area.blockSignals(True)
        pos = area.textCursor().position()
        area.setText(result)
        cursor = area.textCursor()
        cursor.setPosition(min(pos, len(area.toPlainText())))
        area.setTextCursor(cursor)
        area.blockSignals(False)