Vai al contenuto

Documentazione di plugin.json

Ogni plugin Python dichiara la propria identità, il punto di ingresso e la collocazione nella barra dei menu in un file plugin.json accanto al proprio main.py. È lo stesso schema che usa il lato C++; solo i campi entry e module sono specifici di Python.

Esempio

{
  "id":          "org.example.wordcount",
  "name":        "Word Count",
  "version":     "1.0.0",
  "vendor":      "Example, Inc.",
  "description": "Counts words and characters in the active document.",
  "apiVersion":  1,
  "entry":       "python",
  "module":      "main",
  "pyRequires":  [],
  "order":       900,
  "menus": [
    { "title": "Plugins", "barPriority": 570, "itemPriority": 100 }
  ]
}

Campi

Obbligatori

Campo Tipo Note
id stringa Identificatore univoco in DNS inverso. Usato ovunque: abilitazione / disabilitazione, righe di log, impostazioni per plugin. Non deve cambiare tra le versioni.
apiVersion intero Deve essere uguale a MTE_PLUGIN_API_VERSION dell'host. Attualmente 1. Una discordanza emerge nella pagina Plugin e il plugin viene elencato ma non caricato.
entry stringa Dev'essere "python" per passare dal backend Python. "native" o l'assenza del campo passano dal caricatore Qt.
module stringa Nome del modulo Python che contiene register(ctx). Se è "main", il worker cerca main.py dentro la cartella del plugin. I nomi di pacchetto con punti ("src.main") sono un'estensione futura: la fase 1 supporta solo nomi piatti.

Consigliati

Campo Tipo Note
name stringa Nome leggibile mostrato nella pagina Plugin.
version stringa Semver; per il resto forma libera.
vendor stringa Autore / organizzazione. Mostrato nella pagina Plugin.
description stringa Una o due righe. Mostrata nella pagina Plugin.

Facoltativi

Campo Tipo Note
order intero Ordine di caricamento tra i plugin; più basso carica prima. Predefinito 1000. I pari merito si risolvono con id. requires ha la precedenza.
requires array di stringhe Id dei plugin senza i quali questo plugin non può funzionare (nativi o Python indifferentemente), per esempio ["org.mte.lsp"] — non pacchetti pip, quelli vanno in pyRequires. Vengono avviati prima di questo plugin qualunque cosa dica order; se uno manca, è disattivato, bloccato dalla licenza o non è stato caricato, questo plugin non viene avviato affatto e Preferenze → Estensioni dice quale gli serve e perché. Stesso significato che per un plugin nativo.
apiMinorVersion intero La versione minor minima dell'API dell'host di cui questo plugin ha bisogno (predefinito 0). Un plugin Python non ha un info() compilato, quindi questa è la sua unica dichiarazione: indica la minor della chiamata più recente che usi. Un host più vecchio mostra il plugin come «Richiede una versione più recente di OctoEdit» e non lo avvia.
menus array di oggetti Vedi sotto.
pyRequires array di stringhe Stringhe di requisito pip (per esempio ["requests>=2.31"]). Al primo avvio del plugin l'editor predispone un ambiente virtuale per plugin, vi installa questi pacchetti con pip ed esegue il worker del plugin al suo interno (vedi Creazione dei pacchetti). Le voci non stringa e quelle vuote vengono saltate.
permissions array di stringhe Dichiarazioni grossolane di capacità (per esempio ["network"]), mostrate in sola lettura nella colonna Autorizzazioni di Preferenze → Estensioni, così che gli utenti possano vedere che cosa il plugin dice di fare. Solo dichiarazione: non ancora imposta.
thirdParty array di oggetti Componenti di terze parti che il plugin include, per l'attribuzione nella finestra Informazioni. Ogni voce: name (obbligatorio), license, url, file. Distribuisci il testo della licenza nominato da file accanto al plugin sotto Plugins/Licenses/<id>/. Vedi sotto.

Ogni voce dichiara un menu di primo livello a cui il plugin contribuisce e ne stabilisce la posizione. Ripeti un oggetto per ciascun menu di primo livello che tocchi (Tools, Plugins, Help, ecc.).

"menus": [
  { "title": "Plugins", "barPriority": 570, "itemPriority": 100 }
]
Campo Tipo Note
title stringa, obbligatorio L'etichetta del menu di primo livello sotto cui vive la voce (Plugins, Tools, …). Deve corrispondere al segmento più a sinistra dei percorsi che passi a ctx.menus.add_item().
barPriority intero, facoltativo Rango da sinistra a destra nella barra dei menu. Più basso = più a sinistra. I menu del nucleo hanno priorità fisse distanziate di 100 (File 100, Modifica 200, …, Finestra 600); 570 mette il tuo sottomenu vicino alla posizione di Plugins. Ripetuto tra i plugin che puntano allo stesso menu di primo livello; vince l'ultimo, e va bene perché è idempotente.
itemPriority intero, facoltativo Rango verticale dell'intero blocco del tuo plugin dentro il menu foglia. Predefinito 1000. Più basso = più in alto.

Qui NON elenchi le singole voci: quelle vengono aggiunte da ctx.menus.add_item() a tempo di esecuzione. menus riguarda soltanto la collocazione nella barra dei menu.

thirdParty

Dichiara qualsiasi componente di terze parti che il tuo plugin include, così che la finestra Informazioni possa attribuirlo. Ogni voce:

"thirdParty": [
  { "name": "SomeLib", "license": "MIT",
    "url": "https://example.com/", "file": "SomeLib-LICENSE.txt" }
]
Campo Tipo Note
name stringa, obbligatorio Il componente. Le voci senza un nome non vuoto vengono scartate.
license stringa, facoltativo Etichetta in stile SPDX, per esempio MIT, LGPL-3.0.
url stringa, facoltativo Pagina del progetto / pagina iniziale.
file stringa, facoltativo Solo nome del file di licenza che distribuisci, risolto in Plugins/Licenses/<your-plugin-id>/<file>.

I testi delle licenze sono tuoi: distribuiscili con il pacchetto del tuo plugin sotto Plugins/Licenses/<id>/. L'editor elenca i componenti e indirizza gli utenti a quella cartella; non conserva i testi di terze parti del tuo plugin nella propria cartella Licenses/.

Sonda statica

Al momento dell'individuazione — e di nuovo quando viene installato un pacchetto .mteplugin — l'host legge module, apre <pluginDir>/<module>.py e conferma che contenga un def register(...) di primo livello: non viene eseguito alcun codice. L'installer respinge un pacchetto che non supera il controllo con una finestra di errore; l'individuazione salta il plugin in silenzio, con una riga di errore nel log:

PythonPluginBackend: skipping 'org.example.wordcount': module
'.../main.py' does not declare a top-level `def register(...)`.

Tieni register alla colonna 0 di una riga che inizia con def register(.

Ordine di caricamento e collocazione nella barra dei menu

Se il tuo plugin contribuisce a Plugins con barPriority: 570, il menu compare al rango 570 nella barra dei menu. Due plugin con valori di barPriority diversi per lo stesso titolo si contendono la posizione: vince quello caricato per ultimo, ma poiché di norma entrambi dichiarano lo stesso rango per un dato menu la cosa non ha importanza. Vedi PLUGIN_ARCHITECTURE.md §13 per il modello di ordinamento completo.

Che cosa NON va qui

L'host analizza i campi documentati sopra e ignora tutto il resto: non inventare campi, una chiave sconosciuta è silenziosamente peso morto.