Automatizálások

A .clinkplugin fájl opcionális automation objektuma eseményeket, állapotot, beállításokat, parancsokat, kész szabályokat és parancsikonhelyeket deklarál. Minden elemnek stabil azonosítója, pontos sémaverziója és lokalizált címe van. A gazda hozza létre a plugin/<plugin-id>/<kind>/<id> neveket. Egy bővítmény nem használhat rendszerbeli vagy másik bővítményhez tartozó névteret.

Automatizálások ›

Hogyan működnek a bővítmények

A panel a billentyűket váltja fel, a művelet pedig egyszer fut le egy szövegrészen. A bővítménynek nincs saját képernyője a billentyűzeten. A Clink meghatározott pillanatokban hívja a függvényeit, például amikor megnyílik a billentyűzet, vagy amikor befejezel egy szót, a bővítmény pedig frissítheti a szóközt vagy a saját mentett állapotát. A beállításai az appban jelennek meg, ugyanazokkal az építőelemekkel, amelyeket a panelek is használnak. A lenti WPM Spacebar egy teljes bővítmény.

def initial():
    return {"on": False}

def settings(state):
    return section("keys.spacebar", [
        toggle("Show typing speed", state["on"], action="toggle"),
    ], title="WPM Spacebar")

def on_action(action, value, state):
    state["on"] = value
    if value:
        claim("spacebar.text")
    else:
        release("spacebar.text")
        space_text(None)
    return state

def on_word(word, state):
    if state["on"]:
        space_text(f"{stats()['wpm']} wpm")
    return state
A WPM Spacebar egy kapcsolót ad a Billentyűk > Szóköz alá. Amíg be van kapcsolva, a szóköz a pillanatnyi gépelési sebességedet mutatja.

A bővítményekhez Clink Pro szükséges. Mielőtt tárolóból telepítenél egyet, a Clink megkérdezi, engedélyezed-e az abból a tárolóból származó kódot, ugyanúgy, mint a paneleknél és a műveleteknél.

Az on_key és az on_word megkapja, amit gépelsz, egy szószámláló is így működik. A PyMini nem fér hozzá a hálózathoz és a fájlokhoz, ezért a bővítmény nem tudja elküldeni az interneten, amit gépelsz, amit pedig elment, az a Clinknél marad a készülékeden.

Az első bővítményed

A leggyorsabb út az indító szkript, amelyet az app ír meg neked. Egy kapcsolót tesz a Billentyűk > Szóköz alá, és amíg a kapcsoló be van kapcsolva, szavakat számol a szóközön. Öt lépés, letöltés nélkül.

  1. Nyisd meg a Bővítmények lapot, kapcsold be a bővítményeket felül, és koppints a + jelre egy új bővítményhez.
  2. A szerkesztő az indító szkripttel nyílik meg. Olvasd végig egyszer: initial(), settings(), on_action(), on_open() és on_word() az egész.
  3. Válts az Előnézetre. Kapcsold át a kapcsolót, majd koppints néhányszor az on_open és on_word gombokra, és figyeld a szóköz makettjét és a konzolt.
  4. Mentés. A bővítmény be van kapcsolva a listában, és a kapcsolója most már a Billentyűk > Szóköz alatt is ott van.
  5. Nyisd meg a billentyűzetet bárhol, és gépelj. A szóköz számol veled.
def initial():
    return {"on": False, "words": 0}

def settings(state):
    return section("keys.spacebar", [
        toggle("Count words on the space bar", state["on"], action="toggle"),
    ], title="Word count")

def on_action(action, value, state):
    if action == "toggle":
        state["on"] = value
        if value:
            claim("spacebar.text")
        else:
            release("spacebar.text")
            space_text(None)
    return state

def on_open(state):
    state["words"] = 0
    if state["on"]:
        space_text("0 words")
    return state

def on_word(word, state):
    state["words"] += 1
    if state["on"]:
        space_text(f"{state['words']} words")
    return state
Az indító szkript, ahogy az app megírja.

Horogpontok

Definiáld a 33 függvény bármelyikét, a feleslegeseket pedig hagyd ki. Mindegyik utolsó argumentumként megkapja a state értéket. Amelyek valamire reagálnak, visszaadják a state értéket, akár módosították, akár nem. Amelyek egy kérdésre felelnek (elements, draw, effects, a megjelenési horogpontok, haptics, hitboxes, suggestions és correct), a válaszukat adják vissza, és közben helyben is módosíthatják a state értéket.

HorogpontMikor fut
on_automation(command, args, state)Az on_automation(command, args, state) egy jóváhagyott helyi parancsot futtat a meglévő elkülönített környezetben. Frissítheti a szóköz feliratát, közzétehet deklarált állapotot vagy kibocsáthat deklarált eseményt. Ez a hook nem szúrhat be szöveget, nem férhet hozzá a vágólaphoz, nem módosíthat tartós beállítást, és nem indíthat külső kérést.
initial()Egyszer, mielőtt bármilyen mentett állapot létezne. Adj vissza egy dict értéket bármivel, amit a JSON tárolni tud.
settings(state)Amikor a bővítmény beállításai megjelennek az appban. Add vissza a vezérlőit csomópontfaként. A billentyűzetben soha nem fut le.
on_action(action, value, state)Amikor a bővítmény valamelyik vezérlőjét használják. Az on_action(action, state) alak, value nélkül, szintén működik.
on_open(state)Amikor megjelenik a billentyűzet. Jó hely a stats() kiolvasására vagy a szóköz beállítására.
on_close(state)Amikor a billentyűzet bezárul. Az állapot közvetlenül ezután mentődik.
on_key(key, state)Minden alkalommal, amikor egy billentyű beír valamit. Minden leütésnél lefut, ezért legyen gyors.
on_word(word, state)Amikor egy szó elkészül, akár szóközzel, javaslattal vagy csúsztatással.
on_backspace(state)Amikor a törlés billentyűt lenyomják. Szöveget nem kap, csak az állapotot.
on_suggestion(word, state)Amikor egy javaslatra koppintanak. A word az, amelyikre koppintottak.
on_language(code, state)Amikor a gépelés nyelve megváltozik. A code az új nyelv, például en vagy de.
on_field(kind, state)Amikor a billentyűzet egy mezőhöz kapcsolódik. A kind értéke default, email, url, number, phone, password vagy search.
on_tick(state)Másodpercenként egyszer, amíg a billentyűzet látszik, akár gépelsz, akár nem. Ez a horogpont mindenhez, aminek magától kell változnia: óra, visszaszámlálás, vagy sebesség, amelynek nullára kell esnie, ha abbahagyod.
on_swipe(direction, state)Egy betűbillentyűn kezdődő legyintés: "left", "right", "up", "up_left" vagy "up_right". Csak akkor érzékeli, ha a húzásos gépelés ki van kapcsolva. Ha a horogpont nem kér semmit, a legyintés sima billentyűleütés marad; ha kér, előbb visszavonja azt a betűt, amelyen kezdődött.
elements(state)Amit ez a bővítmény egy egyéni kiosztásnak kínál. Adj vissza element(id, name, icon=, width=) bejegyzéseket, vagy hagyd ki a horogpontot.
draw(id, state)Egy elem arca, csomópontfaként. Nagyjából másodpercenként egyszer fut, amíg a billentyűzet látszik.
effects(state)Fényeffektek, amelyeket ez a bővítmény a Hatások oldalnak kínál. Adj vissza light_effect(...) bejegyzéseket, vagy hagyd ki a horogpontot.
key_styles(state)Billentyűstílusok a témaszerkesztőnek. Adj vissza key_style(...) bejegyzéseket; lásd lent a Megjelenések részt.
themes(state)Teljes témák a témaszerkesztő Bővítmények lapjára. Adj vissza theme(...) bejegyzéseket.
popups(state)Billentyű-előugró stílusok. Adj vissza popup_style(...) bejegyzéseket.
animations(state)Animációk: entrance(...), press_animation(...), letter_animation(...) és transition(...) tetszőleges keveréke.
backgrounds(state)Animált hátterek. Adj vissza particles(...) rétegekből álló background(...) bejegyzéseket.
layouts(state)Billentyűzetkiosztások. Adj vissza layout(...) bejegyzéseket.
trails(state)Húzási csíkok, amelyeket ez a bővítmény a csíkválasztónak kínál. Adj vissza trail(...) bejegyzéseket; lásd lentebb a Megjelenéseket.
haptics(state)Billentyűnként egy haptikus visszajelzés, billentyűnevekből érzetekre mutató dict formájában. A billentyűzet megnyitásakor, majd nagyjából másodpercenként olvasódik be.
hitboxes(state)Billentyűnként egy érintési terület, billentyűnevekből hitbox(...) értékekre mutató dict formájában. Ugyanabban az ütemben olvasódik be, mint a haptics.
on_touch(key, x, y, state)Minden koppintás után: melyik billentyűhöz került, és azon a billentyűn hol ért le az ujj. Az x és az y -0.5 és 0.5 között mozog, középen 0.
suggestions(word, state)Szavak a javaslatsávba, amíg a word gépelése folyik. Akkor fut, amikor a sáv megnyugszik, nem minden billentyűnél.
correct(word, fix, state)A szóköz épp lezárta a word szót. Adj vissza egy szót, amely helyette kerül be, False értéket, hogy maradjon úgy, ahogy begépelték, vagy None értéket, hogy a billentyűzet saját javítása érvényesüljön.
bar_items(state)Gombok és tárcsák, amelyeket ez a bővítmény a felső sávnak kínál. Adj vissza bar_button(...) és bar_knob(...) bejegyzéseket, vagy hagyd ki a hookot.
key_art(state)A billentyűkre festendő grafika, billentyűnevekből alakzatokra mutató dict formájában. Minden esemény után újra beolvasódik, amit a bővítmény hall, így a hookban módosított állapot megjelenik a billentyűkön.
events(state)Az eseménynevek, amelyeket az on_event hallani akar, a bővítmény betöltésekor egyszer beolvasva. Enélkül a bővítmény mindent hall a sűrű események kivételével.
on_event(name, info, state)Egyetlen hook mindenre, ami történik: open, close, word, backspace, suggestion, language, field, shift és plane, továbbá a sűrű key, key_down, key_up, predictions és tick, amelyeket névre szólóan kell kérni az events(state)-ben.
def on_key(key, state):
    if key == " " and setting("language") == "en":
        state["spaces"] = state.get("spaces", 0) + 1
    return state

