From: Danilo M. Date: Sun, 3 May 2026 14:09:26 +0000 (+0200) Subject: feat: multi-token tag autocomplete in FrontmatterEditor X-Git-Tag: v1.3~3 X-Git-Url: https://git.danix.xyz/?a=commitdiff_plain;h=365b911ba1288ccfb428602ba765750ad9d0a139;p=publisher.git feat: multi-token tag autocomplete in FrontmatterEditor 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 --- diff --git a/ui/frontmatter_editor.py b/ui/frontmatter_editor.py index 3b4b690..ce70355 100644 --- a/ui/frontmatter_editor.py +++ b/ui/frontmatter_editor.py @@ -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))