]> danix's work - publisher.git/commitdiff
feat: multi-token tag autocomplete in FrontmatterEditor
authorDanilo M. <redacted>
Sun, 3 May 2026 14:09:26 +0000 (16:09 +0200)
committerDanilo M. <redacted>
Sun, 3 May 2026 14:09:26 +0000 (16:09 +0200)
Replace single-token QCompleter with MultiTokenCompleter that
completes each comma-separated tag independently. Activating a
suggestion inserts the completed tag and positions cursor after
a trailing ", " separator for immediate next-tag input.

Co-Authored-By: Claude Sonnet 4.6 <redacted>
ui/frontmatter_editor.py

index 3b4b690dfa3642ab34a1cda4f56bc4152c4cb1fc..ce7035596c78ee7f9c150b59a47b9873bf777c07 100644 (file)
@@ -10,6 +10,41 @@ from core.models import Article, ARTICLE_TYPES
 from core.frontmatter import write_frontmatter
 from core.taxonomy import load_taxonomy
 
+class MultiTokenCompleter(QCompleter):
+    """QCompleter that completes only the last comma-separated token."""
+
+    def __init__(self, tags: list[str], parent=None):
+        super().__init__(tags, parent)
+        self.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
+
+    def attach(self, line_edit):
+        self.setWidget(line_edit)
+        line_edit.textEdited.connect(self._on_text_edited)
+        self.activated[str].connect(self._on_activated)
+
+    def _on_text_edited(self, text: str):
+        token = text.split(",")[-1].lstrip()
+        if token:
+            self.setCompletionPrefix(token)
+            self.complete()
+        else:
+            self.popup().hide()
+
+    def _on_activated(self, completion: str):
+        widget = self.widget()
+        if widget is None:
+            return
+        current = widget.text()
+        if "," in current:
+            prefix = current.rsplit(",", 1)[0]
+            new_text = prefix + ", " + completion + ", "
+        else:
+            new_text = completion + ", "
+        widget.setText(new_text)
+        widget.setCursorPosition(len(new_text))
+        self.popup().hide()
+
+
 class FrontmatterEditor(QDialog):
     def __init__(self, article: Article, blog_root: Path, parent=None):
         super().__init__(parent)
@@ -45,9 +80,7 @@ class FrontmatterEditor(QDialog):
                 self._fields[key] = widget
             elif key == "tags":
                 widget = QLineEdit(", ".join(str(v) for v in val) if isinstance(val, list) else str(val))
-                completer = QCompleter(known_tags)
-                completer.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
-                widget.setCompleter(completer)
+                MultiTokenCompleter(known_tags, widget).attach(widget)
                 self._fields[key] = widget
             else:
                 widget = QLineEdit(str(val))