def on_close(state):
    haptic("light")
    return state
Két horogpont, egy olvasás és egy panelparancs.

Az app és a billentyűzet az állapot egyetlen példányán osztozik. Ha az appban bekapcsolsz egy kapcsolót, a billentyűzet következő megnyitásakor be lesz kapcsolva. Amit a billentyűzet számol, az ott lesz, amikor legközelebb megnyitod a bővítmény beállításait. A billentyűzet bezáráskor menti az állapotot, nem minden billentyű után.

Aktuális javaslat a szóközbillentyűn

A fő megjelenített javaslatot a context()["suggestion"] értékéből olvashatod ki. Iratkozz fel a predictions eseményre, hogy a változásokat az info["suggestion"] mezőben kapd meg. Mindkettőhöz hozzáférés kell a gépelési adatokhoz. Az on_suggestion egy javaslat elfogadásakor fut le, nem a javaslatok változásakor. A space_text(value or None) beállítja a feliratot, vagy visszaállítja, ha nincs javaslat. A szóközbillentyű működése nem változik.

def initial():
    return {}

def events(state):
    return ["predictions"]

def on_open(state):
    space_text(context()["suggestion"] or None)
    return state

def on_event(name, info, state):
    if name == "predictions":
        space_text(info["suggestion"] or None)
    return state

def on_close(state):
    space_text(None)
    return state

Állapot

Az állapot egyetlen dict. Az initial() építi fel először; utána minden horogpont ugyanazt a dict-et kapja, módosítja és visszaadja. Bármit tárol, amit a JSON tud: számokat, sztringeket, listákat, egymásba ágyazott dict-eket. Az app minden használt vezérlő után menti, a billentyűzet bezáráskor, és mindkettő ugyanazt a fájlt olvassa, így sosem térnek el sokáig.

def initial():
    return {"session": 0, "total": 0, "longest": ""}

def on_open(state):
    state["session"] = 0        # starts over each time the keyboard opens
    return state

def on_word(word, state):
    state["session"] += 1
    state["total"] += 1         # survives, it is saved when the keyboard closes
    if len(word) > len(state["longest"]):
        state["longest"] = word
    return state

def settings(state):
    return vstack([
        text(f"{state['total']:,} words so far"),
        text(f"Longest: {state['longest'] or '...'}", size=13, color="gray"),
        button("Start over", "reset", style="destructive"),
    ])

def on_action(action, value, state):
    if action == "reset":
        return initial()
    return state
Egy munkamenetenkénti számláló, amelyet az on_open nulláz, és egy megmaradó összeg.

Az állapot visszaadása jó szokás, de nem kötelező: a dict referencia, ezért a helyben módosítás is működik. Adj vissza egy másik dict-et, mint fent az initial(), és az lesz az állapot.

Beállítások és szakaszok

A settings(state) a panelépítőkkel készült csomópontfát ad vissza: text, toggle, slider, stepper, segmented, button, row, field és az elrendezések. Ez a bővítmény oldalán jelenik meg a Bővítmények lapon. Ha egy részét section(anchor, children, title) hívásba csomagolod, az a rész a Clink egyik saját beállításképernyőjén is megjelenik, amellett a beállítás mellett, amelyhez kapcsolódik.

def settings(state):
    return vstack([
        text("Counts words as you type.", size=13),
        section("keys.spacebar", [
            toggle("Count on the space bar", state["on"], action="toggle"),
            stepper(state["goal"], min=10, max=500, step=10, label="Goal", key="goal"),
        ], title="Word count"),
    ])
A kapcsoló és a léptető a Billentyűk > Szóköz alatt jelenik meg. A felirat csak a bővítmény saját oldalán látszik.

A vezérlők, amelyekre egy bővítménynek a leggyakrabban szüksége van. Mindegyik vagy a key alá írja az új értékét az állapotba, vagy megnevez egy action-t az on_action számára, vagy mindkettőt. A teljes építőlista, az elrendezésekkel együtt, a panelek oldalán van.

ÉpítőelemMit rajzol
toggle(label, on=False, key="", action="")Kapcsoló. A key True vagy False értéket ír az adott állapotkulcsba.
slider(value, min=0, max=100, step=1, label="", key="", action="")Csúszka min és max között. A key az állást írja az adott állapotkulcsba.
stepper(value, min=0, max=100, step=1, label="", key="", action="")Egy érték − és + gombbal, min és max között.
segmented(options, value=None, key="", action="")Egy választás egy listából. A key a kiválasztott elemet írja az állapotkulcsba.
field(key, placeholder="", action="", submit="")Szövegdoboz, amely a state[key] kulcshoz kötődik. Megérintve a billentyűk abba a kulcsba írnak; a submit nevezi meg az Enterre futó kezelőt.
button(label, action="", value=None, insert="", set=None, style="plain", icon="", enabled=True)Egy gomb. Az insert beírja a szövegét oda, ahol éppen írsz, a set kulcsokat olvaszt az állapotba, az action pedig kezelőt nevez meg az on_action számára. A style lehet plain, primary, tinted, quiet vagy destructive.
row(title, subtitle="", detail="", icon="", action="", value=None, insert="")Megérinthető sor: cím, második sor, ikon és jobbra egy részlet.
text(s, size=17, weight="regular", color="", align="leading", lines=0, mono=False)Egy szövegsor. A weight lehet regular, medium, semibold, bold, heavy, light vagy thin; az align lehet leading, center vagy trailing; a lines korlátozza a tördelt sorok számát; a color színnevet vagy #RRGGBB értéket vesz.
Panelek ›

Hová kerülnek a szakaszok

A horgony egy kártya azonosítója a Clink saját beállítási képernyőinek egyikén. Nevezd meg a section() hívásban, és a bővítmény vezérlői közvetlenül az alá a kártya alá rajzolódnak, fölöttük a bővítmény nevével. A legegyszerűbb megtalálni: az appban nyisd meg a Továbbiak > Fejlesztő menüt, és kapcsold be az Azonosítók megjelenítését. Minden kártya kap egy kis infójelvényt, amely megnevezi az azonosítóját és koppintásra másolja; az oldalak a címsorban mutatják a sajátjukat.

Minden horgony, amelyet egy szakasz megnevezhet

  • analytics.heatmap
  • analytics.privacy
  • analytics.trends
  • analytics.typing-test
  • automations.rules
  • gestures.accents
  • gestures.cursor
  • gestures.delete
  • gestures.general
  • gestures.suggestions
  • gestures.swipe
  • haptics.feel
  • keys.adaptive
  • keys.faces
  • keys.hitboxes
  • keys.hitmap
  • keys.long-press
  • keys.numberrow
  • keys.onehanded
  • keys.roundness
  • keys.size
  • keys.spacebar
  • keys.spacing
  • keys.split
  • languages.app
  • languages.custom
  • languages.manage
  • languages.packs
  • languages.switch
  • languages.typing
  • layout.arrange
  • layout.arrangement
  • layout.build
  • layout.longpress
  • layout.presets
  • layout.topbar
  • motion.delete
  • motion.entrance
  • motion.glow
  • motion.key-press
  • motion.key-response
  • motion.letters
  • motion.space-response
  • motion.transition
  • popups.style
  • sound.keysounds
  • text.automation
  • text.content
  • text.corrections
  • text.history
  • text.punctuation
  • text.speed
  • text.suggestions
  • text.symbols
  • themes.background
  • themes.canvas
  • themes.theme

A keys.spacebar saját helyet kap, magán a Szóköz képernyőn. Egy szakasz olyan horgonnyal, amely nincs ebben a listában, továbbra is megjelenik a bővítmény oldalán, így egy elgépelés egy kártyába kerül, nem a bővítménybe.

Átvételek

Amikor egy bővítmény a Clink saját beállításainak egyikét vezérli, az embernek látnia kell ezt, és a kettő nem harcolhat egymással. A claim(control) kimondja, hogy a bővítményé: az app a beállítás kártyáján kiírja a bővítmény nevét, a szóköz szövegmezője pedig zárolva van, amíg a bővítmény tartja. A release(control) visszaadja. Az átvétel abban az on_action-ben legyen, amely bekapcsolja a funkciódat, az elengedés abban, amely kikapcsolja, és ugyanakkor állítsd vissza az értéket None-ra vagy a régi értékére. A listában kikapcsolt bővítmény mindent elenged, amit tartott.

