python - PyQt5 中基于 QScintilla 的文本编辑器,具有可点击的函数和变量

标签 python python-3.x pyqt pyqt5 qscintilla

我正在尝试在 PyQt5 中制作一个简单的文本编辑器,它具有基本的语法突出显示、代码完成以及可点击的函数和变量。我最大的希望是使用 QScintilla 端口
适用于 PyQt5。
我在 Eli Bendersky 网站上找到了以下基于 QScintilla 的文本编辑器示例(http://eli.thegreenplace.net/2011/04/01/sample-using-qscintilla-with-pyqt,Victor S. 已将其改编为 PyQt5)。我认为这个例子是一个很好的起点:

#-------------------------------------------------------------------------
# qsci_simple_pythoneditor.pyw
#
# QScintilla sample with PyQt
#
# Eli Bendersky (eliben@gmail.com)
# This code is in the public domain
#-------------------------------------------------------------------------
import sys

import sip
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.Qsci import QsciScintilla, QsciLexerPython


class SimplePythonEditor(QsciScintilla):
    ARROW_MARKER_NUM = 8

    def __init__(self, parent=None):
        super(SimplePythonEditor, self).__init__(parent)

        # Set the default font
        font = QFont()
        font.setFamily('Courier')
        font.setFixedPitch(True)
        font.setPointSize(10)
        self.setFont(font)
        self.setMarginsFont(font)

        # Margin 0 is used for line numbers
        fontmetrics = QFontMetrics(font)
        self.setMarginsFont(font)
        self.setMarginWidth(0, fontmetrics.width("00000") + 6)
        self.setMarginLineNumbers(0, True)
        self.setMarginsBackgroundColor(QColor("#cccccc"))

        # Clickable margin 1 for showing markers
        self.setMarginSensitivity(1, True)
#        self.connect(self,
#            SIGNAL('marginClicked(int, int, Qt::KeyboardModifiers)'),
#            self.on_margin_clicked)
        self.markerDefine(QsciScintilla.RightArrow,
            self.ARROW_MARKER_NUM)
        self.setMarkerBackgroundColor(QColor("#ee1111"),
            self.ARROW_MARKER_NUM)

        # Brace matching: enable for a brace immediately before or after
        # the current position
        #
        self.setBraceMatching(QsciScintilla.SloppyBraceMatch)

        # Current line visible with special background color
        self.setCaretLineVisible(True)
        self.setCaretLineBackgroundColor(QColor("#ffe4e4"))

        # Set Python lexer
        # Set style for Python comments (style number 1) to a fixed-width
        # courier.
        #

        lexer = QsciLexerPython()
        lexer.setDefaultFont(font)
        self.setLexer(lexer)

        text = bytearray(str.encode("Arial"))
# 32, "Courier New"         
        self.SendScintilla(QsciScintilla.SCI_STYLESETFONT, 1, text)

        # Don't want to see the horizontal scrollbar at all
        # Use raw message to Scintilla here (all messages are documented
        # here: http://www.scintilla.org/ScintillaDoc.html)
        self.SendScintilla(QsciScintilla.SCI_SETHSCROLLBAR, 0)

        # not too small
        self.setMinimumSize(600, 450)

    def on_margin_clicked(self, nmargin, nline, modifiers):
        # Toggle marker for the line the margin was clicked on
        if self.markersAtLine(nline) != 0:
            self.markerDelete(nline, self.ARROW_MARKER_NUM)
        else:
            self.markerAdd(nline, self.ARROW_MARKER_NUM)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    editor = SimplePythonEditor()
    editor.show()
    editor.setText(open(sys.argv[0]).read())
    app.exec_()

只需将这段代码复制粘贴到一个空的 .py 文件中,然后运行它。您应该会在显示器上看到以下简单的文本编辑器:

enter image description here

注意语法高亮是多么完美! QScintilla 当然在后台做了一些解析来实现这一点。
是否可以为这个文本编辑器制作可点击的函数和变量?每个自重的 IDE 都有它。您单击一个函数,IDE 会跳转到函数定义处。变量也一样。我想知道:

  • QScintilla 是否支持可点击的函数和变量
  • 如果没有,是否可以在 QScintilla 文本编辑器中导入另一个实现此功能的 python 模块?

编辑:
λuser 注意到以下内容:

Clickable function names require full parsing with a much deeper knowledge of a programming language [..]
This is way beyond the scope of Scintilla/QScintilla. Scintilla provides a way to react when the mouse clicks somewhere on the text, but the logic of "where is the definition of a function" is not in Scintilla and probably never will be.
However, some projects are dedicated to this task, like ctags. You could simply write a wrapper around this kind of tool.

我想为 ctags 编写这样的包装器现在在我的 TODO 列表中。第一步是在用户单击函数或变量时获得 react (Qt 信号)。当您将鼠标悬停在函数/变量上时,函数/变量可能会变成蓝色,以通知用户它是可点击的。我已经尝试过实现这一点,但由于缺少 QScintilla 文档而受阻。

所以让我们将问题精简为:如何使 QScintilla 文本编辑器中的函数或变量可点击(可点击定义为“发生某事”)


编辑:
我现在才回到这个问题——几个月后。我一直在和我的 friend Matic Kukovec 合作设计一个关于 QScintilla 的网站。这是一个关于如何使用它的初学者友好教程:

enter image description here

https://qscintilla.com/

我希望这一举措能够填补缺乏文档的空白。

最佳答案

语法突出显示只是在源文件上运行词法分析器以查找标记,然后为其添加样式的问题。词法分析器对编程语言有非常基本的了解,它只了解什么是数字文字、关键字、运算符、注释,仅此而已。这是一项稍微简单的工作,只需使用正则表达式即可完成。

另一方面,可点击的函数名称需要对编程语言有更深入的了解才能进行完整解析,例如这是变量的声明还是使用等。此外,这可能需要解析当前编辑器未打开的其他源文件。

这远远超出了 Scintilla/QScintilla 的范围。 Scintilla 提供了一种在鼠标单击文本某处时使用react的方法,但“函数的定义在哪里”的逻辑不在 Scintilla 中,而且可能永远不会。

但是,有些项目专门用于此任务,例如 ctags .您可以简单地围绕这种工具编写一个包装器。

关于python - PyQt5 中基于 QScintilla 的文本编辑器,具有可点击的函数和变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40002373/

相关文章:

python - 在Python中初始化计算潮湿空气密度的类和类方法

python - 每次引入新 key 时如何为列表创建新变量?

python - Tensorflow 在批处理上是独一无二的

Python:如何编辑数组中元素的顺序?

python - 如何在QTableView单元角绘制一个三角形以显示可以从列表中选择模型数据?

python - 如何从 PyQt5 中动态生成的复选框中删除标签?

python - 移动 QSlider 到鼠标点击位置

python - 从 Python 输出 XML 的最简单的非内存密集型方法是什么?

python - 查看标签之间的 html 文本(python、lxml、urllib、xpath)

python - 如何在Python中合并读取文档中的每3行