ctx — liitännäisen konteksti¶
register(ctx) vastaanottaa yhden argumentin: PluginContext-olion. Se paljastaa alla
olevat palvelut (koko IPluginContext-pinnan, joka sopii prosessin ulkopuoliseen malliin).
Kukin on pieni Python-luokka, jonka työntekijä rakentaa RPC-kanavan päälle; lähdekoodi on
Python/mte/.
def register(ctx):
ctx.commands # register/invoke commands
ctx.menus # add menu items & separators
ctx.events # subscribe to editor events
ctx.log # write to the host's diagnostics stream
ctx.status # post transient status-bar messages
ctx.editor # buffer / caret / selection / files / search / bookmarks / groups
ctx.languages # list languages, read / switch a document's language, contribute one
ctx.settings # per-plugin key/value store
ctx.app_settings # editor-wide read-only settings view (keys: mte.keys)
ctx.document_settings # .editorconfig-layered per-document reads
ctx.theme # themeable colour categories for your own UI
ctx.diagnostics # publish squiggles + margin glyphs
ctx.compare # open the side-by-side compare view
ctx.completions # register auto-completion providers
ctx.docks # declarative dock panels (+ set_panel_visible, is_panel_visible)
ctx.line_markers # margin glyphs / line tints that follow edits; the margin-click claim
ctx.settings_page # declarative Preferences pages
ctx.ui # runtime get/set for panel controls
Kahdella natiivin sopimuksen osalla ei vielä ole Python-vastinetta: hover-toimittajilla (joten hoverin prioriteettikaistat eivät koske Python-liitännäisiä) ja editorin kontekstivalikon toimittajilla (joten ei myöskään kontekstivalikon alue teksti / marginaali). Molempiin vastataan käyttäjän odottaessa, mikä vaatii saman määräaikakäsittelyn kuin täydennystoimittajilla on, ennen kuin edestakainen matka työntekijälle on turvallinen.
Älä säilytä ctx-oliota globaalissa muuttujassa odottaen käyttäväsi sitä myöhemmin —
vaikka attribuutit ovat vakaat liitännäisen elinajan, käsittele ctx-oliota
rekisteröintikohtaisena. Säilytä viittaukset niihin yksittäisiin palveluihin, joita
tarvitset (esimerkiksi log = ctx.log).
commands¶
Koriste, joka rekisteröi komennon ja sitoo käärityn funktion sen käsittelijäksi.
id(str, pakollinen): käänteisen DNS:n tyylinen yksilöllinen tunniste (esimerkiksi"wordcount.count"). Samat säännöt kuin tiedostossaplugin.json— täytyy olla globaalisti yksilöllinen.title(str, pakollinen): ihmisluettava nimiö, joka näkyy kaikkialla, missä komento tulee esiin (valikot, komentopaletti).shortcut(str, valinnainen): siirrettävä oletuspikanäppäinmerkkijono, esimerkiksi"Ctrl+Alt+W".Ctrlkuvautuu automaattisesti alustan ensisijaiseen muuntonäppäimeen (CmdmacOS:ssä). Jätä tyhjäksi, jos pikanäppäintä ei ole. Käyttäjä voi määrittää sen uudelleen tai poistaa sen määrityksen kohdassa Asetukset ▸ Pikanäppäimet; valikkoon sidottujen komentojen osalta isäntä ottaa uudelleenmäärityksen käyttöön puolestasi.category(str, valinnainen): vapaamuotoinen ryhmittelynimiö — näytetään komennon luokkana pikanäppäinten määrityksessä.scope(str, valinnainen):""/"application"(oletus — isäntä sitoo pikanäppäimen komennon valikkotoimintoon) tai"pluginWindow"niille yhdistelmille, jotka sijaitsevat liitännäisen omistamassa käyttöliittymässä: isäntä vain luettelee komennon määrityksessä; luectx.commands.effective_shortcut(id)rakentaessasi ohjausobjektejasi ja ota se uudelleen käyttöön tapahtumassa"command.shortcutChanged".
Se pikanäppäin, joka on tällä hetkellä voimassa käyttäjän uudelleenmäärityksen ja
ristiriitojen ratkaisun jälkeen ("" = ilman määritystä tai tuntematon). Turvallinen
kutsua käsittelijöistä.
Kääritty funktio ei ota argumentteja eikä palauta mitään. Sen sisäiset poikkeukset nappaa työntekijä ja kirjaa ne stderriin; ne eivät kaada editoria.
@ctx.commands.command(id="wordcount.count",
title="Count Words",
shortcut="Ctrl+Alt+W",
category="Text")
def _count():
ctx.status.show("counted")
Konepellin alla: Python-puoli varaa tunnisteen handlerId paikallisesti, rekisteröi
takaisinkutsun RPC-yhteyteen ja lähettää kutsun commands.registerCommand isännälle. Kun
käyttäjä aktivoi komennon (valikkonapsautus, pikanäppäin, paletti), isäntä lähettää
callback-RPC:n ja funktiosi ajetaan.
Komentotunnisteet ovat prosessinlaajuisia eivätkä liitännäiskohtaisia. Lisää
käänteinen DNS-nimiavaruutesi tunnisteidesi eteen (wordcount.…) välttääksesi törmäykset.
menus¶
Valikkopolut käyttävät merkkiä / erottimena. Vasemmanpuoleisin osa on ylimmän tason
valikko (Plugins, Tools …); väliosat luovat alivalikot tarvittaessa; viimeinen osa on
kohdan nimiö.
ctx.menus.add_item(path, command_id)¶
path(str):"Ylin/Ali/…/Nimiö". Välialivalikot luodaan tarvittaessa.command_id(str): aiemmin rekisteröidyn komennon tunniste. Kohdan napsauttaminen kutsuu komentoa.
Palauttaa läpinäkymättömän handlerId-merkkijonon. Säilytä se, jos joudut myöhemmin
kutsumaan kohteelle funktiota unsubscribe (harvinaista vaiheessa 1).
Vasemmanpuoleisimman osan ("Plugins" yllä) täytyy vastata jonkin
menus[]-kohtasi kenttää title tiedostossa plugin.json, jotta valikkopalkkisijainti
poimitaan.
ctx.menus.add_separator(path)¶
Lisää erottimen olemassa olevaan alivalikkoon.
ctx.menus.set_item_checked(handler_id, checked)¶
Muuttaa aiemmin lisätyn kohdan valittavaksi valikkokohdaksi ja asettaa sen valintatilan — vakioidiomi pysyvälle päälle/pois-kytkimelle, joka näyttää näkyvän valintamerkin.
item = ctx.menus.add_item("View/Auto-open Preview",
"myplugin.toggleAutoOpen")
# Seed the check mark from the persisted setting so it matches
# reality before the user opens the menu.
ctx.menus.set_item_checked(item, ctx.settings.get("autoOpen", True))
@ctx.commands.command(id="myplugin.toggleAutoOpen",
title="Toggle Auto-Open")
def _toggle():
on = not ctx.settings.get("autoOpen", True)
ctx.settings.set("autoOpen", on)
ctx.menus.set_item_checked(item, on)
Ensimmäinen kutsu tekee kohdasta valittavan; seuraavat kutsut vain kääntävät merkin.
Sellaisen tunnisteen handler_id välittäminen, jota isäntä ei tunne, ei tee hiljaisesti
mitään (turvallista kutsua sen jälkeen, kun polettisi on pudotettu, esimerkiksi
viivästyneestä takaisinkutsusta sammutuksen aikana).
ctx.menus.set_item_enabled(handler_id, enabled)¶
Ottaa aiemmin lisätyn kohdan käyttöön tai harmaannuttaa sen. Käytä sitä, kun komento tarvitsee edellytyksen — jotain suljettavaa, jotain palautettavaa — jotta valikko näyttää, ettei se ole käytettävissä, sen sijaan että tarjoaisi kohtaa, joka ei hiljaisesti tee mitään.
item = ctx.menus.add_item("File/Close Thing", "myplugin.closeThing")
# Nothing to close yet:
ctx.menus.set_item_enabled(item, False)
# ... and from every place that changes the state the command needs:
ctx.menus.set_item_enabled(item, thing_is_open)
Käytöstä poistettu kohta pysyy näkyvissä muttei ole käynnistettävissä, ei napsautuksella
eikä pikanäppäimellään. Kutsu on idempotentti, joten sinun ei tarvitse koskaan muistaa
edellistä tilaa, ja tuntematon handler_id ei tee hiljaisesti mitään, kuten yllä. Kohdat
alkavat käytössä olevina: yksi kutsu heti funktion add_item jälkeen valmistelee kohdan,
joka ei ole käytettävissä käynnistyksessä.
events¶
Tilaa editoritapahtumia. Kaksi vastaavaa API:ta — kevyitä koristeita suositellaan; raaka
subscribe() on saatavilla, jos haluat laskea aiheen ajon aikana.
Kevyet koristeet¶
@ctx.events.on_document_saved
def _saved(ev):
ctx.log.info(f"saved doc {ev.document}")
@ctx.events.on_document_opened
def _opened(ev):
ctx.log.info(f"opened {ev.path}")
Kääritty funktio ottaa yhden argumentin: aihetta vastaavan tyypitetyn dataluokan. Katso koko aihe ↔ dataluokka -taulukko kohdasta Tapahtumadokumentaatio.
Raaka API¶
handler_id = ctx.events.subscribe("document.saved", _saved)
# later:
ctx.events.unsubscribe(handler_id)
Käytettävissä olevat kevyet ominaisuudet (kaikki koristeita):
| Ominaisuus | Laukeaa |
|---|---|
on_document_opened |
Asiakirja avattiin välilehdessä |
on_document_closed |
Asiakirja suljettiin |
on_document_saved |
Asiakirja kirjoitettiin levylle |
on_selection_changed |
Kohdistin tai valinta liikkui aktiivisessa asiakirjassa |
on_active_document_changed |
Etualan välilehti vaihtui |
on_document_modified_changed |
Puhdas/likainen-lippu kääntyi (modified: bool) |
on_text_changed |
Jokainen muokkaus (position, added_bytes, removed_bytes) — pidä se hyvin yksinkertaisena |
on_settings_changed |
Asetukset otettiin käyttöön (scope: "" koko editori, "plugins/<id>") |
on_theme_changed |
Teema vaihdettiin tai sitä muokattiin (variant) — lue kohteen ctx.theme värit uudelleen |
on_workspace_root_changed |
Työtilakansio avattiin tai suljettiin (root) |
on_workspace_files_changed |
Työtilan tiedostojoukko muuttui (files) |
on_host_window_shown |
Kerran ajoa kohti, ensimmäisen ruudun jälkeen — aikatauluta hidas käynnistystyö tähän |
on_app_about_to_quit |
Editori sulkeutuu — viimeinen tilaisuus ajaa |
on_command_shortcut_changed |
Komennon todellinen pikanäppäin muuttui (käyttäjän uudelleenmääritys, näppäinkartan tuonti tai ristiriidan ratkaisu); hyötykuorma: command_id, sequence ("" = ilman määritystä) |
Tuntemattomat aihenimet heittävät poikkeuksen ValueError tilaushetkellä. Tilaajat voivat
ajautua vastaavan natiivin käsittelijän jälkeen; käsittele tapahtumien toimitusta
tiedottavana eikä ratkaisevana.
Julkaiseminen¶
ctx.events.publish(topic, payload) lähettää sekä natiiveille että Python-tilaajille —
hyväksytään vain kahdelle työtila-aiheelle (workspace.rootChanged,
workspace.filesChanged); mikä tahansa muu heittää poikkeuksen ValueError. Katso
Tapahtumadokumentaatio.
log¶
ctx.log.trace ("very-fine-grained")
ctx.log.debug ("dev-only detail")
ctx.log.info ("routine event")
ctx.log.warning("recoverable weirdness")
ctx.log.error ("something is wrong")
Kukin taso vastaa isännän rajapintaa ILogger. Rivit saavat etuliitteen
[python:<plugin.id>], jotta tulosteesi löytyy editorin diagnostiikkalokista:
Älä koskaan käytä funktiota print() liitännäisestä — työntekijän stdout on RPC-kanava, ja
siihen kirjoittaminen turmelee protokollan. ctx.log.* on ainoa hyväksytty tapa lähettää
diagnostiikkatekstiä.
status¶
Lähetä ohimenevä ilmoitus tilariville.
message(str): mitä näyttää. Vain lyhyitä merkkijonoja — tilarivillä on kiinteä leveys.timeout_ms(int, oletus 0): kuinka kauan se pidetään näytöllä;0antaa isännän valita järkevän oletuksen (muutama sekunti).level(str, oletus"info"):"info"/"warning"/"error". Korkeammat tasot voivat pitää näytöllä olon vähimmäisajan hieman pidempänä, jottei virhettä pyyhitä heti pois rutiininomaisella info-viestillä.
ctx.status.show on lähetä-ja-unohda. Jos isännällä ei ole näkyvää tilariviä (pääteetön
tai minimaalinen käännös), kutsu hylätään hiljaisesti. ctx.status.clear() pyyhkii
näytöllä olevan ohimenevän ilmoituksen.
Pysyvät osiot¶
Elävää tilaa varten (sanamäärä, palvelimen tila) käytä omistamaasi osiota ja päivitä sitä — se ei koskaan tuhoa ilmoitusta eikä päinvastoin:
seg = ctx.status.add_segment("wordcount.total", priority=100)
seg.set_text("2,431 words")
seg.set_visible(False) # hide without giving it up
seg.remove() # take it off the bar (idempotent)
priority järjestää liitännäisosiot vasemmalta oikealle (pienempi = kauempana vasemmalla;
tasapelit säilyttävät rekisteröintijärjestyksen). Liitännäisen sammutus poistaa kaiken vielä
hallussa olevan.
editor¶
Täysi synkroninen pääsy aktiiviseen asiakirjaan tai asiakirjoihin. Kukin metodi estää
kutsuvan säikeen, kunnes isäntä vastaa (tyypillisesti mikrosekunteja, kun työntekijä ja
editori jakavat koneen). Sallittu mistä tahansa komento- tai tapahtumakäsittelijästä;
ei koskaan async def-takaisinkutsusta (katso säiehuomautus tämän sivun ylälaidassa).
Asiakirjojen luettelointi¶
doc = ctx.editor.active_document() # 0 when no document is open
docs = ctx.editor.open_documents() # list[int]
ctx.editor.set_active_document(doc)
path = ctx.editor.file_path(doc) # str or None for untitled
Puskurin käyttö¶
text = ctx.editor.text(doc) # whole buffer
slice = ctx.editor.text_range(doc, start, end) # [start, end) bytes
n = ctx.editor.length(doc) # int64
ctx.editor.set_text(doc, "...")
text_range välttää koko puskurin vetämisen RPC:n yli, kun tarvitset vain viipaleen —
suosi sitä lajitteluun ja muunnokseen suurissa tiedostoissa.
Valinta¶
sel = ctx.editor.selection_range(doc) # mte.MatchRange(start, end)
s = ctx.editor.selected_text(doc)
ctx.editor.replace_selection(doc, "new text")
ctx.editor.set_selection(doc, mte.MatchRange(4, 9))
ranges = ctx.editor.selection_ranges(doc) # list[MatchRange]: one per caret
block = ctx.editor.is_rectangular_selection(doc) # Alt+drag column block?
Kohdistin¶
pos = ctx.editor.caret(doc) # mte.EditorPosition(line, column)
ctx.editor.set_caret(doc, mte.EditorPosition(line=7, column=3))
Tiedostotoiminnot¶
new_doc = ctx.editor.open_file("/path/to/file") # doc-id or 0 on failure
here = ctx.editor.open_file_at("/path/to/file", mte.EditorPosition(41, 0))
ctx.editor.reveal_line(doc, 120) # scroll there; caret and focus stay
ok = ctx.editor.save_document(doc)
closed = ctx.editor.close_document(doc) # prompts if modified; False = user cancelled
dirty = ctx.editor.is_modified(doc)
ctx.editor.set_modified(doc, True) # force the tab asterisk
ro = ctx.editor.is_read_only(doc) # e.g. Monitoring (tail -f) mode
enc = ctx.editor.document_encoding(doc) # mte.DocumentEncoding, e.g. UTF8_BOM
ctx.editor.set_document_encoding(doc, mte.DocumentEncoding.UTF8) # takes effect on the next save
eol = ctx.editor.line_ending(doc) # mte.LineEnding, e.g. CRLF
ctx.editor.set_line_ending(doc, mte.LineEnding.LF) # Enter inserts it; the next save writes it
scratch = ctx.editor.create_untitled("text", "Untitled-3") # new buffer, doc-id
sid = ctx.editor.stable_id(doc) # survives Save As; compare with ==
clip = ctx.editor.clipboard_text() # system clipboard, "" if no text
# Declare that you snapshot unsaved buffers (the host then stops asking
# "save changes?" when the window closes):
ctx.editor.set_unsaved_changes_preserved(True)
ctx.editor.unsaved_changes_preserved() # bool, global flag
open_file_at on se yksi kutsu, jolla »viedään käyttäjä sinne« (käännösvirhe,
pinokehys, hakutulos): se avaa tiedoston tai aktivoi sen välilehden,
sijoittaa kohdistimen ilman valintaa, avaa rivin piilottavan laskostuksen,
vierittää rivin näkyviin — keskitettynä, jos se oli näytön ulkopuolella — ja
kohdistaa editoriin. Rivi ja sarake alkavat nollasta (sarake UTF-8-tavuina)
ja ne rajataan, niitä ei koskaan hylätä; se palauttaa asiakirjan tunnisteen,
tai 0, jos tiedostoa ei voitu avata, ja silloin mikään ei liikkunut.
reveal_line vain näyttää rivin: se ei siirrä kohdistinta, ei vaihda
välilehteä eikä ota kohdistusta.
Kirjanmerkit, merkinnät ja URL-korostus¶
ctx.editor.toggle_bookmark(doc, line) # 0-based line
lines = ctx.editor.bookmarked_lines(doc) # list[int]
nxt = ctx.editor.next_bookmark(doc, from_line, wrap=True) # -1 = none
prv = ctx.editor.previous_bookmark(doc, from_line, wrap=True)
ctx.editor.clear_bookmarks(doc)
ctx.editor.mark_range(doc, mte.MatchRange(4, 9)) # "mark" indicator
ctx.editor.clear_marks(doc)
ctx.editor.set_url_highlight_enabled(doc, True)
ctx.editor.is_url_highlight_enabled(doc)
url = ctx.editor.url_at_caret(doc) # "" when none
ctx.editor.open_url_at_caret(doc) # bool
Haku¶
opts = mte.SearchOptions(match_case=True, mode="regex")
hit = ctx.editor.find_in_range(doc, r"TODO\(.*\)", 0,
ctx.editor.length(doc), opts)
if hit.valid:
new_end = ctx.editor.replace_target(doc, hit, "DONE()", opts)
SearchOptions.mode: "normal" / "extended" / "regex".
SearchOptions.direction: "forward" / "backward". Katso koko kenttäluettelo kohteesta
mte.SearchOptions.
Tarkentuva haku (kasvata hahmoa käyttäjän kirjoittaessa, kiinnitetystä ankkurista):
ctx.editor.set_incremental_search_anchor(doc)
hit = ctx.editor.incremental_search(doc, "TOD", opts) # MatchRange
Sisennys ja syntaksi¶
style = ctx.editor.indentation(doc) # IndentationStyle(use_tabs, width)
ctx.editor.set_indentation(doc,
mte.IndentationStyle(use_tabs=False, width=2))
# Where word-wrapped continuation rows start:
# "left" (window edge) / "same" (align with the line; default) / "indent"
ctx.editor.set_wrap_indent(doc, "same")
mode = ctx.editor.wrap_indent(doc) # same strings back
lang = ctx.editor.colorizer_id(doc) # e.g. "python", "" if none
# Semantic classification from the active colorizer (cheap, no re-lex):
# list[mte.CategorySpan(start, length, category)] with category names
# "comment" / "string" / "keyword" / ... -- a spell checker keeps to
# comments and strings this way.
spans = ctx.editor.text_categories(doc, 0, ctx.editor.length(doc))
ctx.editor.trigger_completion(doc) # pop the list as if Ctrl+Space
Jaettu näkymä ja välilehtiryhmät¶
n = ctx.editor.group_count() # >= 1
g = ctx.editor.group_of(doc) # -1 if not open
w = ctx.editor.group_weights() # relative widths
ctx.editor.move_document_to_group(doc, 1) # creates trailing groups on demand
ctx.editor.set_group_weights([2, 1])
ctx.editor.set_document_tab_index(doc, 0) # reorder within its pane
gs = ctx.editor.groups_of(doc) # EVERY pane showing it
ctx.editor.show_document_in_group(doc, 1) # split it into pane 1
Kahdessa ruudussa näkyvä asiakirja on yksi asiakirja, jolla on yksi tunniste, joten
group_of() voi nimetä vain toisen sen paikoista. groups_of() ilmoittaa ne kaikki, ja
show_document_in_group() luo toisen jaetun näkymän — saman, minkä Näytä > Jaa
asiakirja oikealle tekee, joten document_opened-tapahtumaa ei nosteta.
ctx.editor heijastaa nyt natiivia rajapintaa IEditorService yksi yhteen.
languages¶
Syntaksivärjäys on ytimen ominaisuus — isäntä tunnistaa asiakirjan kielen ja värittää sen
ilman liitännäistä. ctx.languages antaa sinun osallistua: luettele, mitä isäntä tuntee,
lue tai ohita asiakirjan kieli, aja tunnistus uudelleen ja tarjoa kokonaisia
kielimäärityksiä.
for lang in ctx.languages.available(): # list[mte.LanguageInfo(id, name)]
...
lang_id = ctx.languages.language_for(doc) # "" when uncoloured
ok = ctx.languages.set_language_for(doc, "json") # "" clears; False = unknown
ctx.languages.auto_detect_for(doc) # undo a manual override
handler = ctx.languages.register(
id="mylang", name="My Language", lexer="cpp",
extensions=["mylang", "ml2"],
keywords=[{"group": "Primary keywords and identifiers",
"words": "if else while"}],
styles={"SCE_C_COMMENT": "comment", "SCE_C_STRING": "string"})
...
ctx.languages.unregister(handler) # restores what it displaced
register ottaa saman muodon kuin mukana tuleva colorizers/*.json-tiedosto (tai kokonaisen
definition=-sanakirjan): lexer nimeää olemassa olevan taustajärjestelmän leksikaalisen
jäsentimen (isäntä ei saa uusia jäsentimiä ajon aikana), styles kuvaa tuon jäsentimen omat
tyylinimet semanttisiksi luokiksi, ja keywords osoittaa sen sanaluetteloihin jäsentimen
oman paikkakuvauksen mukaan — isäntä ratkaisee molemmat täsmälleen kuten mukana tulevalle
tiedostolle, joten sinun ei tarvitse koskaan kirjoittaa moottorin tunnisteita. Jo olemassa
olevan tunnisteen rekisteröinti korvaa sen niin kauan kuin pidät käsittelijätunnistetta;
liitännäisen sammutus peruu kaiken vielä hallussa olevan.
document_settings¶
Vain luettavia, asiakirjaan rajattuja asetuksia, jotka kerrostavat projektin
.editorconfig-tiedoston omien ctx.settings-asetustesi päälle. Avaimelle k ja
asiakirjalle doc luku ratkaisee avaimen mte.<plugin.id>.<k> siitä
.editorconfig-tiedostosta, joka koskee tuota asiakirjaa, turvautuu sitten kohteeseen
ctx.settings ja sitten oletusarvoosi:
wrap = ctx.document_settings.get_bool(doc, "wrap", False)
width = ctx.document_settings.get_int(doc, "width", 80)
ratio = ctx.document_settings.get_double(doc, "ratio", 1.0)
name = ctx.document_settings.get_string(doc, "profile", "")
ctx.document_settings.contains(doc, "wrap") # set in either layer?
Kirjoitukset kulkevat kohteen ctx.settings kautta — ei koskaan takaisin
.editorconfig-tiedostoon.
diagnostics¶
Työnnä aaltoviivoja ja marginaalimerkkejä asiakirjalle — staattiselta analysaattorilta,
kielipalvelimelta tai käännöslokista. Isäntä piirtää ne; sinä et koskaan kosketa näkymään.
Julkaiseminen korvaa kaiken, minkä olet aiemmin julkaissut tuolle parille
(asiakirja, lähde), joten lähetä koko joukko joka kerta:
ctx.diagnostics.publish(doc, "mylinter", [
mte.Diagnostic(start=12, end=18, message="unused variable",
severity=mte.SEVERITY_WARNING, code="W0612"),
])
ctx.diagnostics.publish(doc, "mylinter", []) # retract only your own
ctx.diagnostics.clear(doc) # clears EVERY producer's set on doc
source on pakollinen — juuri se pitää joukkosi erillään muiden tuottajien
(LSP-liitännäisen, oikoluvun) joukoista samassa asiakirjassa. Vakavuusasteet:
SEVERITY_ERROR / SEVERITY_WARNING / SEVERITY_INFORMATION / SEVERITY_HINT.
Siirtymät ovat puoliavoimia [start, end)-tavuvälejä.
theme¶
Rekisteröi ne värit, joita oma käyttöliittymäsi piirtää, nimettyinä, teemoitettavina luokkina; Teemaeditori luettelee ne automaattisesti ja käyttäjän ohitukset kulkevat edestakaisin teematiedostossa:
h = ctx.theme.register_category("com.example.my/match", "Match highlight",
default_light=0xFFF3B0, default_dark=0x8A6D00)
rgb = ctx.theme.resolve_color("com.example.my/match") # 0xRRGGBB int
themed = ctx.theme.has_override("com.example.my/match")
variant = ctx.theme.active_variant() # "light" / "dark" / ""
cats = ctx.theme.categories() # list[mte.ThemeCategory]
ctx.theme.unregister_category(h)
Lue resolve_color uudelleen tapahtumassa ctx.events.on_theme_changed.
compare¶
Avaa (tai kohdista) editorin vierekkäinen vertailunäkymä kahdelle lähteelle. Kukin puoli on
levyllä oleva tiedosto (path=), kirjaimellinen teksti (content=) tai molemmat (sisältö
näytetään, polku antaa istunnon säilytykselle palautettavan identiteetin):
shown = ctx.compare.open(
mte.CompareSource("before", path="/tmp/a.txt"),
mte.CompareSource("after", content=new_text),
ignore_whitespace=True) # ignore_case / ignore_eol too
Palauttaa arvon False, kun puolta ei voi lukea.
settings¶
Pysyvä tyypitetty avain–arvo-varasto, rajattuna polkuun plugins/<your.id>/ isännässä.
Kaikki metodit ovat synkronisia; get ja set päätellään oletusarvon Python-tyypistä.
ctx.settings.set("wrap", True)
ctx.settings.set("count", 42)
ctx.settings.set("theme", "dark")
wrap = ctx.settings.get("wrap", False) # returns bool
count = ctx.settings.get("count", 0) # returns int
theme = ctx.settings.get("theme", "light") # returns str
Tyypit:
Kentän default Python-tyyppi |
Siirtotyyppi | Funktion get() palauttama tyyppi |
|---|---|---|
bool |
bool |
bool |
int (ei bool) |
int |
int |
float |
double |
float |
str (tai None) |
string |
str |
Lisäksi:
ctx.settings.contains("wrap") # bool
ctx.settings.remove("stale_key")
ctx.settings.sync() # optional; host also syncs on shutdown
Reagoi asetusikkunassa tehtyihin muutoksiin tilaamalla aihe settings.changed
(ctx.events.on_settings_changed; katso Tapahtumadokumentaatio).
app_settings¶
Vain luettava näkymä editorin sovelluksenlaajuiseen kokoonpanoon. Tunnetut avainnimet
viedään vakioina moduulissa mte.keys (peilaten C++-otsikkotiedostoa
PluginApi/AppSettingsKeys.h, joka pysyy ratkaisevana luettelona):
import mte
size = ctx.app_settings.get(mte.keys.EDITOR_FONT_SIZE, mte.keys.DEFAULT_EDITOR_FONT_SIZE)
family = ctx.app_settings.get(mte.keys.EDITOR_FONT_FAMILY, "") # "" = host default
theme = ctx.app_settings.get(mte.keys.UI_THEME, mte.keys.DEFAULT_UI_THEME) # "system"/"light"/"dark"
Asettajat, remove() ja sync() kohteessa ctx.app_settings heittävät poikkeuksen
RuntimeError — näkymä on tarkoituksella vain luettava.
completions¶
Rekisteröi täydennystoimittaja, joka osallistuu editorin ponnahdusluetteloon:
@ctx.completions.provider(languages=["python"])
def _complete(req: mte.CompletionRequest):
if not req.prefix:
return []
return [mte.CompletionItem(text=w, kind=mte.KIND_KEYWORD)
for w in ("hello", "hello_world", "helper")
if w.startswith(req.prefix)]
Kääritty funktio kutsutaan jokaisella näppäinpainalluksella (tai Ctrl+välilyönnillä), jonka
asiakirja vastaa kielisuodatinta. Olion req kentät:
| Kenttä | Tyyppi | Merkitys |
|---|---|---|
document |
int |
Muokattava asiakirja |
prefix |
str |
Sanan osa välittömästi ennen kohdistinta |
position |
int |
Kohdistimen tavusiirtymä |
language_id |
str |
Värjääjän tunniste ("python", "cpp" …) |
manual |
bool |
True, kun käyttäjä painoi Ctrl+välilyöntiä; False automaattisella laukaisulla |
Palauta luettelo mte.CompletionItem-olioita (tai tavallisia merkkijonoja tai sanakirjoja
muotoa {text, detail, kind}). Lajit: mte.KIND_KEYWORD / KIND_WORD / KIND_SYMBOL /
KIND_SNIPPET / KIND_UNKNOWN.
Määräaika
Isäntä lähettää toimittajallesi näppäinpainalluspyynnön noin 30 ms:n määräajalla. Jos takaisinkutsusi ylittää sen, ponnahdusluettelo näytetään ilman ehdokkaitasi tuon näppäinpainalluksen osalta. Rakenna mikä tahansa kallis hakemisto taustalla ja vastaa välimuistista — älä koskaan tee I/O:ta takaisinkutsussa. LSP-tyylinen verkkotäydennys kuuluu tulevaan asynkroniseen pintaan eikä tänne.
languages=[] (tai puuttuva) tarkoittaa »jokainen asiakirja«. Useita toimittajia
liitännäistä kohti on sallittu; kukin koriste rekisteröi omansa.
data_dir¶
Palauttaa liitännäiskohtaisen kirjoitettavan hakemiston, jonka isäntä on jo luonut
puolestasi. Käytä välimuisteihin, hakemistoihin ja kaikkeen omistamaasi dataan.
ctx.diagnostics_dir() palauttaa vastaavasti jaetun kaatumis- ja lokihakemiston (sinulle
vain luettava — kaatumisraportoija kirjoittaa sinne).
docks¶
Kuvailevat telakkapaneelit — sivupaneelikäyttöliittymä, joka on rakennettu
lomakemäärittelystä eikä Qt-ohjausobjekteista. Katso rakentajien sanasto kohdasta
mte.ui.
from mte.ui import Column, Row, Label, LineEdit, Checkbox, Button
def register(ctx):
def _on_needle_changed(value: str) -> None:
ctx.log.info(f"needle -> {value!r}")
needle_handler = ctx.docks.on_change(_on_needle_changed)
panel_id = ctx.docks.add_panel(
id="renamer.panel",
title="Renamer",
area="right", # left / right / top / bottom
form=Column([
Label(text="Search:"),
LineEdit(id="needle", placeholder="text...",
binds="settings:lastNeedle",
on_change=needle_handler),
Checkbox(id="cs", label="Case sensitive",
binds="settings:caseSensitive"),
Row([Button(text="Run", on_click="renamer.run")]),
]),
)
ctx.docks.add_panel(*, id=None, title="", area="right", form, initially_visible=True, proportional_size=0.0, tab_group="") -> str¶
Rekisteröi telakkapaneelin. Palauttaa paneelin tunnisteen (automaattisesti varattuna, kun
id on None).
id(str, valinnainen) — vakaa tunniste, jotactx.ui.get/ctx.ui.setkäyttää osoittaakseen tämän paneelin sisällä oleviin ohjausobjekteihin. Jos et anna sitä, isäntä varaa tunnisteen muotoapy-dock/Nja palauttaa sen.title(str) — näkyy telakan otsikossa.area(str) —"left"/"right"/"top"/"bottom". Tuntemattomat arvot turvautuvat arvoon"right".form(dict) —mte.ui-rakentajilla rakennettu määrittely.initially_visible(bool) — näytetäänkö telakka, kun liitännäinen latautuu. OletusTrue. AnnaFalsepaneelille, jonka ei pitäisi ponnahtaa esiin käynnistyksessä, ja tuo se esiin myöhemmin funktiollaset_panel_visible.proportional_size(float) — paneelin oletuskoko osuutena pääikkunasta: sen leveydestä alueilla"left"/"right", sen korkeudesta alueilla"top"/"bottom".0.0(oletus) säilyttää pikselikäyttäytymisen, jota työkalupaneeli haluaa — paneeli pitää kokonsa, eikä ikkunan koon muuttaminen kosketa sitä. Murtoluku kuten0.4on sitä, mitä esikatselu haluaa: ikkunan suurentaminen leventää paneelia sen mukana. Vain oletus on sinun; heti kun käyttäjä vetää paneelin erotinta, isäntä ottaa käyttöön ja muistaa hänen osuutensa. Rajojen ulkopuoliset arvot rajataan, ja isäntä säilyttää vähimmäislaajuuden sekä paneelille että editorille. Täydet säännöt ovat kohdassaproportionalSize.tab_group(str) — paneelit, joilla on sama ei-tyhjä ryhmätunniste samallaarea-alueella, jakavat yhden telakan välilehtinä sen sijaan, että olisivat vierekkäin. Anna sille nimiavaruus kuten paneelin tunnisteelle ("renamer/panels"). Vain oletusjärjestely: käyttäjän tallentama asettelu voittaa. KatsotabGroup.
ctx.docks.is_panel_visible(handler_id) -> bool¶
Onko add_panel-kutsulla lisätty paneeli auki — toisen taakse
välilehdeksi jäänyt paneeli lasketaan avoimeksi; arvolla
initially_visible=False rekisteröity eikä koskaan näytetty paneeli,
suljettu paneeli ja tuntematon tunniste eivät. Yhdistä se
set_panel_visible-kutsuun, kun haluat näyttää paneelisi tehtävän ajaksi ja
palauttaa sen jälkeen sen, mitä käyttäjällä oli:
was_open = ctx.docks.is_panel_visible(panel)
ctx.docks.set_panel_visible(panel, True)
# ... when the task ends:
ctx.docks.set_panel_visible(panel, was_open)
ctx.docks.set_panel_visible(handler_id, visible)¶
Tuo esiin tai piilottaa paneelin, joka on lisätty funktiolla add_panel. Näyttäminen myös
nostaa paneelin niiden telakoiden yläpuolelle, joiden kanssa se jakaa alueen, joten komento,
joka »avaa« paneelinsa, todella laittaa sen käyttäjän eteen. Idempotentti — toista sama arvo
vapaasti, mitään ei tarvitse seurata; ohitetaan hiljaisesti tuntemattomalle tunnisteelle.
panel = ctx.docks.add_panel(id="mine.panel", title="Mine", form=form,
initially_visible=False)
@ctx.commands.command("mine.show", title="Show My Panel")
def _show():
ctx.docks.set_panel_visible(panel, True)
ctx.docks.on_change(callback) -> str¶
Varaa käsittelijätunnisteen ohjausobjektin on_change-kentän kytkemiseksi Python-funktioon.
Takaisinkutsu saa uuden arvon merkkijonona; totuusarvo-ohjausobjektit toimittavat arvon
"true" / "false", ja numeeriset ohjausobjektit toimittavat kokonaisluvun merkkijonona.
def _on_volume(value: str) -> None:
ctx.log.info(f"volume={int(value)}")
handler = ctx.docks.on_change(_on_volume)
form = Column([NumberSpin(id="volume", default=5, on_change=handler)])
on_change-käsittelijätunnisteilla on etuliite py-dock-cb/N eivätkä ne koskaan törmää
komento-, tapahtuma- tai täydennyskäsittelijöiden tunnisteisiin.
Takaisinkutsu ajetaan työntekijän tapahtumasilmukassa EIKÄ säiepoolissa — pidä se nopeana.
Käytä kohdetta ctx.log, muuta pientä muistissa olevaa tilaa tai laukaise jatkokomento; älä
tee raskasta työtä täällä.
line_markers¶
Marginaalisymbolit ja kokonaisten rivien sävytykset, jotka on kiinnitetty asiakirjan riveihin ja jotka seuraavat käyttäjän muokkauksia — keskeytyskohdat, nykyisen lauseen nuoli, muutospalkit — sekä kirjanmerkkisarakkeen napsautuksen varaus. Natiivi palvelu ja kaikki sen säännöt kuvataan kohdassa Rivimerkit ja marginaalin napsautus.
bp_colour = ctx.theme.register_category("myplugin.breakpoint", "Breakpoint",
default_light=0xCC0000,
default_dark=0xFF5555)
bp = ctx.line_markers.register_kind(glyph=mte.GLYPH_CIRCLE,
glyph_color="myplugin.breakpoint",
line_tint="", z_order=50)
marker = ctx.line_markers.add_marker(bp, doc, line) # 0 = refused
ctx.line_markers.line_of(marker) # where it is NOW; -1 = gone
ctx.line_markers.markers(bp, doc) # [mte.LineMarkerPlacement(id, line)]
ctx.line_markers.remove_marker(marker)
ctx.line_markers.clear_markers(bp, doc) # doc 0 = every document
ctx.line_markers.release(bp) # removes the kind and its markers
register_kind(glyph=, glyph_color=, line_tint=, z_order=)—glyphon jokin arvoistamte.GLYPH_NONE(pelkkä sävytys),GLYPH_CIRCLE,GLYPH_CIRCLE_HOLLOW,GLYPH_CIRCLE_BAR,GLYPH_ARROW,GLYPH_STRIP; värit ovat niiden luokkien tunnisteita, jotka olet rekisteröinytctx.theme-palvelulla. Editorissa on kaikille liitännäisille yhteensä vain muutama merkkipaikka, joten tämä voi epäonnistua — silloin heitetäänRpcError. Rekisteröi lajisi kerran, funktiossaregister().add_marker(kind, doc, line)— nollasta alkava rivi, jota ei rajata: asiakirjan ulkopuolinen rivi palauttaa 0 eikä sijoita mitään.- Merkit liikkuvat rivien mukana, säilyvät uudelleenlatauksessa samalla
rivinumerolla ja katoavat asiakirjansa mukana — lisää omasi uudelleen
käsittelijässä
ctx.events.on_document_opened.
Marginaalin napsautus¶
@ctx.events.on_margin_clicked
def _clicked(ev): # mte.MarginClicked
if ev.modifiers & mte.MODIFIER_CONTROL:
edit_condition(ev.document, ev.line)
else:
toggle_breakpoint(ev.document, ev.line)
claim = ctx.line_markers.claim_margin_click()
Jokainen vasemman painikkeen napsautus kirjanmerkkisarakkeessa julkaistaan
aiheena margin.clicked (document, line, margin = "symbol",
modifiers — bitit mte.MODIFIER_SHIFT / MODIFIER_CONTROL /
MODIFIER_ALT / MODIFIER_META). Oletuksena editori myös lisää tai poistaa
kirjanmerkin napsautuksesta; niin kauan kuin jokin liitännäinen pitää
claim_margin_click()-varausta, se ei tee niin vaan jättää napsautuksen
liitännäisille. ctx.line_markers.release(claim) palauttaa napsautuksen.
settings_page¶
Lisää sivun editorin asetusikkunaan. Sama lomakemäärittelyn sanasto kuin
telakkapaneeleilla; sama binds="settings:<key>"-tallennus.
from mte.ui import Column, Checkbox, NumberSpin
def register(ctx):
ctx.settings_page.register(
category="Plugins/Renamer", # slash-separated tree path
title="Renamer",
form=Column([
Checkbox(id="cs", label="Case sensitive by default",
binds="settings:caseSensitive"),
NumberSpin(id="results", default=100, min=1, max=10_000,
binds="settings:resultCap"),
]),
)
ctx.settings_page.register(*, category, title, form, scope="") -> str¶
category(str, pakollinen) — kauttaviivoin erotettu polku asetuspuussa, esimerkiksi"Plugins/My Plugin". Sisäkkäiset luokat saapuvat puusolmuina.title(str, pakollinen) — otsikko, joka näytetään sivun yläpuolella.form(dict, pakollinen) —mte.ui-rakentajilla rakennettu määrittely.scope(str, valinnainen) — tapahtuman laajuus, joka lähetetään tapahtumassaSettingsChanged, kun käyttäjä painaa OK tai Ota käyttöön.
Palauttaa käsittelijätunnisteen.
Peruuta EI peru muutoksia
Ohjausobjektit, joilla on binds="settings:<key>", tallentuvat innokkaasti käyttäjän
muokatessa, joten Peruuta-painikkeen painaminen asetusikkunassa ei kumoa niitä. Tämä
on tunnettu vaiheen 3 rajoitus; tuleva hienosäätö kääri taustalla olevat asetukset
puskuroivaan välikerrokseen.
ui¶
Lukee ja kirjoittaa ohjausobjektien arvoja jo rekisteröimissäsi paneeleissa. Arvot ovat siirtotiellä aina merkkijonoja.
def register(ctx):
panel_id = ctx.docks.add_panel(id="renamer.panel", ...)
@ctx.commands.command(id="renamer.echo", title="Echo needle")
def _echo():
needle = ctx.ui.get(panel_id, "needle") or ""
cs = (ctx.ui.get(panel_id, "cs") or "false") == "true"
ctx.status.show(f"needle={needle!r} case={cs}")
@ctx.commands.command(id="renamer.clear", title="Clear needle")
def _clear():
ctx.ui.set(panel_id, "needle", "")
ctx.ui.get(panel_id, control_id) -> Optional[str]¶
Lukee ohjausobjektin nykyisen arvon. Palauttaa arvon None, kun paneeli tai ohjausobjekti
on tuntematon (ei virhe — käsittele sekä None että "" merkityksessä »tyhjä«).
- Label / Button / LineEdit / ComboBox — palauttaa tekstin.
- Checkbox — palauttaa arvon
"true"tai"false". - NumberSpin — palauttaa kokonaisluvun desimaalimerkkijonona.
- List — palauttaa valitun kohdan tekstin (tyhjä, kun mitään ei ole valittuna).
ctx.ui.set(panel_id, control_id, value) -> bool¶
Kirjoittaa arvon ohjausobjektiin ohjelmallisesti. Palauttaa arvon True, kun kirjoitus
onnistui, ja False, kun paneeli tai ohjausobjekti on tuntematon tai arvoa ei voi muuntaa
(esimerkiksi ei-kokonaisluku lähetettynä NumberSpin-kenttään).
Pythonin True / False muunnetaan arvoiksi "true" / "false" ennen lähetystä; kaikki
muu kulkee funktion str() kautta.
Isännän ohjaama set EI laukaise ohjausobjektin on_change-takaisinkutsua uudelleen, joten
voit päivittää omia ohjausobjektejasi komentokäsittelijästä ilman äärettömiä silmukoita.
Ajonaikaisten sidontojen yhteenveto (vaihe 3)¶
| Lomakemäärittelyn kenttä | Ajonaikainen käyttäytyminen |
|---|---|
id="…" |
Osoita ohjausobjektiin funktioilla ctx.ui.get / ctx.ui.set. |
binds="settings:<key>" |
Lukee alkuarvon kohteesta ctx.settings; kirjoittaa takaisin jokaisella käyttäjän muokkauksella. |
on_click="<cmd>" |
Painikkeet kutsuvat rekisteröityä komentotunnistetta napsautettaessa. |
on_change=käsittelijä |
Laukaisee takaisinkutsun, joka on rekisteröity funktiolla ctx.docks.on_change(...), käyttäjän muokatessa. |
Samat säännöt pätevät telakkapaneeleihin ja asetussivuihin.