def on_action(action, value, state):
    if action == "toggle":
        state["on"] = value
        if value:
            claim("spacebar.text")
            space_text("...")
        else:
            release("spacebar.text")
            space_text(None)      # hand the person's own text back
    return state
A pár, amely minden átvevő bővítményben megvan: bekapcsoláskor elvesz, kikapcsoláskor visszaad.

Két bővítmény is átveheti ugyanazt a vezérlőt; az app azt nevezi meg, amelyik utoljára vette át. Az átvételeket az app jegyzi fel, ezért az on_action-ből vedd át, amely ott fut. A billentyűzeten belül tett átvétel nem marad meg.

Parancsok és olvasások

A bővítmények minden panelparancsot használhatnak, ezen felül van hat saját parancsuk és két olvasásuk. A parancsok sorba kerülnek, és azután hajtódnak végre, hogy a függvényed visszatért, így a billentyűzeten semmi sem változik egy hívás közepén. Az olvasások a közvetlenül a hívás előtti értékeket adják vissza.

HívásMit csinál
space_text(text)Feliratot jelenít meg a szóközön, legfeljebb 32 karakterben. None értéket átadva visszaáll a felhasználó saját szóközszövege.
space_language_text(text)Felülírja a szóköz sarkában lévő nyelvjelzőt, önmagában, akkor is, ha a beépített jelző ki van kapcsolva. Egy sor, legfeljebb 12 karakter; a "" elrejti, a None pedig visszaadja a beépített szöveget.
space_language_flag(language)Zászlót tesz erre a jelzőre egy nyelvazonosító, például en_GB alapján, a mellékelt zászlógrafikából. A None visszaadja a beépített viselkedést.
space_language_emoji(language)Ugyanaz a jelző, a régió zászlóemodzsijaként. A három jelzőparancs egyetlen helyen osztozik, így az egyik jelzőbővítmény bekapcsolása kikapcsolja a többit.
set_setting(name, value)Név alapján módosítja a Clink egy beállítását megfelelő fajtájú értékre: logikai érték, a tartományon belüli szám, a választási lehetőségek egyike vagy szöveg. Ismeretlen név KeyError hibát dob. A rossz fajtájú vagy tartományon kívüli érték nem lép érvénybe, és a szerkesztő konzolja megmondja, mit vár a beállítás.
claim(control)Átvesz egyet a Clink saját beállításai közül. A kártyája az appban megnevezi a bővítményt, amelyik tartja.
release(control)Visszaadja a beállítást. Egy bővítmény kikapcsolásakor minden felszabadul, amit átvett.
suggest(words)Legfeljebb tíz saját szót tesz a javaslatsáv elejére. Addig maradnak, amíg valaki rá nem koppint egyre, meg nem nyomja a törlést, vagy a mező nem változik; a suggest([]) hamarabb eltünteti őket. Koppintásra begépeli a szót.
banner(text)Rövid üzenetet mutat a billentyűzeten egy pillanatra. Egy jelzésre való, nem beszélgetésre.
press(key)Lenyomja a billentyűzet egyik saját gombját, mintha megérintették volna: "space" vagy "delete". Bármely más név ValueError hibát dob.
pick_suggestion(slot)A sáv "left", "center" vagy "right" részében lévő javaslatot választja, pont úgy, mint egy koppintás. Görgetett sávnál az számít, ami a képernyőn látszik. Az on_swipe hookon belül abból a sávból választ, amilyen az ujj érintésekor volt.
stats()Egy dict értéket ad vissza wpm, peak_wpm, keystrokes, words és streak mezőkkel. A wpm élőben frissül, amíg a bővítmények be vannak kapcsolva. Az összesítések az Elemzésből jönnek, és nem frissülnek tovább, ha az Elemzés ki van kapcsolva.
setting(name)Név szerint kiolvassa az alább felsorolt beállítások egyikét. Bármilyen más név KeyError hibát vált ki.
context()Ugyanaz a pillanatkép, amit egy panel is olvas, bővítménynél kiegészülve a suggestion, shift (off, on vagy locked) és plane kulcsokkal. A dokumentumkulcsokat a gépelési adatokhoz való hozzáférés tölti fel; a shift enélkül is olvasható.
KulcsMit tartalmaz
stats()["wpm"]Szó per perc az utolsó néhány másodpercből, a mezőbe érkező karakterek alapján. A szám egy-két másodperccel az indulás után jelenik meg, szünet alatt csökken, és nullára ér, ha abbahagyod. A törlés sosem növeli.
stats()["peak_wpm"]A Statisztika által valaha rögzített legjobb sebesség.
stats()["keystrokes"]Összes leütés, ahogy a Statisztika számolja.
stats()["words"]Véglegesített szavak összesen.
stats()["streak"]Egymást követő gépelős napok, a mai nappal bezárólag.

A setting(name) és a set_setting(name, value) egyetlen névlistán osztozik, és a claim(control) is bármelyiket elfogadja. A logikai értékek True vagy False formában olvashatók, a számok számként, a választások az azonosítójukkal. A lista szándékosan hosszú: egy bővítmény szinte mindenre reagálhat, vagy majdnem mindent vezérelhet, amit egy személy az appban beállíthat.

