Pular para conteúdo

Referência de eventos

Todo evento que o host publica para plugins nativos (PluginEvents.h) chega também ao Python, com uma exceção anotada abaixo. Cada tópico entrega uma pequena dataclass tipada ao seu manipulador. As dataclasses são definidas em Python/mte/events.py e podem ser importadas do pacote mte de nível superior.

Tabela de tópico ↔ dataclass

Tópico Dataclass da carga útil Campos Decorador
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 ("" = de todo o editor, "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 (bits mte.MODIFIER_SHIFT / MODIFIER_CONTROL / MODIFIER_ALT / MODIFIER_META) — um clique na coluna de marcadores, veja ctx.line_markers on_margin_clicked
workspace.rootChanged mte.WorkspaceRootChanged root: str ("" = pasta fechada) 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 (sem campos) — uma vez por execução, depois do primeiro quadro on_host_window_shown
app.aboutToQuit mte.AppAboutToQuit (sem campos) on_app_about_to_quit

document é um id inteiro opaco atribuído pelo host. Compare ids com ==; não os persista entre reinícios do editor. O text.changed dispara a cada edição — mantenha aquele manipulador trivial.

Assinar por decorador açucarado

Recomendado — o nome do decorador coincide com o tópico e o tipo da carga útil é inferido:

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")

Assinar pela API bruta

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

handler_id = ctx.events.subscribe("document.saved", _saved)
  • Devolve o handler_id alocado localmente (uma cadeia "py-ev/N").
  • Tópicos desconhecidos levantam ValueError na hora da assinatura — nada de silêncio.

Cancele a assinatura quando não se importar mais:

ctx.events.unsubscribe(handler_id)

Observação: depois de unsubscribe, o host para de entregar o tópico a você, mas o despachante local do trabalhador mantém a entrada dele até o plugin encerrar. Não conte com o unsubscribe para limpeza de memória — ele é um sinal de política, não uma primitiva de coleta de lixo.

Semântica de entrega

  • Os eventos disparam depois que a ação correspondente foi concluída. No document.saved, o arquivo já está no disco. No document.closed, o id do documento já é inválido.
  • Vários assinantes do mesmo tópico disparam todos, em ordem indefinida.
  • Exceções levantadas no seu manipulador são capturadas pelo trabalhador e escritas em stderr (visíveis no log do host como [worker stderr] …). Um manipulador que se comporta mal não impede que os outros assinantes disparem.
  • As dataclasses de carga útil são imutáveis; não altere os campos de ev.

Publicando

ctx.events.publish(topic, payload) coloca um evento no barramento compartilhado, onde assinantes nativos e Python o recebem igualmente. Apenas os dois tópicos que devem ser publicados por um plugin são aceitos — o par do espaço de trabalho, que o plugin Espaço de trabalho transmite para o Localizar em arquivos e a paleta de comandos:

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

Qualquer outro tópico levanta ValueError: os demais são afirmações de fato do próprio host (um documento foi salvo, o tema mudou) que um plugin não tem por que declarar. Para mensagens entre plugins além dessas, registre um comando e faça o outro lado invocá-lo.

Não disponível

Dois eventos do host não têm tópico em Python:

  • document.aboutToSave: o host o publica de forma síncrona, com o salvamento bloqueado até todo assinante retornar, e honrar isso pelo RPC do trabalhador exige o mesmo tratamento de prazos dos provedores de autocompletar antes de ser seguro. Plugins nativos podem usá-lo hoje.
  • DocumentAboutToClose — só nativo, por projeto. Toda a sua promessa é que o documento ainda pode ser lido dentro do manipulador, e a entrega a um plugin Python é assíncrona, então o manipulador rodaria depois do fechamento. Use document.closed em vez disso e mantenha atualizado o que você precisa saber de um documento a partir dos eventos anteriores, em vez de lê-lo no fechamento.