aboutsummaryrefslogtreecommitdiffstats
path: root/Lib/defconQt/scriptingWindow.py
blob: 2448d487546a543014abd13502ac35b1cf08cc7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from defconQt.baseCodeEditor import CodeEditor, CodeHighlighter
from keyword import kwlist
import traceback
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor, QFont, QKeySequence, QTextCharFormat, QTextCursor
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenu, QPlainTextEdit

class MainScriptingWindow(QMainWindow):
    def __init__(self):
        super(MainScriptingWindow, self).__init__()

        self.editor = PythonEditor(parent=self)
        self.resize(600, 500)

        fileMenu = QMenu("&File", self)
        fileMenu.addAction("&Run…", self.runScript, "Ctrl+R")
        fileMenu.addSeparator()
        fileMenu.addAction("E&xit", self.close, QKeySequence.Quit)
        self.menuBar().addMenu(fileMenu)

        self.setCentralWidget(self.editor)
        self.setWindowTitle("[*]Untitled.py")
        # arm `undoAvailable` to `setWindowModified`
        self.editor.undoAvailable.connect(self.setWindowModified)

    def runScript(self):
        app = QApplication.instance()
        script = self.editor.toPlainText()
        global_vars = {
            "__builtins__": __builtins__,
            "AllFonts": app.allFonts,
            "CurrentFont": app.currentFont,
        }
        try:
            code = compile(script, "<string>", "exec")
            exec(code, global_vars)
        except:
            print(traceback.format_exc())

class PythonEditor(CodeEditor):
    autocomplete = {
        Qt.Key_ParenLeft: "()",
        Qt.Key_BracketLeft: "[]",
        Qt.Key_BraceLeft: "{}",
        Qt.Key_Apostrophe: "''",
        Qt.Key_QuoteDbl: '""',
    }

    def __init__(self, text=None, parent=None):
        super(PythonEditor, self).__init__(text, parent)
        self.openBlockDelimiter = ":"
        self.highlighter = PythonHighlighter(self.document())

    def keyPressEvent(self, event):
        key = event.key()
        if key in self.autocomplete.keys():
            super(PythonEditor, self).keyPressEvent(event)
            cursor = self.textCursor()
            cursor.insertText(self.autocomplete[key][-1])
            cursor.movePosition(QTextCursor.PreviousCharacter)
            self.setTextCursor(cursor)
            event.accept()
            return
        elif key == Qt.Key_Backspace:
            cursor = self.textCursor()
            ok = cursor.movePosition(QTextCursor.PreviousCharacter)
            if ok:
                ok = cursor.movePosition(QTextCursor.NextCharacter, QTextCursor.KeepAnchor, 2)
                if ok and cursor.selectedText() in self.autocomplete.values():
                    cursor.removeSelectedText()
                    event.accept()
                    return
        super(PythonEditor, self).keyPressEvent(event)

class PythonHighlighter(CodeHighlighter):
    def __init__(self, parent=None):
        super(PythonHighlighter, self).__init__(parent)

        keywordFormat = QTextCharFormat()
        keywordFormat.setForeground(QColor(34, 34, 34))
        keywordFormat.setFontWeight(QFont.Bold)
        self.highlightingRules.append(("\\b(%s)\\b" % ("|".join(kwlist)), keywordFormat))

        singleLineCommentFormat = QTextCharFormat()
        singleLineCommentFormat.setForeground(Qt.darkGray)
        self.highlightingRules.append(("#[^\n]*", singleLineCommentFormat))

        classOrFnNameFormat = QTextCharFormat()
        classOrFnNameFormat.setForeground(QColor(96, 106, 161))
        self.highlightingRules.append(("(?<=\\bclass\\s|def\\s\\b)\\s*(\\w+)", classOrFnNameFormat))

        quotationFormat = QTextCharFormat()
        quotationFormat.setForeground(QColor(223, 17, 68))
        self.highlightingRules.append(("'.*'|[\"]{1,3}.*[\"]{1,3}", quotationFormat))