A setting() által elfogadott nevek

  • analytics
  • emoji.skin_tone
  • emoji.trailing_space
  • gestures.cursor
  • gestures.cursor_style
  • gestures.highlight_shift
  • gestures.plane_slide
  • gestures.predictive_flick
  • gestures.quick_accent
  • gestures.swipe
  • gestures.swipe_delete
  • gestures.swipe_multi_word
  • gestures.swipe_space_commit
  • gestures.swipe_two_thumb
  • gestures.trail
  • gestures.trail_style
  • gestures.trail_width
  • haptics.enabled
  • haptics.intensity
  • haptics.sharpness
  • keys.accents
  • keys.glyph_scale
  • keys.height
  • keys.long_press_hint
  • keys.popup_style
  • keys.popups
  • keys.radius
  • keys.row_spacing
  • keys.spacing
  • keys.uppercase
  • keys.width
  • language
  • language.bar_key
  • language.bar_key_style
  • language.mode
  • layout
  • layout.dismiss_shortcut
  • layout.number_row
  • layout.number_row_scale
  • layout.one_handed
  • layout.one_handed_shortcut
  • layout.one_handed_side
  • layout.one_handed_width
  • layout.split
  • layout.split_gap
  • layout.split_number_row
  • layout.split_shortcut
  • layout.split_space_bar
  • pet.corner
  • pet.enabled
  • pet.species
  • settings.accentHoldDelay
  • settings.accentMoveCancel
  • settings.activateWithIcon
  • settings.adaptiveGrow
  • settings.adaptiveHitboxes
  • settings.adaptivePredictAtWordStart
  • settings.adaptivePredictionWeight
  • settings.adaptiveShrink
  • settings.adaptiveSpace
  • settings.aiAutocorrect
  • settings.aiCompletions
  • settings.aiExtensionEnabled
  • settings.aiSearch
  • settings.aiToolsColorOverrides
  • settings.aiToolsDiffStyle
  • settings.aiToolsDisabled
  • settings.aiToolsLayoutStyle
  • settings.aiToolsOrder
  • settings.aiToolsPromptOverrides
  • settings.aiTranslate
  • settings.alternatingSplit
  • settings.arabicIndicNumerals
  • settings.backgroundEffectOverride
  • settings.clipboardCloseOnPaste
  • settings.clipboardDeleteOnPaste
  • settings.clipboardIgnoreImages
  • settings.clipboardIgnorePinsOnDelete
  • settings.clipboardStyle
  • settings.cursorActivationHaptic
  • settings.cursorLineStride
  • settings.cursorStepHaptic
  • settings.customPanelsStandalone
  • settings.customPetID
  • settings.deleteWordSwipeEngage
  • settings.deleteWordSwipeStride
  • settings.dictationAssist
  • settings.dictationAssistCustom
  • settings.dictationAssistLevel
  • settings.dictationColorScheme
  • settings.dictationGlassCapsule
  • settings.dictationSmartActions
  • settings.dictationStyle
  • settings.dictationVisualStyle
  • settings.dragUpThreshold
  • settings.emojiCategoryOrder
  • settings.emojiCellSpacing
  • settings.emojiColumnCount
  • settings.emojiCrossAxisSwitchesTab
  • settings.emojiCustomSets
  • settings.emojiGlyphScale
  • settings.emojiHiddenCategories
  • settings.emojiHiddenFromPanels
  • settings.emojiRecentsCap
  • settings.emojiRecentsSort
  • settings.emojiRememberCategory
  • settings.emojiRowCount
  • settings.emojiScrollDirection
  • settings.emojiSearchSlot
  • settings.emojiShowABCKey
  • settings.emojiShowBackspaceKey
  • settings.emojiStartCategoryID
  • settings.emojiTabBarSlot
  • settings.emojiTabIconStyle
  • settings.emojiToneHoldDelay
  • settings.extensionOrder
  • settings.extraTopBars
  • settings.formFreeCorners
  • settings.formLayoutEnabled
  • settings.gifShareAsLink
  • settings.glassPerRowMerge
  • settings.glassReleaseResponse
  • settings.gridSwitchAnimation
  • settings.gridSwitchDuration
  • settings.handwritingInkColor
  • settings.handwritingInkGlow
  • settings.handwritingInkStyle
  • settings.handwritingInkWidth
  • settings.hitboxScale
  • settings.iconPickerStyle
  • settings.keyBloomScale
  • settings.keyLighting
  • settings.keyPressGlow
  • settings.keyPressInstant
  • settings.keyPressLinger
  • settings.keySpringDamping
  • settings.keySpringResponse
  • settings.keyboardBottomPadding
  • settings.keyboardLanguages
  • settings.keyboardTopPadding
  • settings.longPressGlyphScale
  • settings.minPressVisible
  • settings.notepadBrowseStyle
  • settings.notepadMode
  • settings.numberRowFontSize
  • settings.numberRowLeadingKeys
  • settings.numberRowTrailingKeys
  • settings.oneHandedCustomKeys
  • settings.oneHandedExtraKeys
  • settings.panelButtonHitboxScale
  • settings.persistentLeadingKeys
  • settings.persistentTrailingKeys
  • settings.petIdleMotion
  • settings.petScale
  • settings.pinyinFuzzyEnabled
  • settings.pluginLooks
  • settings.popupSpringDamping
  • settings.popupSpringResponse
  • settings.predictiveFlickSuggestionPosition
  • settings.predictiveFlickSuggestionsSeparate
  • settings.reduceEffectsOnLowPower
  • settings.repeatAccelStep
  • settings.repeatHoldDelay
  • settings.repeatInitialInterval
  • settings.repeatMinInterval
  • settings.replacementsLayout
  • settings.rowInsets
  • settings.secondaryNeuralModelsEnabled
  • settings.separateActivation
  • settings.separateLanguageLayouts
  • settings.showCaptureOverlay
  • settings.showCorrectionField
  • settings.showHitboxOverlay
  • settings.showIconsBeforeTyping
  • settings.showRecentEmoji
  • settings.showTouchHeatmap
  • settings.showTouchSurfaceBounds
  • settings.showTouchTelemetryOverlay
  • settings.slideUpPickerStyle
  • settings.solidPopupOpacity
  • settings.soundVoice
  • settings.spaceBloomScale
  • settings.spaceCursorActivationDelay
  • settings.spaceCursorDragScale
  • settings.spaceCursorStride
  • settings.spaceLeanMultiplier
  • settings.spaceSpringDamping
  • settings.spaceSpringResponse
  • settings.spatialBiasEnabled
  • settings.spatialBiasGain
  • settings.splitIndices
  • settings.splitOtherPlanes
  • settings.stickerGridSnap
  • settings.stickerPlacements
  • settings.suggestionDebounceDelay
  • settings.suggestionHitboxScale
  • settings.suggestionSegmentLiquidGlass
  • settings.suggestionSegmentStyle
  • settings.suggestionSegmentsFollowTheme
  • settings.suggestionSeparatorColor
  • settings.suggestionSeparatorStyle
  • settings.suggestionTopPadding
  • settings.swipeKeyMorph
  • settings.swipeMorphRadius
  • settings.swipeMorphStrength
  • settings.swipeTrailEndWidth
  • settings.swipeTrailMaxLength
  • settings.swipeTrailStartWidth
  • settings.swipeTrailTrim
  • settings.toolsButtonStyle
  • settings.toolsHiddenFromPanels
  • settings.topBarItems
  • settings.topBarOrder
  • settings.translateLanguageOrder
  • settings.translateLanguagesDisabled
  • settings.translateStyle
  • settings.translateTone
  • settings.vietnameseInputMethod
  • sound.enabled
  • sound.pack
  • sound.volume
  • spacebar.corner
  • spacebar.language_code
  • spacebar.size
  • spacebar.text
  • stickers.enabled
  • text.arithmetic
  • text.auto_capitalize
  • text.auto_punctuation
  • text.autocorrect
  • text.autocorrect_everywhere
  • text.contacts
  • text.conversions
  • text.double_space_period
  • text.learning
  • text.punctuation_spacing
  • text.return_to_letters
  • text.revert_on_delete
  • text.smart_quotes
  • text.suggestions
  • text.suggestions_animation
  • text.suggestions_height
  • text.suggestions_scroll
  • text.suggestions_style
  • theme
  • theme.background
  • theme.dark
  • theme.delete_glyph
  • theme.entrance
  • theme.glyph_press
  • theme.light
  • theme.match_system
  • theme.press_style
  • theme.reactive_background
  • tools.calculator
  • tools.cling
  • tools.clipboard
  • tools.conversion
  • tools.dictation
  • tools.dictionary
  • tools.emoji
  • tools.gif
  • tools.handwriting
  • tools.layout_switcher
  • tools.notepad
  • tools.plugin_switcher
  • tools.profiles
  • tools.replacements
  • tools.textfx
  • tools.theme_switcher
  • tools.translate

Parancsok

  • insert()
  • backspace()
  • delete_word()
  • replace()
  • move_cursor()
  • copy()
  • close()
  • haptic()
  • toast()

Ahogy egy panel view() függvénye, a settings() is csak vezérlőket írjon le. Az onnan hívott parancsok nem hajtódnak végre, csak bekerülnek a konzolnaplóba.

Példák

Öt kis bővítmény, mindegyik teljes. Illessz be egyet egy új bővítménybe, mentsd el, és fut.

def initial():
    return {"on": True}

def settings(state):
    return section("keys.spacebar", [
        toggle("Language on the space bar", state["on"], action="toggle"),
    ], title="Language badge")

def on_action(action, value, state):
    if action != "toggle":
        return state
    state["on"] = value
    if value:
        claim("spacebar.text")
        space_text(setting("language").upper())
    else:
        release("spacebar.text")
        space_text(None)
    return state

def on_open(state):
    if state["on"]:
        space_text(setting("language").upper())
    return state

def on_language(code, state):
    if state["on"]:
        space_text(code.upper())
    return state
Nyelvjelvény: a gépelés nyelve a szóközön, frissül, amint megváltozik.
SHORTCUTS = {"omw": "on my way", "brb": "be right back", "ty": "thank you"}

def on_key(key, state):
    if key != " ":
        return state
    words = context()["before"].split()
    if words and words[-1] in SHORTCUTS:
        # the space is already in the text, so it goes too and comes back after
        replace(len(words[-1]) + 1, SHORTCUTS[words[-1]] + " ")
    return state
Rövidítések: írd be, hogy omw meg egy szóköz, és on my way lesz belőle. Az on_key a szóközt már beírás után látja, ezért a csere átlépi.
def initial():
    return {"goal": 200, "count": 0}

def settings(state):
    return vstack([
        stepper(state["goal"], min=50, max=2000, step=50, label="Words per session", key="goal"),
        progress(state["count"], total=state["goal"], label=f"{state['count']} of {state['goal']}"),
    ])

def on_open(state):
    state["count"] = 0
    return state

def on_word(word, state):
    state["count"] += 1
    if state["count"] == state["goal"]:
        haptic("medium")
        banner("Goal reached")
    return state
Szócél: egy léptető a bővítmény oldalán, egy folyamatjelző, és egy rezgés meg egy szalag, amikor a munkamenet eléri.
def initial():
    return {"muted": False, "was_on": True}

def on_field(kind, state):
    # a password or a number field is not a place for key sounds
    quiet = kind in ("password", "number", "phone")
    if quiet and not state["muted"]:
        state["was_on"] = setting("sound.enabled")
        state["muted"] = True
        set_setting("sound.enabled", False)
    elif not quiet and state["muted"]:
        state["muted"] = False
        if state["was_on"]:
            set_setting("sound.enabled", True)
    return state
Csendes mezők: a billentyűhangok kikapcsolnak jelszó- vagy számmezőben, és utána visszatérnek, az on_field, a setting() és a set_setting() segítségével.
NAMES = ["sam", "ana", "team"]

def on_key(key, state):
    typing = context()["before"].split(" ")[-1]
    if typing.startswith("@"):
        start = typing[1:].lower()
        suggest([n for n in NAMES if n.startswith(start)])
        state["showing"] = True
    elif state.get("showing"):
        suggest([])                 # the mention is over, give the bar back
        state["showing"] = False
    return state
Említések: a @ beírása a saját neveidet teszi a javaslatsávba.
def on_swipe(direction, state):
    if direction == "left":
        delete_word()
    elif direction == "right":
        press("space")              # the space bar's own path, so it autocorrects
    elif direction == "up":
        pick_suggestion("center")
    elif direction == "up_left":
        pick_suggestion("left")
    elif direction == "up_right":
        pick_suggestion("right")
    return state
Fleksy-stílusú legyintések, a Flick Gestures bővítmény lényege: balra egy szót töröl, jobbra szóközt ír, felfelé javaslatot választ. Legyintés csak akkor érkezik, ha a húzásos gépelés ki van kapcsolva.

Elemek egy kiosztásban

