How to implement indentation based code folding in QScintilla? How to implement indentation based code folding in QScintilla? python python

How to implement indentation based code folding in QScintilla?


[erased the previous answer, since in the light of the last question edit the only value it might probably have is historical; refer to the edit history if you`re still curious]

Finally, the optimized version — bundled with 80 kilolines of sample text to show off its performance.

from PyQt5.Qsci import QsciScintillafrom PyQt5.Qt import *def set_fold(prev, line, fold, full):    if (prev[0] >= 0):        fmax = max(fold, prev[1])        for iter in range(prev[0], line + 1):            view.SendScintilla(view.SCI_SETFOLDLEVEL, iter,                fmax | (0, view.SC_FOLDLEVELHEADERFLAG)[iter + 1 < full])def line_empty(line):    return view.SendScintilla(view.SCI_GETLINEENDPOSITION, line) \        <= view.SendScintilla(view.SCI_GETLINEINDENTPOSITION, line)def modify(position, modificationType, text, length, linesAdded,           line, foldLevelNow, foldLevelPrev, token, annotationLinesAdded):    full = view.SC_MOD_INSERTTEXT | view.SC_MOD_DELETETEXT    if (~modificationType & full == full):        return    prev = [-1, 0]    full = view.SendScintilla(view.SCI_GETLINECOUNT)    lbgn = view.SendScintilla(view.SCI_LINEFROMPOSITION, position)    lend = view.SendScintilla(view.SCI_LINEFROMPOSITION, position + length)    for iter in range(max(lbgn - 1, 0), -1, -1):        if ((iter == 0) or not line_empty(iter)):            lbgn = iter            break    for iter in range(min(lend + 1, full), full + 1):        if ((iter == full) or not line_empty(iter)):            lend = min(iter + 1, full)            break    for iter in range(lbgn, lend):        if (line_empty(iter)):            if (prev[0] == -1):                prev[0] = iter        else:            fold = view.SendScintilla(view.SCI_GETLINEINDENTATION, iter)            fold //= view.SendScintilla(view.SCI_GETTABWIDTH)            set_fold(prev, iter - 1, fold, full)            set_fold([iter, fold], iter, fold, full)            prev = [-1, fold]    set_fold(prev, lend - 1, 0, full)if __name__ == '__main__':    import sys    import textwrap    app = QApplication(sys.argv)    view = QsciScintilla()    view.SendScintilla(view.SCI_SETMULTIPLESELECTION, True)    view.SendScintilla(view.SCI_SETMULTIPASTE, 1)    view.SendScintilla(view.SCI_SETADDITIONALSELECTIONTYPING, True)    view.SendScintilla(view.SCI_SETINDENTATIONGUIDES, view.SC_IV_REAL);    view.SendScintilla(view.SCI_SETTABWIDTH, 4)    view.setFolding(view.BoxedFoldStyle)    view.SCN_MODIFIED.connect(modify)    NUM_CHUNKS = 20000    chunk = textwrap.dedent("""\        x = 1            x = 2            x = 3    """)    view.setText("\n".join([chunk for i in range(NUM_CHUNKS)]))    view.show()    app.exec_()