You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Python的自定义编程语言编辑器多词变量自动补全实现咨询

Hey there! Let’s break down how to tackle your two core challenges—autocompleting those quirky quoted space-containing variables and managing them in a separate table window—using Python with PyQt/PySide6. I’ll cover two practical approaches based on the tools you’ve already explored.


Approach 1: QPlainTextEdit + QCompleter (Beginner-Friendly)

Since you’re still learning Python, this method uses more familiar PySide6 widgets and gives you full control over the autocomplete logic, which is perfect for your space-in-variable-names use case.

Step 1: Build the Variable Management Table

First, create a separate widget with a table to add/edit variables. Any changes here will automatically update the autocomplete list.

Step 2: Customize Autocomplete for Quoted Variables

We’ll use QCompleter to handle autocomplete, but tweak its behavior to trigger only when the user is inside unclosed single quotes, and insert variables with proper quoting.

Full Code Example

from PySide6.QtWidgets import (QApplication, QMainWindow, QPlainTextEdit, 
                               QCompleter, QTableWidget, QTableWidgetItem,
                               QWidget, QVBoxLayout, QSplitter, QPushButton)
from PySide6.QtCore import QStringListModel, Qt

class VariableManager(QWidget):
    def __init__(self, completer_model, parent=None):
        super().__init__(parent)
        self.completer_model = completer_model
        layout = QVBoxLayout(self)
        
        # Table for variables
        self.table = QTableWidget()
        self.table.setColumnCount(1)
        self.table.setHorizontalHeaderLabels(["Variables"])
        layout.addWidget(self.table)
        
        # Button to add new variable rows
        add_btn = QPushButton("Add New Variable")
        add_btn.clicked.connect(self.add_empty_variable)
        layout.addWidget(add_btn)
        
        # Update autocomplete whenever table changes
        self.table.itemChanged.connect(self.sync_completer)
        
        # Add a sample variable to start
        self.add_empty_variable()
        self.table.setItem(0, 0, QTableWidgetItem('THIS IS A VARIABLE'))

    def add_empty_variable(self):
        row = self.table.rowCount()
        self.table.insertRow(row)
        item = QTableWidgetItem("")
        item.setFlags(item.flags() | Qt.ItemIsEditable)
        self.table.setItem(row, 0, item)

    def sync_completer(self):
        # Collect all valid variables from the table
        var_list = []
        for row in range(self.table.rowCount()):
            item = self.table.item(row, 0)
            if item and item.text().strip():
                var_list.append(item.text())
        self.completer_model.setStringList(var_list)

class CustomTextEditor(QPlainTextEdit):
    def __init__(self, completer, parent=None):
        super().__init__(parent)
        self.completer = completer
        self.completer.setWidget(self)
        self.completer.activated.connect(self.insert_completed_variable)

    def insert_completed_variable(self, completion):
        cursor = self.textCursor()
        prev_text = self.toPlainText()[:cursor.position()]
        
        # Check if we're inside an unclosed single quote
        last_quote_idx = prev_text.rfind("'")
        if last_quote_idx != -1 and prev_text.count("'") % 2 == 1:
            # Replace partial text between quote and cursor with completion
            cursor.setPosition(last_quote_idx + 1)
            cursor.movePosition(cursor.End, cursor.KeepAnchor)
            cursor.insertText(completion)
            # Add closing quote if missing
            if not self.toPlainText()[cursor.position():].startswith("'"):
                cursor.insertText("'")
        else:
            # Insert full quoted variable if not in quote context
            cursor.insertText(f"'{completion}'")

    def keyPressEvent(self, event):
        # Let completer handle tab/enter when popup is visible
        if self.completer.popup().isVisible():
            if event.key() in (Qt.Key_Tab, Qt.Key_Enter, Qt.Key_Return):
                event.ignore()
                return
        
        super().keyPressEvent(event)
        
        # Trigger autocomplete only inside unclosed single quotes
        cursor = self.textCursor()
        prev_text = self.toPlainText()[:cursor.position()]
        quote_count = prev_text.count("'")
        
        if quote_count % 2 == 1:
            # Get partial variable text under cursor to filter completer
            cursor.select(cursor.WordUnderCursor)
            self.completer.setCompletionPrefix(cursor.selectedText())
            # Position popup next to cursor
            cr = self.cursorRect()
            cr.setWidth(self.completer.popup().sizeHintForColumn(0) + self.completer.popup().verticalScrollBar().sizeHint().width())
            self.completer.complete(cr)
        else:
            self.completer.popup().hide()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Custom Language Editor")
        self.resize(800, 600)
        
        # Split window into editor and variable manager
        splitter = QSplitter(Qt.Horizontal)
        
        # Setup autocomplete model and completer
        var_model = QStringListModel()
        completer = QCompleter(var_model)
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        
        # Add editor and variable manager to splitter
        self.editor = CustomTextEditor(completer)
        splitter.addWidget(self.editor)
        
        self.var_manager = VariableManager(var_model)
        splitter.addWidget(self.var_manager)
        
        self.setCentralWidget(splitter)