Egy egyéni kiosztás billentyűkből és elemekből áll: egy sáv a legutóbbi emojikkal, egy számsor, egy kurzorpad. Egy bővítmény hozzáadhatja a sajátjait. Az elements(state) megmondja, mit kínál, a draw(id, state) pedig megrajzol egyet, így egy billentyű bármit mutathat, amit a bővítmény ki tud számolni: gépelési sebességet, órát, visszaszámlálást vagy saját töltöttségjelzőt.

Két horogpont épít egyet. Az elements(state) felsorolja, mit kínálsz, elemenként egy bejegyzést, és az app ebből tölti fel a kiosztásszerkesztő palettáját. A draw(id, state) megkapja az egyik azonosítót, és visszaadja, mit kell rajzolni. Egy bővítmény többet is kínálhat; a draw mindegyikre külön kérdez rá.

HívásMit csinál
element(id, name, icon="", width=2)Egy felkínált elem. A width billentyűszélességben mér, ahogy egy kiosztás számolja, az icon pedig az az SF Symbol, amit a szerkesztő a palettáján mutat.
sparkline(values, min=None, max=None, fill=False)Vonal egy számsoron át, kitöltve a kapott helyet. Ha kihagyod a min és max értéket, a saját adataihoz igazodik. Csak bővítmény rajzolhatja, és billentyűre készült.
POINTS = 30

def initial():
    return {"history": []}

def elements(state):
    return [element("sparkline", "WPM sparkline", icon="waveform.path.ecg", width=3)]

def on_tick(state):
    history = state["history"]
    history.append(stats()["wpm"])
    state["history"] = history[-POINTS:]
    return state

def draw(id, state):
    rate = state["history"][-1] if state["history"] else 0
    return hstack([
        sparkline(state["history"], min=0, max=max(60, max(state["history"] or [0])), fill=True),
        text(f"{rate}", size=12, weight="semibold"),
    ], spacing=5, align="center")
A WPM Sparkline bővítmény teljes egészében: egyetlen elemet kínál, és arra rajzolja a sebességed utolsó harminc másodpercét.

Az arc egy csomópontfa, mint egy beállítási oldal, de a billentyű nem beállítási oldal: csak a rajzoló csomópontok számítanak, minden koppintható kimarad. A billentyű már a kiosztásé, így nincs benne hely egy gombnak.

AMIT EGY ARC RAJZOLHAT

  • sparkline
  • text
  • badge
  • icon
  • progress
  • hstack
  • vstack
  • spacer
  • divider

Billentyűméretre tervezd. A width billentyűszélességben mér: 1 egy betű, 3 nagyjából egy sor harmada, és utólag át lehet méretezni. A szöveg egy sort kap, és összehúzódik, hogy elférjen; a színek alapból a billentyű saját szövegszínét követik, így az elem illik a körülötte lévő billentyűkhöz, hacsak mást nem kérsz. Egy sparkline az utolsó 120 pontját tartja meg, többet, mint amennyit egy billentyű megmutathat.

import time

def elements(state):
    return [element("clock", "Clock", icon="clock", width=2)]

def draw(id, state):
    return text(time.format("HH:mm"), size=15, weight="semibold")
Óra egy billentyűn: nincs állapot, nincsenek horogpontok, csak az idő minden kérdésre. Az elemek maguktól újrarajzolódnak nagyjából másodpercenként.
GOAL = 200

def initial():
    return {"words": 0}

def elements(state):
    return [element("goal", "Word goal", icon="target", width=2)]

def on_open(state):
    state["words"] = 0
    return state

def on_word(word, state):
    state["words"] += 1
    return state

def draw(id, state):
    return vstack([
        text(f"{state['words']}/{GOAL}", size=11),
        progress(state["words"], total=GOAL),
    ], spacing=2)
Egy munkamenetre szóló szócél, amit az on_word számol és sávként rajzolunk ki. A horogpontok viszik az állapotot, a draw csak olvassa.

Az elemek egyéni kiosztásokban élnek, tehát előbb kiosztást kell építeni. Az előre elkészítettek nem tudnak elemet tartani: az első, amit a szerkesztő felajánl, hogy másold sajátoddá.

  1. Telepítsd a bővítményt és kapcsold be. Az elemei azonnal megjelennek.
  2. Nyisd meg a Kiosztást, hozz létre vagy másolj egy egyéni kiosztást, és lépj az Elrendezésre.
  3. Koppints az Elem gombra, válaszd ki a bővítmény elemét a sávból, és állítsd be a szélességét.

A szerkesztő Előnézete minden elemet kirajzol, amit a szkript kínál, nagyjából akkorában, mint a billentyű, amelyre kerül, a szóköz makettje alatt. Mentsd el, tedd ki egyszer, és a billentyűzet ugyanazt rajzolja.

Egy elem csak azt mutatja, amit a bővítmény rajzol: a koppintás nem csinál semmit, mert a billentyű már a kiosztásé. A kiosztás akkor is megtartja az elemet, ha a bővítménye ki van kapcsolva vagy eltávolították, és a billentyű újra megtelik, amint visszakerül.

Gombok és tárcsák a felső sávon

A billentyűk fölötti sávot a Kiosztás > Felső sáv alatt lehet összerakni, és egy bővítmény saját vezérlőket kínálhat bele. A bar_items(state) adja vissza őket: a bar_button(...) koppintásra való, a bar_knob(...) tekerésre. A lista a billentyűzet megnyitásakor és minden koppintás után újra beolvasódik, így egy elem a bővítmény állapotával jöhet és mehet.

HívásMit csinál
bar_items(state)Minden, amit ez a bővítmény a sávnak kínál, listaként. Az id-nek csak a bővítményen belül kell egyedinek lennie; a sáv a bővítmény saját azonosítója mellé teszi el. Ismétlődő id esetén az első marad, és amit a hook már nem ad vissza, az nem rajzolódik ki.
bar_button(id, name, icon="", title="")Egy gomb. A name az, amit a szerkesztő kilistáz, és amit a VoiceOver felolvas. Az icon egy SF Symbol, a title pedig legfeljebb 12 karakternyi felirat mellette: ikonnal és title nélkül az ikon áll magában, ikon nélkül a szöveg. A gombnak nincs értéke és nincs tartománya. Egy koppintás az on_action(id, None, state) hívást jelenti, és minden, amit a gomb csinál, ott történik.
bar_knob(id, name, icon="", min=0, max=1, step=0, value=0, setting=None, art=None, rotor=None)Egy tárcsa. A min és a max a tartománya, a step nullánál nagyobb értéknél fokozatokra osztja, a value pedig a kiindulópont. A setting= ehelyett az app egyik saját számvezérlőjéhez köti, és onnan jön a tartomány és az állás is. Az art= és a rotor= rajzolja meg Pythonban.
def initial():
    return {"width": 2.0}

def bar_items(state):
    return [
        bar_button("sig", "Sign off", icon="signature", title="Sign off"),
        bar_knob("volume", "Key volume", icon="speaker.wave.2", setting="sound.volume"),
        bar_knob("width", "Trail width", icon="scribble", min=1, max=6, step=0.5, value=state["width"]),
    ]

def on_action(action, value, state):
    if action == "sig":
        insert(" sent from Clink")
    elif action == "width":
        state["width"] = value
    return state
Egy gomb és két tárcsa, az egyik a billentyűhangerőhöz kötve

Mindkettő az on_action(action, value, state) hookon jön vissza, az elem id-je alapján, így a bővítmény sávelemei és a beállításvezérlői ugyanazt a hookot használják. Egy koppintás None-t küld. A tárcsa minden kattanásnál elküldi az értékét, amíg az ujj lent van, és még egyszer elengedéskor, így a bővítmény követheti a húzást, vagy megvárhatja az utolsó értéket.

A setting= paraméterrel ellátott tárcsa olyan beállítást tekeri, ami az appban már megvan, a fenti Parancsok és olvasások listájából, például sound.volume vagy haptics.intensity. Olyan név, amit az app nem ismer, KeyError a konzolon. A tartomány és a kiindulási állás ebből a vezérlőből jön, a billentyűzet saját másolata már húzás közben változik, így a következő leütés már az új szinten szól, az érték pedig elengedéskor mentődik. A nulláról felhúzott hangerő- vagy rezgéstárcsa a húzás idejére vissza is kapcsolja a hangot vagy a rezgést, hogy a kattanások felfelé menet hallatszódjanak és érezhetők legyenek; ezt a kapcsolót a bővítmény menti el, a saját set_setting hívásával az on_action-ben.

A tárcsa Pythonban is megrajzolható. Az art= az, ami a helyén marad, a foglalat vagy a test, a rotor= pedig a forgó lap, a minimumnál -135 fok, a maximumnál +135 fok. Mindkettő ugyanazokat az alakzatokat, festéseket, színátmeneteket és árnyékokat fogadja, mint a billentyűgrafika, egyenként legfeljebb tizenhat alakzatot, az unit="key" pedig a négyzetes számlapra méretezi a koordinátákat, ahol a negatív y-nál lévő mutató felfelé néz. A rajz megkapja a sáv szövegszínét "text" néven és a téma kiemelőszínét "accent" néven. Ha mindkettőt kihagyod, a tárcsa egy gyűrű az ikonnal a közepén; a szerkesztőben a sávba tett tárcsára bármelyik beépített kidolgozás rátehető.

