热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何在QScintilla中实现基于缩进的代码折叠?

如何解决《如何在QScintilla中实现基于缩进的代码折叠?》经验,为你挑选了1个好方法。

这里的最终目标是在QScintilla中实现基于缩进的代码折叠,类似于SublimeText3所做的方式。

首先,这是一个使用QScintilla机制手动提供折叠的小例子:

import sys

from PyQt5.Qsci import QsciScintilla
from PyQt5.Qt import *

if __name__ == '__main__':
    app = QApplication(sys.argv)
    view = QsciScintilla()

    # http://www.scintilla.org/ScintillaDoc.html#Folding
    view.setFolding(QsciScintilla.BoxedTreeFoldStyle)

    lines = [
        (0, "def foo():"),
        (1, "    x = 10"),
        (1, "    y = 20"),
        (1, "    return x+y"),
        (-1, ""),
        (0, "def bar(x):"),
        (1, "    if x > 0:"),
        (2, "        print('this is')"),
        (2, "        print('branch1')"),
        (1, "    else:"),
        (2, "        print('and this')"),
        (2, "        print('is branch2')"),
        (-1, ""),
        (-1, ""),
        (-1, ""),
        (-1, "print('end')"),

    ]

    view.setText("\n".join([b for a, b in lines]))
    MASK = QsciScintilla.SC_FOLDLEVELNUMBERMASK

    for i, tpl in enumerate(lines):
        level, line = tpl
        if level >= 0:
            view.SendScintilla(view.SCI_SETFOLDLEVEL, i, level | QsciScintilla.SC_FOLDLEVELHEADERFLAG)
        else:
            view.SendScintilla(view.SCI_SETFOLDLEVEL, i, 0)

    view.show()
    app.exec_()

要更深入地了解它,可以查看官方文档:

Doc参考:

QSciScintilla

闪烁折叠

就像我说的,我想像Sublime一样实现代码折叠,因此我创建了这个小mcve作为基本代码,可以作为参考:

import re
import time
from pathlib import Path

from PyQt5.Qsci import QsciLexerCustom, QsciScintilla
from PyQt5.Qt import *


def lskip_nonewlines(text, pt):
    len_text = len(text)

    while True:
        if pt <= 0 or pt >= len_text:
            break
        if text[pt - 1] == "\n" or text[pt] == "\n":
            break
        pt -= 1

    return pt


def rskip_nonewlines(text, pt):
    len_text = len(text)

    while True:
        if pt <= 0 or pt >= len_text:
            break
        if text[pt] == "\n":
            break
        pt += 1

    return pt


