Kuna (Ń switcher on "proof of concept" staadiumis) sai piisavalt palju konstruktiivset tagasisidet (mis on meeldiv), jĂ€tkasin oma vaba aja kulutamist projekti arendamiseks. NĂŒĂŒd tahan kulutada natuke teie⊠Teine samm on veidi ebatavaline: konfiguratsiooni disaini ettepanek/arutelu.

Kuna tavaliselt tundub, et normaalsetele programmeerijatele on nende kÔikide keerukate seadistuste tegemine ÀÀrmiselt igav.
Kuna ei ole mÔtet olla sÔnaselge, siin on nÀide sellest, millega ma kokku puutun.
SuurepÀraselt kujundatud (ja hÀsti teostatud) Apache Kafka & ZooKeeper.
â Konfiguratsioon? Aga see on ju igav! TĂ”mba-tĂ”mba xml (sest "karbist vĂ€lja").
â Oh, ja teie tahate ka ACL-i? Aga see on ju nii tĂŒĂŒtu! TĂ”mba-tĂ”mba⊠Nii see on.
Ja minu töös on see tĂ€iesti vastupidine. Ăigesti (kahjuks ei juhtu see peaaegu kunagi esimesel katsel) koostatud mudel vĂ”imaldab hiljem lihtsalt ja vaevata (noh, peaaegu) koos skeemi kokku panna.
Hiljuti nĂ€gin HabrĂ© artiklit andeteadlastest, kelle töö ei ole kergeâŠ
Selgub, et see aspekt on neil tĂ€ielikult realiseeritud. Ja minu praktikas, nagu öeldakse, on see "kerge versioon". Mitmeosalisemad mudelid, kogenud programmeerijad OOP-iga ja nii edasi â see kĂ”ik tuleb hiljem, kui/ja kui tĂ”usma hakkab. A konstruktor peab siin ja praegu millegagi alustama.
Asi on tĂ”sine. SĂŒntaktilise aluseks vĂ”tsin TOML .
Sest ta (TOML) on ĂŒhelt poolt inimese redigeerimiseks sobiv. Teiselt poolt â edastatakse 1:1 igasse levinumasse sĂŒntaksisse: XML, JSON, YAML.
Lisaks on minu kasutatavad rakendused âgithub.com/BurntSushi/tomlâ kuigi mitte kĂ”ige moes (ikka veel sĂŒntaks 1.4), kuid sĂŒntaktiliselt ĂŒhilduv sama (âsisseehitatudâ) JSON-iga.
See tĂ€hendab, et soovi korral vĂ”ib lihtsalt öelda "kasu meetod sellest TOMList, tahan XXX" ja "patcheerida" kogu koodi ĂŒhe reaga.
Seega, kui soovite kirjutada mingisuguseid aknaid xswitcherâile (kindlasti mitte mina) probleeme âselle teie kuradi konfiguratsioonigaâ ei oodata.
Kogu ĂŒlejÀÀnud sĂŒntaks âvĂ”ti = vÀÀrtusâ (ja mĂ”ne paari keerukama valikuga, nagu = [mĂ”ni, massiiv]) ma arvan
intuitiivselt mugav.
Mis on huvitav, mul endal umbes samal ajal (aasta paiku 2013). Ainult, erinevalt minust, tuli TOMLi autor loomulikult asjast lÀbi.
Seega on mul nĂŒĂŒd lihtsam kohandada selle rakendust enda jĂ€rgi, mitte vastupidi.
Ăldiselt vĂ”tame TOML (vĂ€ga sarnane vana Windowsi INI-le). Ja seadistame konfiguratsiooni, kus kirjeldame, kuidas siduda rida hook'e olenevalt viimaste klaviatuurikoodide kogumist. Allpool tĂŒkkhaaval â see, mis hetkel vĂ€lja tuli. Ja selgitused, miks ma nii otsustasin.
0. PÔhialused
- Klaviatuurikoodide tÀhistamine. Sellega tuleb kindlasti midagi teha, kuna lihtsalt numbrilised koodid on tÀiesti mittetÀielikult loetavad (ma pole siinkohal aiamaastikul). ).
VĂ”tsin "ecodes.go" failist "golang-evdev" (originaali jĂ€rgi ei viitsinud minna, kuigi autor on selle kenasti vĂ€lja toonud). Natuke (praegu) muutsin tĂ€iesti kohutavat. NĂ€iteks "LEFTBRACE" â "L_BRACE". - TĂ”in tĂ€iendavalt sisse mĂ”isted "klahvid seisundiga". Kuna kasutatud regulaarne grammatika ei vĂ”imalda pikki jutustusi. (Aga see vĂ”imaldab kontrollida minimaalsete kuludega. Kui kasutada ainult "otsest" salvestust.)
- Sisse tuleb ehitatud "deduplicaator" vajutatud klahvide jaoks. Nii et seisund "kordus"=2 salvestatakse. ĂŒhte Mis puutub reaalsesse tööprotsessi, siis rohkem kui poole aasta jooksul ja, tĂ€helepanu, regulaarsete kuudepikkuste vĂ€rskendustega, on operatsioonisĂŒsteemi taaskĂ€ivitamine toimunud vaid ĂŒks kord, samas kui sel perioodil Windows Server 2019 GUI oli taaskĂ€ivitamisel iga kuu.
1. Mallide jaotamine
[Templates] # "@name@" vÀljendite lihtsustamiseks
# SÔnad vÔivad koosneda jÀrgmistes mÀrkidest (regex)
"WORD" = "([0-9A-Z`;']|[LR]_BRACE|COMMA|DOT|SLASH|KP[0-9])"
Millest koosneb sĂ”na inimkeeles koos fonoloogilise kirjutamisega. (berreak kevadest aka "hieroglĂŒĂŒfid")? ĐаĐșаŃ-ŃĐŸ ŃжаŃĐœĐ°Ń Â«ĐżŃĐŸŃŃŃĐœŃ». ĐĐŸŃŃĐŸĐŒŃ ŃŃĐ°Đ·Ń Đ·Đ°ĐșлаЎŃĐČĐ°Ń ĐżĐŸĐœŃŃОД «ŃĐ°Đ±Đ»ĐŸĐœĐ°Â».
2. Mida teha, kui midagi vajutatakse (jÀrjekordne klaviatuurikood saabus)
[ActionKeys]
# Kogu klahv ja testi kÀsu jÀrjestus
# !!! Korduvad koodid (code=2) tuleb koguda ainult ĂŒhe klahvi kohta!
Add = ["1..0", "=", "BS", "Q..]", "L_CTRL..CAPS", "N_LOCK", "S_LOCK",
"KP7..KPDOT", "R_CTRL", "KPSLASH", "R_ALT", "KPEQUAL..PAUSE",
"KPCOMMA", "L_META..COMPOSE", "KPLEFTPAREN", "KPRIGHTPAREN"]
# Viska kÔik kogutud klahvid, sealhulgas see. See on vaikimisi toiming.
Drop = ["ESC", "-", "TAB", "ENTER", "KPENTER", "LINEFEED..POWER"]
# Salvestage ekstra kaart nende klahvide jaoks, kui mÔni on "all" seisundis.
# Seisundit kontrollitakse "OFF:"|"ON:" tingimuste kaudu tegevuses.
# (Samuti peavad nende klahvide seisundid pĂŒsima puhverlagede vahel.)
# ??? Kuidas tegeleda CAPS ja "LOCK"-klahvidega ???
StateKeys = ["L_CTRL", "L_SHIFT", "L_ALT", "L_META", "CAPS", "N_LOCK", "S_LOCK",
"R_CTRL", "R_SHIFT", "R_ALT", "R_META"]
# Testimiseks, kuid Àra kogu.
# NĂ€iteks kasutan F12 asemel BREAK odavatel sĂŒlearvutitel, millel on kehvad klaviatuurid (uued ThinkPadid)
Test = ["F1..F10", "ZENKAKUHANKAKU", "102ND", "F11", "F12",
"RO..KPJPCOMMA", "SYSRQ", "SCALE", "HANGEUL..YEN",
"STOP..SCROLLDOWN", "NEW..MAX"]
Kokku on ette nĂ€htud 768 koodi. (Aga "iga juhuks" lisasin koodi xswitcher'i ĂŒllatuste pĂŒĂŒdmiseks).
Sisemiselt kirjeldasin massiivi tĂ€itmist linkidega funktsioonide "mida teha". Go keeles on see (ĂŒllatuslikult) osutunud mugavaks ja ilmseks.
- Kavasin plaanin "Drop" selle koha pealt minimeerida. Paindlikuma töötlemise kasuks (nÀitan allpool).
3. Akende klasside tabel
# Some behaviour can depend on application currently doing the input.
[[WindowClasses]]
# VNC, VirtualBox, qemu etc. emulates there input independently, so never intercept.
# With the exception of some stupid VNC clients, which does high-level (layout-based) keyboard input.
Regex = "^VirtualBox"
Actions = "" # Do nothing while focus stays in VirtualBox
[[WindowClasses]]
Regex = "^konsole"
# In general, mouse clicks leads to unpredictable (at the low-level where xswitcher resides) cursor jumps.
# So, it's good choise to drop all buffers after click.
# But some windows, e.g. terminals, can stay out of this problem.
MouseClickDrops = 0
Actions = "Actions"
[[WindowClasses]] # Default behaviour: no Regex (or wildcard like ".")
MouseClickDrops = 1
Actions = "Actions"
Tabeli read â topelt-konditsioneerivate nurkade vahel koos selle nimega. Lihtsalt esimesel katsel ei Ă”nnestunud. SĂ”ltuvalt aktiivsest aknast saad valida valikud:
- Oma komplekt "kiirklahve" "Actions = âŠ". Kui pole / tĂŒhi â midagi ei toimu.
- LĂŒliti "MouseClickDrops" â mida teha, kui hiirekliki tuvastatakse. Kuna xswitcheri sisselĂŒlitamise punktis pole mingeid ĂŒksikasju "kuhu klikkida", lĂ€htestame vaikimisi vahemĂ€lu. Kuid terminalides (nĂ€iteks) ei pruugi seda teha. (ĂŒldiselt).
4. Ăks (vĂ”i mitu) vajutust kĂ€ivitavad selle vĂ”i teise hook'i
# action = [ regex1, regex2, ... ]
# "CLEAN" state: all keys are released
[Actions]
# Inverse regex is hard to understand, so extract negation to external condition.
# Expresions will be checked in direct order, one-by-one. Condition succceds when ALL results are True.
# Maximum key sequence length, extra keys will be dropped. More length - more CPU.
SeqLength = 8
# Drop word buffer and start collecting new one
NewWord = [ "OFF:(CTRL|ALT|META) SEQ:(((BACK)?SPACE|[LR]_SHIFT):[01],)*(@WORD@:1)", # "@WORD@:0" then collects the char
"SEQ:(@WORD@:2,@WORD@:0)", # Drop repeated char at all: unlikely it needs correction
"SEQ:((KP)?MINUS|(KP)?ENTER|ESC|TAB)" ] # Be more flexible: chars line "-" can start new word, but must not completelly invalidate buffer!
# Drop all buffers
NewSentence = [ "SEQ:(ENTER:0)" ]
# Single char must be deleted by single BS, so there is need in compose sequence detector.
Compose = [ "OFF:(CTRL|L_ALT|META|SHIFT) SEQ:(R_ALT:1,(R_ALT:2,)?(,@WORD@:1,@WORD@:0){2},R_ALT:0)" ]
"Action.RetypeWord" = [ "OFF:(CTRL|ALT|META|SHIFT) SEQ:(PAUSE:0)" ]
"Action.CyclicSwitch" = [ "OFF:(R_CTRL|ALT|META|SHIFT) SEQ:(L_CTRL:1,L_CTRL:0)" ] # Single short LEFT CONTROL
"Action.Respawn" = [ "OFF:(CTRL|ALT|META|SHIFT) SEQ:(S_LOCK:2,S_LOCK:0)" ] # Long-pressed SCROLL LOCK
"Action.Layout0" = [ "OFF:(CTRL|ALT|META|R_SHIFT) SEQ:(L_SHIFT:1,L_SHIFT:0)" ] # Single short LEFT SHIFT
"Action.Layout1" = [ "OFF:(CTRL|ALT|META|L_SHIFT) SEQ:(R_SHIFT:1,R_SHIFT:0)" ] # Single short RIGHT SHIFT
"Action.Hook1" = [ "OFF:(CTRL|R_ALT|META|SHIFT) SEQ:(L_ALT:1,L_ALT:0)" ]
Hoope jagasin kaheks tĂŒĂŒbiks. Sissetoodud, "rÀÀkivate" nimede (NewWord, NewSentence, Compose) ja programmeeritavad.
Programmeeritavate nimed algavad "Action.". TOML v1.4 alusel peavad punktidega nimed olema jutumÀrkides.
Allpool peab igaĂŒhe jaoks olema kirjeldatud sektsioon sama nimega.
Et mitte inimestele "paljaste" regulaarmĂ€rkide tĂ”ttu pead lĂ”hkuda (kogemus nĂ€itab, et kirjutada- vĂ”ib olla ĂŒks kĂŒmnest professionaalist), tutvustan kohe tĂ€iendavat sĂŒntaksit.
- "OFF:" (vÔi "ON:") enne regexp (regulaarmÀrk) nÔuavad, et edasi antud nupud oleksid vabastatud (vÔi vajutatud).
Edasi plaanin teha "ebaregulaarse" regulaarmĂŒĂŒgi. Eraldi kontrolliga osade vahel pipe'ide "|". EesmĂ€rgiga vĂ€hendada salvestuste arvu, nagu "[LR]_SHIFT" (seal, kus see ei ole selgelt vajalik). - "SEQ:" Kui eelmised tingimused on tĂ€idetud (vĂ”i puuduvad), kontrollime edasi "tavalise" regulaarmĂŒĂŒgi suhtes. Ăksikasjade jaoks saadan koheselt raamatukogusse "regexp." Sest ma pole endiselt viitsinud vĂ€lja selgitada ĂŒhilduvuse taset minu lemmikute pcre-dega ("perl compatible").
- VÀljend sÔnastatakse kujul "BUTTON_1: CODE1, BUTTON_2: CODE2" jne, saabumise jÀrjekorras sken-koodide jÀrgi.
- Kontroll toimub alati jÀrelduse lÔpus, seega ei pea lÔppu "$" lisama.
- KĂ”ik kontrollid ĂŒhes reas toimuvad jĂ€rjestikku ja ĂŒhendatakse "JA". Kuid kuna vÀÀrtus on mÀÀratletud massiivina, vĂ”ib pĂ€rast koma kirjutada alternatiivse kontrolli. Kui see on mingil pĂ”hjusel vajalik.
- TÀhendus "SeqLength = 8" piirab vahemÀlu suurust, mille suhtes kÔik kontrollid toimuvad. Kuna mul pole elus (kuni praeguseni) olnud piiramatu ressursi kogemust.
5. Eelmises osas kirjeldatud hookide seadistamine
# Action is the array, so actions could be chained (m.b., infinitely... Have I to check this?).
# For each action type, extra named parameters could be collected. Invalid parameters will be ignored(?).
[Action.RetypeWord] # Switch layout, drop last word and type it again
Action = [ "Action.CyclicSwitch", "RetypeWord" ] # Call Switch() between layouts tuned below, then RetypeWord()
[Action.CyclicSwitch] # Cyclic layout switching
Action = [ "Switch" ] # Internal layout switcher func
Layouts = [0, 1]
[Action.Layout0] # Direct layout selection
Action = [ "Layout" ] # Internal layout selection func
Layout = 0
[Action.Layout1] # Direct layout selection
Action = [ "Layout" ] # Internal layout selection func
Layout = 1
[Action.Respawn] # Completely respawn xswitcher. Reload config as well
Action = [ "Respawn" ]
[Action.Hook1] # Run external commands
Action = [ "Exec" ]
Exec = "/path/to/exec -a -b --key_x"
Wait = 1
SendBuffer = "Word" # External hook can process collected buffer by it's own means.
Peamine siin â âAction = [Massiiv]â. Nagu eelnevas osas, on olemas piiratud hulk sisseehitatud tegevusi. Ja pĂ”himĂ”tteliselt pole piiratud vĂ”imalus siduda (kirjuta âAction.XXXâ ja Ă€ra unusta kirjutada sellele veel ĂŒks sektsioon).
Sealhulgas, Ă”igekirjakorrektuuri sĂ”na ĂŒlekirjutamine jaguneb kaheks osaks: âvaheta klaviatuur sarnaselt seal mÀÀratletuleâ ja âĂŒlekirjutaâ (âRetypeWordâ).
ĂlejÀÀnud parameetrid salvestatakse âsĂ”nastikkuâ (âmapâ golangis) selle tegevuse jaoks, nende loetelu sĂ”ltub âActionisâ kirjutatust.
MĂ”ningaid erinevaid tegevusi saab kirjeldada ĂŒhes kastmes (sektsioonid). Ja neid saab ka laiali tassida. Nagu ma eespool nĂ€itasin.
Kohe seadistan tegevuse âExecâ â teosta vĂ€lise skripti. Valikuga, et tal oleks stdin'is kirja pandud puhver.
- âWait = 1â â oota, kuni kĂ€ivitatud protsess lĂ”petatakse.
- TĂ”enĂ€oliselt tahad âlisaksâ keskkonda visata tĂ€iendavat teavet, nagu akna klassi nimi, millest on kinni peetud.
âTahtsid oma töötlejat lisada? Siin on sul koht.â
Uf (hingasin vÀlja). NÀib, et midagi pole ununenud.
Ops! Jah, ei unustanudâŠ
Ja kus on kÀivituskonfiguratsioon? KÔvakoodis? Umbes nii:
[ScanDevices]
# Peab olemas olema kÀivitamisel. Enda taastamine, kui see on noorem kui 30s
Test = "\/dev\/input\/event0"
Respawn = 30
# Otsimismask
Search = "\/dev\/input\/event*"
# Minu ThinkPadidel on sellised pseudo-klaviatuurid, kus on tohutult ĂŒleliigseid sĂŒndmusi
Bypass = "(?i)Video|Camera" # "(?i)" erineb ilmselgelt âklassikalisestâ pcre'st.
Ja kus ma unustasin/vÀÀratustasin (ilma selleta â ei saa), loodan tĂ”eliselt, et tĂ€helepanelikud lugejad ei viitsi nina sisse torgata.
Edu!
Allikas: habr.com