A sávba magától nem kerül semmi. Az elemet kézzel kell odatenni, ugyanúgy, mint a menüt és a javaslatokat.

  1. Telepítsd a bővítményt és kapcsold be. A sávelemei rögtön megjelennek.
  2. Nyisd meg a Kiosztás > Felső sáv menüpontot.
  3. Add hozzá a bővítmény gombját vagy tárcsáját, és húzd a helyére. A tárcsához ezen felül kidolgozást is lehet választani.

Az építők szó nélkül átlépnek egy kulcsszót, amit nem ismernek. A setting=, min=, max=, step=, value=, art= és rotor= csak a bar_knob sajátja, így a bar_button ettől még egyszerű gombként épül fel, és nem szól semmi: a gomb munkája az on_action-be való. Fordítva a title= a gombé, a tárcsa pedig átlépi.

Fényeffektek

Egy bővítmény saját billentyűvilágítást is adhat. Az effects(state) light_effect(...) bejegyzéseket ad vissza, és mindegyik megjelenik az appban a Hatások > Bővítményekből részben, a beépített stílusok és a felhasználók saját effektjei mellett. Az effekt adat, nem rajz: rétegek halmaza, amelyet a billentyűzet maga animál. A szkriptben tehát semmi sem fut képkockánként, és a billentyűfelületek, a betűk, a ragyogás, a leütéskori felvillanás és az alvó mód ugyanúgy működik, mint a beépített stílusoknál.

HívásMit csinál
light_effect(id, name, layers=[...], colors=[], icon="")Egy effekt. Az id-nek csak a bővítményen belül kell egyedinek lennie. A layers light_layer(...) elemek listája, fentről lefelé alkalmazva. A colors legfeljebb nyolc "#rrggbb" karakterlánc, amelyeken a szín körbejár; ha elhagyod, az effekt a felhasználó Szín beállítását követi.
light_layer(pattern, ...)Egy réteg: egy minta az alábbi listából. Minden kulcsszó elhagyható.
COLORS = ["#00e5ff", "#7c4dff", "#ff4081"]

def effects(state):
    return [
        light_effect("tide", "Tide", colors=COLORS, layers=[
            light_layer("solid", low=0.2, high=0.2),
            light_layer("wave", moves="both", speed=0.8, size=1.5,
                        direction="up"),
        ]),
    ]
Egyenletes alap, rajta egy lassú hullám, amely három színen halad át. A hullám hozzáadja a fényét az alaphoz, és közben mozgatja a színt.

Minták

  • solid
  • pulse
  • wave
  • gradient
  • twinkle
  • sweep
  • rain
  • flicker
  • checker
KulcsMit csinál
moves="light"Mit változtat a minta: "light" a fényerőt, "color" vagy "both".
mix="add"Hogyan találkozik a fényereje a fölötte lévő rétegekkel: "add", "max" a fényesebbet tartja meg, "multiply" pedig maszkként elsötétíti őket.
shape="smooth"A pulse, a wave és a gradient emelkedése és esése: "smooth", "ramp", "step" vagy "spike".
direction="right"Merre halad a wave, a gradient, a sweep és a rain: "right", "left", "down", "up", vagy "out" a középről kifelé.
speed=10 és 4 között. 0-nál a minta áll.
size=10,25 és 4 között: hányszor ismétlődik a minta a billentyűzeten. A twinkle-nél azt adja meg, hány billentyű világít, a sweep-nél a csóva hosszát.
low=0, high=1A fényerő, amely között a minta mozog, mindkettő 0 és 1 között. Ha a low magasabb, mint a high, a minta megfordul.
color_span=1, color_offset=0Mennyit halad a minta a színeken, és honnan indul, mindkettő 0 és 1 között.
def effects(state):
    return [
        light_effect("scanner", "Scanner", layers=[
            light_layer("wave", moves="color", speed=0.3),
            light_layer("sweep", mix="multiply", speed=1.2, size=1.5),
        ]),
    ]
Maszkként használt sweep. Az első réteg csak a színt mozgatja, a sweep pedig eldönti, mely billentyűk világítanak. colors nélkül a Szín beállítást követi, így Színképpel szivárvány lesz belőle.

Egy effekt kiválasztása bemásolja azt a felhasználó beállításaiba, így kikapcsolt bővítménnyel is működik tovább. Amíg a bővítmény be van kapcsolva és valamelyik effektje fut, a billentyűzet megnyitáskor, majd nagyjából másodpercenként újra beolvassa az effects(state) eredményét, és átveszi, ami változott. Így követheti az effekt az állapotot, az időt vagy a stats() értékeit.

def effects(state):
    # Rounded, so the effect only changes when the pace really does.
    tempo = round(0.3 + min(stats()["wpm"], 120) / 40, 1)
    return [
        light_effect("tempo", "Tempo", colors=["#ff3d7f", "#ffb000"], layers=[
            light_layer("wave", moves="both", speed=tempo, low=0.15),
        ]),
    ]
A Tempo a Light Show bővítményből: egy hullám, amely annál gyorsabb, minél gyorsabban gépelsz. Egy réteg úgy is változtathat sebességet, hogy a mintája nem ugrik.

A szerkesztő effects gombja kilistázza, mit kínál a szkript. Ha mozgásban akarod látni, mentsd a bővítményt, válaszd ki az effektet a Hatások > Bővítményekből részben, és figyeld a képernyő tetején lévő billentyűzetet.

Kerekíts mindent, ami ugrál, például a gépelési sebességet. Egy effekt, amely minden másodpercben másképp érkezik vissza, minden másodpercben feleslegesen cserélődik. Ismeretlen minta vagy kulcsszó ValueError a szerkesztő konzoljában, a rétegek nélküli effekt pedig kimarad.

Megjelenések

Hét horogpont kínál választanivalót az appnak: key_styles, themes, popups, animations, backgrounds, trails és layouts. Mindegyik az alábbi hívásokkal épített bejegyzéseket ad vissza, és ezek a Bővítményekből alatt jelennek meg a beépített lehetőségek mellett. Kivételt a témák jelentenek: ezek saját Bővítmények lapot kapnak a témaszerkesztőben. Egy megjelenés számokból és szavakból áll, nem rajzoló kódból, így a szkriptben semmi sem fut képkockánként. A kiválasztás bemásolja a felhasználó beállításaiba, így kikapcsolt bővítménnyel is működik tovább, egy beépített lehetőség későbbi kiválasztása pedig félreteszi.

HívásMit csinál
key_style(id, name, material=, variant=, shape=, shadow=, cap=cap(...))Billentyűstílus, amely a témaszerkesztőben épp megnyitott témára kerül a Stílus kártyáról. Csak a megnevezett mezők változnak: material, variant, shape, glass, fan, a mechanikus inner_radius, face_inset, edges, raised és light_angle, shadow (a 0 lapos) és outline. A színek a témáé maradnak.
cap(outline="round", corner=None, travel=2, layers=[cap_layer(...)])Festett billentyűfelület egy billentyűstílushoz, cap_layer(...) bejegyzésekből rétegezve. Az outline round vagy rect, a corner felülírja a lekerekítést, a travel pedig azt mondja meg, milyen mélyre süllyed a billentyű lenyomáskor.
cap_layer(kind, paint, inset=0, x=0, y=0, blur=0, fade=None, when=[...])Egy festett billentyűfelület egy rétege. A kind fill, stroke vagy inner, a paint a billentyűszín-nyelvtant, egy color(...)-t vagy egy gradient(...)-et fogad, a when pedig a pale, dark, pressed, resting és highlighted állapotokra szűkíti a réteget. A moves=False a helyén tartja a réteget, miközben a billentyű süllyed.
theme(id, name, background=, keys=, key_text=, style=key_style(...), ...)Teljes téma a témaszerkesztő Bővítmények lapján. A background, keys és key_text kötelező "#rrggbb" színek; a special, special_text, accent, background_bottom (átmenet lefelé), dark, font és weight elhagyható. A style=key_style(...) adja a felület kidolgozását. Kiválasztva egyéni témaként települ.
popup_style(id, name, shape="tile", width=48, height=56, lift=30, ...)A lenyomott billentyű fölötti buborék, a Megjelenés > Előugró ablakok alatt. A shape értéke "tile", "round" vagy "balloon"; a width, height, lift és font_size pontban értendő, a response és a damping a rugót állítja.
entrance(id, name, opacity=0, x=0, y=0, scale=1, tilt=0, spin=0, ...)Ahogyan a billentyűzet megérkezik, a Megjelenés > Megjelenés alatt. Az opacity, x, y, scale, tilt és spin a kiinduló állapot; a response és a damping szerinti rugóval áll nyugalomba.
press_animation(id, name, scale=, x=0, y=0, rotation=0, ...)A lenyomva tartott billentyű alakja, a Reakciók > Geometria alatt: a scale (vagy a scale_x és a scale_y), az x, az y és a rotation teljes lenyomásnál.
letter_animation(id, name, scale=, x=0, y=0, rotation=0, anchor="center")A rövid mozdulat, amelyet egy betű minden koppintáskor lejátszik, a Reakciók > Betűk alatt: ugyanazok a számok a csúcson, plusz az anchor.
transition(id, name, x=0, y=0, scale=1, tilt=0, fade=True, duration=None)A váltás a betűk, a 123 és a #+= között, a Megjelenés > Átmenet alatt. Az x és az y azt adja meg, mennyit mozdulnak a régi billentyűk a billentyűzet arányában, az újak pedig tükrözve érkeznek. A scale, a tilt, a fade és a duration is megadható.
background(id, name, layers=[...], colors=[])Animált háttér, a Megjelenés > Háttér alatt: legfeljebb négy particles(...) réteg és legfeljebb nyolc "#rrggbb" szín.
particles(shape="glow", count=40, size=4, speed=20, direction="none", ...)Egy háttér egyik rétege. A shape értéke "dot", "glow", "streak", "ring" vagy "square"; a count, size, speed, direction, spread, gravity, wobble, life, twinkle és opacity alakítja a mozgást, a burst pedig részecskéket lő ki minden lenyomott billentyűből.
layout(id, name, rows=[...], left=[], right=[])Kiosztás, az Elrendezés > Elrendezés alatt. Minden sor billentyűk listája: egy karakterlánc betű, minden más layout_key(...). A left és a right legfeljebb három billentyűt tesz a szóköz mellé. A kiválasztása egy közönséges egyéni kiosztást telepít.
layout_key(glyph, action="insert", width=1)Billentyű, amely nem egyszerű betű. Az action értéke insert, spacer, shift, delete, space, return, numbers, emoji, globe, tab, left, right, undo, redo vagy dismiss, a width pedig billentyűben értendő.
trail(id, name, layers=[...], colors=[])Egy húzási csík. A layers trail_line, trail_stamps és trail_head bejegyzésekből áll, sorban kirajzolva, a colors pedig az a paletta, amire hivatkoznak.
trail_line(width=1, tail_width=1, color=-1, glow=0, dash=0, gap=0, band=0, flow=0)A húzás mentén futó vonal. A tail_width elvékonyítja a régi végét, a color=-1 az egész palettát elkeveri a vonal hosszában, a dash, gap, band és flow pedig feltördeli vagy mozgásba hozza.
trail_stamps(shape="dot", size=1, spacing=14, scatter=0, spin=0, twinkle=0, color=-1)A húzás mentén lehulló alakzatok: dot, ring, square, diamond, star, spark vagy heart. A spacing a köztük lévő távolság pontban, a scatter leszórja őket a vonalról, a spin forgatja, a twinkle pedig fel-le úsztatja őket.
trail_head(shape="dot", size=1.5, pulse=0, opacity=1, color=-1, glow=0)Az ujjhegynél lévő jel. A pulse lélegeztet rajta, a glow pedig fényt szór köré.
def animations(state):
    return [
        entrance("swoop", "Swoop", y=90, scale=0.94, tilt=-20,
                 response=0.5, damping=0.72),
        press_animation("dip", "Dip", scale=0.93, y=2),
        letter_animation("bounce", "Bounce", y=-7, scale=1.12,
                         anchor="bottom"),
        transition("glide", "Glide", x=0.3, scale=0.96),
    ]