class Region():
    __slots__ = ['a', 'b']

    def __init__(self, x, b=None):
        if b is None:
            if isinstance(x, int):
                self.a = x
                self.b = x
            elif isinstance(x, tuple):
                self.a = x[0]
                self.b = x[1]
            elif isinstance(x, Region):
                self.a = x.a
                self.b = x.b
            else:
                raise TypeError(f"Can't convert {x.__class__} to Region")
        else:
            self.a = x
            self.b = b

    def __str__(self):
        return "(" + str(self.a) + ", " + str(self.b) + ")"

    def __repr__(self):
        return "(" + str(self.a) + ", " + str(self.b) + ")"

    def __len__(self):
        return self.size()

    def __eq__(self, rhs):
        return isinstance(rhs, Region) and self.a == rhs.a and self.b == rhs.b

    def __lt__(self, rhs):
        lhs_begin = self.begin()
        rhs_begin = rhs.begin()

        if lhs_begin == rhs_begin:
            return self.end()  rhs.end():
            return [self]
        elif rhs.contains(self):
            return []
        elif self.contains(rhs):
            return [Region(self.begin(), rhs.begin()), Region(rhs.end(), self.end())]
        elif rhs.begin() <= self.begin():
            return [Region(rhs.end(), self.end())]
        elif rhs.begin() > self.begin():
            return [Region(self.begin(), rhs.begin())]
        else:
            raise Exception("Unknown case")

    def empty(self):
        return self.a == self.b

    def begin(self):
        if self.a = self.begin() and x <= self.end()

    def cover(self, rhs):
        a = min(self.begin(), rhs.begin())
        b = max(self.end(), rhs.end())

        if self.a = rhs.end():
            return Region(0)

        return Region(max(self.begin(), rhs.begin()), min(self.end(), rhs.end()))

    def intersects(self, rhs):
        lb = self.begin()
        le = self.end()
        rb = rhs.begin()
        re = rhs.end()

        return (
            (lb == rb and le == re) or
            (rb > lb and rb  lb and re  rb and lb  rb and le  view.size():
            return 0
        else:
            i = 0
            count = 0
            len_line = len(line)
            level = 0

            while True:
                if i >= len_line:
                    break
                if line[i] == " ":
                    i += 1
                    count += 1
                    if count == self.tab_size:
                        level += 1
                        count = 0
                elif line[i] == "\t":
                    level += 1
                else:
                    break

            if count != 0:
                level += 1
            return level


if __name__ == '__main__':
    import sys
    import textwrap

    app = QApplication(sys.argv)
    view = View()
    view.setText(textwrap.dedent("""\
                x - 0
            x - 3
            x - 3
                x - 4
            x - 3


    x - 1
     x - 2
      x - 2
        x - 2
            x - 3
            x - 3
                x - 4
            x - 3
    x - 1
                x - 4



x - 0
a
b
c
d
e
f
"""))

    view.show()
    app.exec_()

在上面的代码片段中,您可以看到我已经尝试复制一些Sublime函数。如果我的测试没有错,则indentation_level应该提供与Sublime View提供的输出相同的输出。

问题:您将如何修改上面的代码片段,以提供基于缩进的代码折叠(例如Sublime的代码折叠)?

在这里,您可以看到Sublime如何工作的示例:

当然,使用多重选择(在上面的mcve中已启用)时,适当的标识符也应该起作用,例如:

您可以查看Sublime中每个文档的更改如何完美/有效地更新缩进折叠级别

我的盒子的设置:

赢7

Python 3.6.4(x86)

PyQt5 == 5.12

QScintilla == 2.10.8

附言 我在互联网上找到了一个很好的有趣代码,可以很好地运行,https://github.com/pyQode/pyqode.core/blob/master/pyqode/core/api/folding.py问题是该代码是打算在上工作QPlainTextEditQSyntaxHighlighter所以我不太清楚如何调整它以在QScinScintilla小部件中工作



1> hidefromkgb..:

[删除了先前的答案,因为鉴于最后一个问题,编辑可能唯一具有历史价值的值;如果仍然感到好奇,请参阅编辑历史记录]

最后,优化版本-捆绑了80公里示例文本,以展示其性能。

from PyQt5.Qsci import QsciScintilla
from 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 


推荐阅读
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • 本文介绍了贝叶斯垃圾邮件分类的机器学习代码,代码来源于https://www.cnblogs.com/huangyc/p/10327209.html,并对代码进行了简介。朴素贝叶斯分类器训练函数包括求p(Ci)和基于词汇表的p(w|Ci)。 ... [详细]
  • 判断编码是否可立即解码的程序及电话号码一致性判断程序
    本文介绍了两个编程题目,一个是判断编码是否可立即解码的程序,另一个是判断电话号码一致性的程序。对于第一个题目,给出一组二进制编码,判断是否存在一个编码是另一个编码的前缀,如果不存在则称为可立即解码的编码。对于第二个题目,给出一些电话号码,判断是否存在一个号码是另一个号码的前缀,如果不存在则说明这些号码是一致的。两个题目的解法类似,都使用了树的数据结构来实现。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • Python瓦片图下载、合并、绘图、标记的代码示例
    本文提供了Python瓦片图下载、合并、绘图、标记的代码示例,包括下载代码、多线程下载、图像处理等功能。通过参考geoserver,使用PIL、cv2、numpy、gdal、osr等库实现了瓦片图的下载、合并、绘图和标记功能。代码示例详细介绍了各个功能的实现方法,供读者参考使用。 ... [详细]
  • WebSocket与Socket.io的理解
    WebSocketprotocol是HTML5一种新的协议。它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送 ... [详细]
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • ScrollView嵌套Collectionview无痕衔接四向滚动,支持自定义TitleView
    本文介绍了如何实现ScrollView嵌套Collectionview无痕衔接四向滚动,并支持自定义TitleView。通过使用MainScrollView作为最底层,headView作为上部分,TitleView作为中间部分,Collectionview作为下面部分,实现了滚动效果。同时还介绍了使用runtime拦截_notifyDidScroll方法来实现滚动代理的方法。具体实现代码可以在github地址中找到。 ... [详细]
  • EzPP 0.2发布,新增YAML布局渲染功能
    EzPP发布了0.2.1版本,新增了YAML布局渲染功能,可以将YAML文件渲染为图片,并且可以复用YAML作为模版,通过传递不同参数生成不同的图片。这个功能可以用于绘制Logo、封面或其他图片,让用户不需要安装或卸载Photoshop。文章还提供了一个入门例子,介绍了使用ezpp的基本渲染方法,以及如何使用canvas、text类元素、自定义字体等。 ... [详细]
  • 在IDEA中运行CAS服务器的配置方法
    本文介绍了在IDEA中运行CAS服务器的配置方法,包括下载CAS模板Overlay Template、解压并添加项目、配置tomcat、运行CAS服务器等步骤。通过本文的指导,读者可以轻松在IDEA中进行CAS服务器的运行和配置。 ... [详细]
  • 求解连通树的最小长度及优化
    本文介绍了求解连通树的最小长度的方法,并通过四边形不等式进行了优化。具体方法为使用状态转移方程求解树的最小长度,并通过四边形不等式进行优化。 ... [详细]
  • Python15行代码实现免费发送手机短信,推送消息「建议收藏」
    Python15行代码实现免费发 ... [详细]
  • 在搜索数据库中的数据时,您可以使用SQL通配符。SQL通配符在搜索数据库中的数据时,SQL通配符可以替代一个或多个字符。SQL通配符必须与LIKE运算符 ... [详细]
author-avatar
719苗苗113
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有