if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

Approach 2: QScintilla (Powerful Editor Option)

If you want to stick with QScintilla for its advanced code editing features, you can override its default autocomplete behavior to support your variable format. The key is manually triggering autocomplete when in a quote context and feeding it your custom variable list.

Full Code Example

from PySide6.QtWidgets import (QApplication, QMainWindow, QSplitter, 
                               QTableWidget, QTableWidgetItem, QWidget, 
                               QVBoxLayout, QPushButton)
from PySide6.QtCore import Qt
import PySide6.Qsci as Qsci

class VariableManager(QWidget):
    def __init__(self, editor, parent=None):
        super().__init__(parent)
        self.editor = editor
        layout = QVBoxLayout(self)
        
        self.table = QTableWidget()
        self.table.setColumnCount(1)
        self.table.setHorizontalHeaderLabels(["Variables"])
        layout.addWidget(self.table)
        
        add_btn = QPushButton("Add New Variable")
        add_btn.clicked.connect(self.add_empty_variable)
        layout.addWidget(add_btn)
        
        self.table.itemChanged.connect(self.sync_autocomplete)
        self.add_empty_variable()
        self.table.setItem(0, 0, QTableWidgetItem('THIS IS A VARIABLE'))

    def add_empty_variable(self):
        row = self.table.rowCount()
        self.table.insertRow(row)
        item = QTableWidgetItem("")
        item.setFlags(item.flags() | Qt.ItemIsEditable)
        self.table.setItem(row, 0, item)

    def sync_autocomplete(self):
        var_list = []
        for row in range(self.table.rowCount()):
            item = self.table.item(row, 0)
            if item and item.text().strip():
                # Wrap variables in quotes so autocomplete inserts them correctly
                var_list.append(f"'{item.text()}'")
        self.editor.autoCompleteList(var_list)

class CustomQsciEditor(Qsci.QsciScintilla):
    def __init__(self, parent=None):
        super().__init__(parent)
        # Basic editor setup
        self.setUtf8(True)
        self.setAutoCompletionThreshold(1)
        self.setAutoCompletionSource(Qsci.QsciScintilla.AcsAPIs)

    def keyPressEvent(self, event):
        super().keyPressEvent(event)
        
        # Check if we're inside unclosed single quotes
        cursor_pos = self.currentPosition()
        prev_text = self.text()[:cursor_pos]
        quote_count = prev_text.count("'")
        
        if quote_count % 2 == 1:
            # Trigger autocomplete when typing inside quotes
            self.autoComplete()
        else:
            # Cancel autocomplete if outside quotes
            self.autoCompleteCancel()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QScintilla Custom Editor")
        self.resize(800, 600)
        
        splitter = QSplitter(Qt.Horizontal)
        self.editor = CustomQsciEditor()
        splitter.addWidget(self.editor)
        
        self.var_manager = VariableManager(self.editor)
        splitter.addWidget(self.var_manager)
        
        self.setCentralWidget(splitter)

if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

Quick Tips for Your Workflow

  • For the QCompleter approach, you can add validation to the table to prevent duplicate variables.
  • With QScintilla, you can further customize syntax highlighting by creating a custom lexer for your old language.
  • Both examples let you edit variables in the table and see changes reflected in autocomplete instantly.

内容的提问来源于stack exchange,提问作者InfiniteNopes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 06:40:08