Minden fajta animációból egy. Mindegyik a Bővítményekből alatt jelenik meg, a Megjelenés saját kártyáján.
def backgrounds(state):
    return [
        background("snowfall", "Snowfall", colors=["#ffffff", "#cfe8ff"], layers=[
            particles(shape="dot", count=70, size=2.2, speed=28,
                      direction="down", spread=12, wobble=10, life=9),
            particles(shape="glow", count=0, size=3, life=1,
                      burst=8, burst_speed=90),
        ]),
    ]
Snowfall: ringatózva hulló pelyhek, és egy kis fényfelvillanás minden lenyomott billentyűből.

A trails(state) függvény trail csomópontokat adjon vissza. Minden nyomnak van colors színpalettája és rétegei, például trail_line. A color=-1 értékkel a vonal színei fokozatosan váltakoznak a húzás mentén. Kapcsold be a bővítményt, majd válaszd ki a nyomát a nyomválasztó Bővítményekből részében. A rajzelemek állapotban tárolása önmagában nem rajzol nyomot.

def trails(state):
    return [trail("rainbow", "Rainbow", colors=["#ff0000", "#ff8800", "#ffff00", "#00cc44", "#0066ff", "#9900ff"],
        layers=[trail_line(width=1.3, tail_width=0.2, color=-1)])]
Szivárványos húzási nyom

Egy megjelenés a kiválasztáskor másolódik, így a szkript későbbi módosítása nem változtatja meg a már használt megjelenést; újra ki kell választani. Egy elgépelt kulcsszó, a listáján kívüli szó vagy szám helyett szöveg hiba a szerkesztő konzoljában, a számok pedig az app saját vezérlőinek tartományaiban maradnak.

Rajz a billentyűkön

A key_art(state) billentyűnevekből rajzra mutató dictet ad vissza, a billentyűzet pedig a billentyű felületére festi. A billentyűnevek ugyanazok, mint a haptics-nál, a letters és keys tartalékokkal. A rajz lehet shape(...) lista, egyetlen alakzat, egy art([...]) réteg vagy rétegek listája, és minden réteg a saját órája szerint úszik át a következő rajzába, így egy billentyű két, eltérő sebességgel mozgó dolgot is hordozhat.

HívásMit csinál
art(shapes, animate=0, curve="ease_out")Egy animálódó réteg. Adj át új rajzot, és a réteg animate másodperc alatt úszik át rá a curve mentén: ease_out, linear, ease_in, ease_in_out vagy spring. Az egy billentyűn lévő több réteg mind külön animálódik.
shape(kind, anchor="center", unit="pt", x=0, y=0, size=, width=, height=, fill=, stroke=, ...)Egy megrajzolt dolog: circle, rect, capsule, line, path, text vagy icon. A billentyű anchor pontjától x és y távolságra ül, pontokban vagy unit="key" esetén a billentyű arányában. A fill és a stroke hexszínt, "text" vagy "accent" értéket, color(...)-t vagy gradient(...)-et fogad, és van még line_width, corner, trim_from, trim_to, rotation, opacity, blur és legfeljebb három árnyék.
graph(values, min=None, max=None, width=0.8, height=0.25, stroke=, fill=)Számsor közönséges alakzatokká kiterítve, hogy alakzatlistához fűzd vagy önmagában használd. A legfrissebb 60 véges minta marad meg, a határok egyébként magából a sorból jönnek, a fill pedig zárt alapvonalat tesz a vonal alá.
color(value, opacity=1)Egy festés: hexszín, vagy "text", illetve "accent", amit az alatta lévő billentyűhöz képest old fel, opacity átlátszósággal.
gradient(kind, colors, stops=[], start=, end=, center=, radius=0.5)Lineáris vagy sugaras színátmenet egy színlistán át. A stops helyezi el a színeket, a start és az end irányítja a lineárist, a center és a radius helyezi el a sugarasat.
shadow(color, radius=4, x=0, y=0)Árnyék egy alakzat alatt, legfeljebb három. A billentyűt kitöltő fátyol követi a billentyű sarkait ahelyett, hogy szögletesre vágná; a ragyogás viszont kiszökik a billentyűről.

A rajz minden esemény után újra beolvasódik, amit a bővítmény hall, és ennyi az egész kör: állapotot módosítasz az on_event(name, info, state)-ben, és abból rajzolsz a key_art(state)-ben. Az events(state) nevezi meg a kívánt eseményeket, és a bővítmény betöltésekor olvasódik be egyszer. Enélkül a bővítmény mindent hall a key, key_down, key_up, predictions és tick kivételével, amelyek leütésenként vagy másodpercenként futtatnak szkriptet, ezért külön kell kérni őket. A shift és a sík változása akkor is újrarajzolja a rajzot, ha senki sem figyel, és a context()-be is eljut.

def initial():
    return {"shift": "off"}

def events(state):
    return ["shift"]

def on_event(name, info, state):
    state["shift"] = info["state"]
    return state

def key_art(state):
    if state["shift"] != "locked":
        return {}
    lamp = shape("circle", anchor="top_right", x=-7, y=7, size=5,
                 fill="accent", shadow=shadow("accent", radius=4))
    return {"shift": art([lamp], animate=0.12)}
Caps lock lámpa, amit a bővítmény rajzol, nem a billentyűzet tartalmaz

Alakzatok

  • circle
  • rect
  • capsule
  • line
  • path
  • text
  • icon

Billentyűnként tizenhat alakzat, az összes rétegét egybeszámolva, és útvonalanként 64 pont; ami ezen túl van, az kimarad. Az alakzat a saját width és height méretű dobozába rajzolódik, és a vastagság nélküli doboz semmit sem fest, ezért egy vízszintes vonalnak kell egy kis saját height, a pontjaival annak közepén (height=0.03, points=[[0, 0.5], [1, 0.5]]), különben szó nélkül nem jelenik meg.

Haptika, érintési területek és javítások

A haptics(state) és a hitboxes(state) billentyűnevekkel kulcsolt dicteket ad vissza: maga a betű, "space", "delete", "return", "shift" vagy "globe", aztán "letters" minden meg nem nevezett betűre és "keys" minden másra. A bővítmény által kihagyott billentyűk megtartják a felhasználó saját beállításait. Mindkét tábla a billentyűzet megnyitásakor, majd nagyjából másodpercenként olvasódik be, így miattuk semmi sem fut billentyűleütésenként.

