Przejdź do treści

Dokumentacja zdarzeń

Każde zdarzenie, które host publikuje dla wtyczek natywnych (PluginEvents.h), dociera też do Pythona — z jednym wyjątkiem opisanym niżej. Każdy temat dostarcza do Twojego handlera mały typowany dataclass. Dataclassy zdefiniowane są w Python/mte/events.py i są importowalne z pakietu najwyższego poziomu mte.

Tabela temat ↔ dataclass

Temat Dataclass ładunku Pola Dekorator
document.opened mte.DocumentOpened document: int, path: str on_document_opened
document.closed mte.DocumentClosed document: int on_document_closed
document.saved mte.DocumentSaved document: int on_document_saved
document.encodingChanged mte.DocumentEncodingChanged document: int, encoding: mte.DocumentEncoding on_document_encoding_changed
document.lineEndingChanged mte.DocumentLineEndingChanged document: int, ending: mte.LineEnding on_document_line_ending_changed
document.modifiedChanged mte.DocumentModifiedChanged document: int, modified: bool on_document_modified_changed
document.activeChanged mte.ActiveDocumentChanged document: int on_active_document_changed
text.changed mte.TextChanged document, position, added_bytes, removed_bytes on_text_changed
selection.changed mte.SelectionChanged document: int on_selection_changed
settings.changed mte.SettingsChanged scope: str ("" = cały edytor, "plugins/<id>") on_settings_changed
theme.changed mte.ThemeChanged variant: str ("light" / "dark" / "") on_theme_changed
margin.clicked mte.MarginClicked document: int, line: int, margin: str ("symbol"), modifiers: int (bity mte.MODIFIER_SHIFT / MODIFIER_CONTROL / MODIFIER_ALT / MODIFIER_META) — kliknięcie w kolumnie zakładek, zobacz ctx.line_markers on_margin_clicked
workspace.rootChanged mte.WorkspaceRootChanged root: str ("" = folder zamknięty) on_workspace_root_changed
workspace.filesChanged mte.WorkspaceFilesChanged files: list[mte.WorkspaceFile] (path, display_path) on_workspace_files_changed
command.shortcutChanged mte.CommandShortcutChanged command_id: str, sequence: str on_command_shortcut_changed
host.windowShown mte.HostWindowShown (brak pól) — raz na uruchomienie, po pierwszej klatce on_host_window_shown
app.aboutToQuit mte.AppAboutToQuit (brak pól) on_app_about_to_quit

document to nieprzezroczyste całkowitoliczbowe id przydzielane przez hosta. Porównuj id operatorem ==; nie utrwalaj ich między restartami edytora. text.changed odpala się przy każdej edycji — ten handler trzymaj trywialny.

Subskrypcja przez dekorator (sugar)

Zalecana — nazwa dekoratora odpowiada tematowi, a typ ładunku jest wnioskowany:

import mte

def register(ctx):

    @ctx.events.on_document_saved
    def _saved(ev: mte.DocumentSaved):
        ctx.log.info(f"saved doc {ev.document}")

    @ctx.events.on_document_opened
    def _opened(ev: mte.DocumentOpened):
        ctx.log.info(f"opened {ev.document} at {ev.path}")

    @ctx.events.on_app_about_to_quit
    def _quit(_ev: mte.AppAboutToQuit):
        ctx.log.info("editor is closing")

Subskrypcja przez surowe API

def _saved(ev):
    ctx.log.info(f"saved {ev.document}")

handler_id = ctx.events.subscribe("document.saved", _saved)
  • Zwraca lokalnie przydzielony handler_id (string postaci "py-ev/N").
  • Nieznane tematy rzucają ValueError w momencie subskrypcji — bez cichego no-op.

Wypisz się z subskrypcji, gdy przestaje Cię interesować:

ctx.events.unsubscribe(handler_id)

Uwaga: po unsubscribe host przestaje dostarczać Ci ten temat, ale lokalny dyspozytor workera zachowuje swój wpis aż do zamknięcia wtyczki. Nie polegaj na unsubscribe przy sprzątaniu pamięci — to sygnał polityki, a nie prymityw odśmiecania pamięci.

Semantyka dostarczania

  • Zdarzenia odpalają się po zakończeniu odpowiadającej im akcji. Przy document.saved plik jest już na dysku. Przy document.closed id dokumentu jest już nieprawidłowe.
  • Wielu subskrybentów tego samego tematu odpala się wszystkich, w niezdefiniowanej kolejności.
  • Wyjątki rzucone w Twoim handlerze są łapane przez workera i zapisywane na stderr (widoczne w logu hosta jako [worker stderr] …). Wadliwy handler nie powstrzymuje odpalania pozostałych subskrybentów.
  • Dataclassy ładunków są niemutowalne; nie modyfikuj pól ev.

Publikowanie

ctx.events.publish(topic, payload) kładzie zdarzenie na wspólnej szynie, gdzie odbierają je zarówno subskrybenci natywni, jak i pythonowi. Akceptowane są tylko dwa tematy, które mają być publikowane przez wtyczkę — para workspace, którą wtyczka Obszar roboczy rozgłasza dla Znajdź w plikach i Palety poleceń:

ctx.events.publish("workspace.rootChanged", {"root": "/home/me/project"})
ctx.events.publish("workspace.filesChanged", {"files": [
    {"path": "/home/me/project/a.txt", "displayPath": "a.txt"},
]})

Każdy inny temat rzuca ValueError: pozostałe to stwierdzenia faktów należące do hosta (dokument został zapisany, motyw się zmienił), których wtyczka nie ma prawa ogłaszać. Do komunikacji wtyczka–wtyczka poza tym zarejestruj polecenie i pozwól drugiej stronie je wywołać.

Niedostępne

Dwa zdarzenia hosta nie mają tematu w Pythonie:

  • document.aboutToSave: host publikuje je synchronicznie, blokując zapis do powrotu każdego subskrybenta, a honorowanie tego przez RPC workera wymaga takiego samego limitu czasu jak providery uzupełniania, zanim będzie bezpieczne. Wtyczki natywne mogą go używać już dziś.
  • DocumentAboutToClose — z założenia tylko natywne. Cała jego obietnica to to, że dokument da się jeszcze odczytać wewnątrz obsługi, a dostarczanie do wtyczki Pythona jest asynchroniczne, więc obsługa uruchomiłaby się już po zamknięciu. Używaj document.closed i na bieżąco utrzymuj to, czego potrzebujesz o dokumencie, na podstawie wcześniejszych zdarzeń, zamiast odczytywać to przy zamknięciu.