I am trying to make a simple texteditor with basic syntax highlighting, code completion and clickable functions & variables in PyQt5. My best hope to achieve this is using the QScintilla port
for PyQt5.
I have found the following QScintilla-based texteditor example on the Eli Bendersky website (http://eli.thegreenplace.net/2011/04/01/sample-using-qscintilla-with-pyqt, Victor S. has adapted it to PyQt5). I think this example is a good starting point:
#-------------------------------------------------------------------------
# qsci_simple_pythoneditor.pyw
#
# QScintilla sample with PyQt
#
# Eli Bendersky ([email protected])
# 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_()
Just copy-paste this code into an empty .py
file, and run it. You should get the following simple texteditor appearing on your display:
Notice how perfect the syntax highlighting is! QScintilla certainly did some parsing on the background to achieve that.
Is it possible to make clickable functions & variables for this texteditor? Every self-respecting IDE has it. You click on a function, and the IDE jumps to the function definition. The same for variables. I would like to know:
- Does QScintilla support clickable functions & variables?
- If not, is it possible to import another python module that implements this feature in the QScintilla texteditor?
EDIT :
λuser noted the following:
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.
I guess that writing such wrapper for ctags is now on my TODO list. The very first step is to get a reaction (Qt signal) when the user clicks on a function or variable. And perhaps the function/variable should turn a bit blueish when you hover with the mouse over it, to notify the user that it is clickable. I already tried to achieve this, but am held back by the shortage of QScintilla documentation.
So let us trim down the question to: How do you make a function or variable in the QScintilla texteditor clickable (with clickable defined as 'something happens')
EDIT :
I just returned to this question now - several months later. I have been cooperating with my friend Matic Kukovec to design a website about QScintilla. It is a beginner-friendly tutorial on how to use it:
I hope this initiative fills the gap of lacking documentation.
ctags
, it is still going to be a lot of work incorporating into a text editor. – Sargassoctags
. Do you have an idea on how to get this first step done? QScintilla documentation is very poor... – DrainQPoint
. (PS: the way to grok the documentation, is to read the Scintilla docs first and then go back to the QScintilla docs to see what high-level APIs are provided. The SciTE docs are also sometimes useful). – SargassoPyQt5.Qsci
, I have to executepip install QScintilla
or I will gotModuleNotFoundError: No module named 'PyQt5.Qsci'
error, see riverbankcomputing.com/software/qscintilla, pypi.org/project/QScintilla – Intervalometer