HívásMit csinál
feel(style=None, intensity=None, sharpness=None)Haptikus visszajelzés: a style értéke "soft", "light", "medium", "heavy", "rigid" vagy "off", az intensity és a sharpness (0 és 1 között) pedig finomítja. Egy stílusszó önmagában is jó.
hitbox(scale=1, x=0, y=0)Érintési terület: az x és az y a billentyű célját a mérete ekkora hányadával tolja el, legfeljebb fél billentyűvel, a scale pedig nagyítja vagy kicsinyíti. Egy puszta szám scale-nek számít.
def haptics(state):
    return {
        "space": "heavy",
        "return": "rigid",
        "delete": feel(intensity=0.45, sharpness=0.9),
    }
Heavy Space: nehezebb szóköz, pattogós Return és könnyű törlés.

Az on_touch(key, x, y, state) minden koppintás után fut, miután a koppintás feldolgozása megtörtént, azzal, hogy hol ért le az ujj a billentyűn. A helyet a kirajzolt billentyűhöz mérjük, nem az eltolt célhoz, így egy bővítmény minden billentyűt arrafelé tolhat, ahol valójában megnyomják, anélkül hogy a saját eltolását kergetné.

def initial():
    return {"keys": {}}

def on_touch(key, x, y, state):
    if len(key) != 1:
        return state
    n, ax, ay = state["keys"].get(key, [0, 0.0, 0.0])
    n = min(n + 1, 50)
    ax += (x - ax) / n
    ay += (y - ay) / n
    state["keys"][key] = [n, ax, ay]
    return state

def hitboxes(state):
    boxes = {}
    for key in state["keys"]:
        n, x, y = state["keys"][key]
        if n >= 12:
            boxes[key] = hitbox(x=round(x * 0.6, 2), y=round(y * 0.6, 2))
    return boxes
Adaptive Hitbox: megtanulja, hol nyomják meg valójában az egyes billentyűket, és a céljukat részben oda tolja.

A suggestions(word, state) szavakat tesz a sáv elejére, amíg egy szó gépelése folyik. A correct(word, fix, state) szavanként egyszer fut, amikor a szóköz lezárja a szót, a billentyűzet saját javításával vagy None értékkel, kikapcsolt automatikus javításnál is. Adj vissza egy szót, hogy bekerüljön, False értéket, hogy a szó úgy maradjon, ahogy begépelték, vagy None értéket, hogy a billentyűzet döntsön. Az első válaszoló bővítmény nyer, és a közvetlenül utána nyomott törlés visszavonja, mint bármely automatikus javítást.

SHORT = {"brb": "be right back", "omw": "on my way", "idk": "I don't know"}

def suggestions(word, state):
    long = SHORT.get(word.lower())
    return [long] if long else []

def correct(word, fix, state):
    if len(word) > 1 and word.isupper():
        return False
    return None
Shorthand: a brb gépelése közben felajánlja a „be right back” kifejezést, és távol tartja az automatikus javítást a csupa nagybetűs szavaktól.

Egyik horogpont sem fut jelszómezőkben. A sáv javítási címkéje a billentyűzet saját javítását mutatja, nem azt, amit a correct visszaadna, és az on_touch-ban módosított tábla a következő ütemben jut el a billentyűzetig.

Tesztelés a szerkesztőben

A szerkesztő Előnézete egy helyettesítő billentyűzet. Élőben rajzolja a settings(state) függvényt, koppintásra bármely horogpontot elindít mintaszóval, billentyűvel vagy mezőtípussal, mutatja a szóközt úgy, ahogy a bővítmény hagyta, és felsorol mindent, amit a bővítmény a billentyűzettől kért. A stats() ott kitalált számokat ad vissza, így gépelés nélkül is megjelenik egy sebesség.

  1. Használd az előnézet vezérlőit. Mindegyik lefuttatja az on_action-t és újrarajzol.
  2. Koppints a horogpontgombokra abban a sorrendben, ahogy a billentyűzet tenné: on_open, aztán néhányszor on_word vagy on_key, majd on_close.
  3. Olvasd a konzolt. A parancsok úgy jelennek meg, ahogy írtad őket, alattuk a print() sorai, a hiba pedig megnevezi a sorát.
  4. Töltsd újra az állapot nullázásához. A szkript szerkesztése önmagában nem állítja vissza.

Az előnézetnek nincs dokumentuma, ezért az insert() és a replace() csak naplóz. Kipróbálásukhoz ments, és gépelj bármelyik mezőbe nyitott billentyűzettel.

Korlátok

Ha egy bővítmény fájlként vagy tárolóból érkezik, a Clink mentés előtt ellenőrzi. 64 000 bájtnál és 1600 sornál kisebbnek kell lennie, legalább egy horogpontot kell definiálnia, csak engedélyezett modulokat importálhat, és a következők egyikét sem tartalmazhatja:

Megosztott bővítményben nem megengedett

  • __
  • exec(
  • eval(
  • open(
  • compile(

Modulok, amelyeket egy megosztott bővítmény importálhat

  • json
  • math
  • random
  • re
  • sys
  • time

Minden horogponthívás 2 000 000 értelmezőlépést kap, ugyanannyit, mint egy panel kirajzolása. Az on_key viszont minden leütésnél lefut, így az ott végzett nehéz munka jóval azelőtt lelassítja a gépelést, hogy elérné ezt a korlátot.

A fájl

A bővítmény egyetlen JSON-dokumentum. Az id frissítések között is állandó, a version szabad szöveg, amely a listában látszik, az icon egy SF Symbol neve, a source pedig a szkript escape-elt sortörésekkel. Oszd meg a szerkesztő ellenőrzőjéből, vagy importálj egyet a Bővítmények lap nyílgombjával.

{
  "id": "word-count",
  "name": "Word count",
  "icon": "text.word.spacing",
  "summary": "Counts words on the space bar",
  "version": "1.0",
  "author": "You",
  "enabled": true,
  "source": "def initial():\n    return {\"on\": False}\n..."
}
Egy .clinkplugin, rövidítve.

A bővítményeket .clinkplugin fájlként lehet megosztani, ez egy JSON-dokumentum, benne a szkripttel. Tárolón keresztül lehet közzétenni őket, ugyanúgy, mint a paneleket: egy mappa fájllal, egy manifeszttel és egy kiadással. A hivatalos tároló: anti-ltd/clink-plugins.

Tárházak ›

Ha valami nem történik meg

Legtöbbször ezek egyike.

TünetMit érdemes ellenőrizni
Semmi sem történikA bővítmények ki vannak kapcsolva a Bővítmények lap tetején, a bővítmény ki van kapcsolva a listában, vagy nincs Clink Pro tagság. Mindhárom esetben a billentyűzet egyetlen bővítményt sem futtat.
A szóköz szövege ki van szürkítveEgy bővítmény átvette. A mező alatti sor megnevezi, melyik; kapcsold ki annak a bővítménynek a kapcsolóját, vagy magát a bővítményt, hogy visszakapd a mezőt.
Hiányzik a szakaszA horgony el van gépelve. Vesd össze az app Azonosítók megjelenítése funkciójával, és ne feledd, hogy a szakasz továbbra is megjelenik a bővítmény saját oldalán, ahol először érdemes nézni.
Egy elem-billentyű üresA mögötte lévő bővítmény ki van kapcsolva, el van távolítva, vagy a draw(id, state) hibát dobott. A kiosztás így is megtartja a billentyűt, tehát újra megtelik, amint a bővítmény bekapcsol. A hibát a szerkesztő konzolja mutatja.
Egy elem sosem változikA draw továbbra is lefut, tehát a mögötte lévő állapot nem mozdul. Amit az arc mutat, azt horogpontból kell frissíteni: on_tick, ha magától változik, on_word vagy on_key, ha a gépelést követi.
A set_setting() nem csinált semmitA fenti listában nem szereplő név KeyError hibát dob. A rossz fajtájú vagy tartományon kívüli érték kimarad, és a szerkesztő konzolja megmondja, mit vár a beállítás. Egy zárolt beállítás tagság nélkül vissza is ugrik.
A számláló lenullázódottA billentyűzet bezáráskor menti az állapotot, nem minden billentyűnél. Egy, a rendszer által munkamenet közben leállított billentyűzet elveszíti, amit a bővítményei a megnyitás óta számoltak. Tartsd az összegeket az app oldali horogpontokban, ha ez számít.
Lassúnak érződik a gépelésValami nehéz fut az on_key-ben. Tedd át az on_word-be, csinálj belőle kevesebbet, vagy gyorsítótárazd az eredményt az állapotban.
Egy effekt hiányzik a Bővítményekből részbőlA Bővítményeknek bekapcsolva, a bővítménynek engedélyezve kell lennie, és az effects(state) függvénynek legalább egy réteggel rendelkező light_effect-et kell visszaadnia. Koppints a szerkesztőben az effects gombra, hogy lásd, mi jött vissza, és keress ValueError-t a konzolban.
A felső sáv egyik eleme nem csinál semmitA koppintás és az elengedett tárcsa is az on_action(action, value, state) hookba érkezik, az elem id-je és nem a neve alapján párosítva. A tárcsa csak akkor ír beállítást, ha a bar_knob megnevez egyet a setting=-ben; enélkül az érték a bővítményre marad, gomb pedig sosem ír beállítást.
PyMini ›
Letöltés az App Store-ból