TÄ kÄ (hSwitcher paÅ”laik ir Ā«pierÄdÄ«juma koncepcijÄĀ») saÅÄma diezgan daudz konstruktÄ«vu atsauksmju (kas ir patÄ«kami), es turpinÄju tÄrÄt savu brÄ«vo laiku projekta attÄ«stÄ«bai. Tagad vÄlos tÄrÄt nedaudz no jÅ«su... Otrais solis bÅ«s nedaudz neierastÄks: piedÄvÄjums/apsprieÅ”ana dizaina konfigurÄcijai.

KÄ mūždien, izrÄdÄs, normÄliem programmÄtÄjiem ir ļoti garlaicÄ«gi regulÄt visus Å”os slÄdžus.
Lai nebÅ«tu balsojumi, iekÅ”Ä ir piemÄrs no tÄ, ar ko nodarbojos.
Lieliski vispÄr iecerÄtie (un labi realizÄtie) Apache Kafka & ZooKeeper.
ā KonfigurÄcija? Bet tas taÄu ir garlaicÄ«gi! Ätri ā Ätri xml (jo Ā«no kastesĀ»).
ā Ak, bet vai jÅ«s vÄlaties arÄ« ACL? Bet tas ir tik apgrÅ«tinoÅ”i! TÅ«lÄ«t⦠KÄ kaut kÄ tÄ.
Bet manÄ darbÄ ā tieÅ”i pretÄji. Pareizi (žÄl, ka pirmo reizi gandrÄ«z nekad nav) izveidotÄ modelis ļauj tÄlÄk viegli un neuzkrÄ«toÅ”i (nu, gandrÄ«z) izveidot shÄmu.
Nesen HabrÄ uzdÅ«ros rakstam par datu zinÄtnieku grÅ«to darbu...
IzrÄdÄs, Å”is moments viÅiem tiek Ä«stenots pilnÄ mÄrÄ. Un manÄ praksÄ, kÄ saka, Ā«gaismas versijaĀ». DaudzsÄriju modeļi, pieredzÄjuÅ”i programmÄtÄji ar OOP rokÄs utt. ā tas viss parÄdÄ«sies, kad/ja pacelsies. Bet konstruktors tam ir jÄuzsÄk tagad.
TuvÄk lietai. KÄ sintaktisko bÄzi es izvÄlÄjos TOML .
Jo tas (TOML) no vienas puses ir cilvÄkiem rediÄ£Äjams. Bet no otras puses ā tiek pÄrveidots 1:1 jebkurÄ no izplatÄ«tÄkajÄm sintaksÄm: XML, JSON, YAML.
TurklÄt, mana izmantotÄ Ä«stenoÅ”ana no Ā«github.com/BurntSushi/tomlĀ» nav ne modÄ«gÄkÄ (joprojÄm sintakse 1.4), tomÄr sintaktiski saderÄ«ga ar to paÅ”u (Ā«iebÅ«vÄtoĀ») JSON.
Tas ir, ja vÄlaties, varat vienkÄrÅ”i teikt Ā«Ei meÅ¾Ä ar Å”o tavu TOML, es vÄlos XXXĀ» un Ā«izmainÄ«tĀ» kodu vienÄ rindÄ.
TÄdÄjÄdi, ja vÄlaties uzrakstÄ«t kaut kÄdas logus hSwitcher iestatīŔanai (definitÄ«vi ne es) problÄmu Ā«ar Å”o jÅ«su nolÄdÄto konfigurÄcijuĀ» ā nenotiek.
Visiem citiem sintakse, kas balstÄs uz Ā«atslÄga = vÄrtÄ«baĀ» (un burtiski ar pÄris sarežģītÄkÄm opcijÄm, piemÄram, = [kÄdu, masÄ«vu]) uzskatu
par intuitÄ«vi Ärtu.
Kas interesanti, manam apmÄram tajÄ paÅ”Ä laikÄ (ap 2013. gadu). Tikai, atŔķirÄ«bÄ no manis, TOML autors piegÄja ar atbilstoÅ”u apjomu.
TÄpÄc tagad man ir vieglÄk pielÄgot tÄ Ä«stenoÅ”anu sev, nevis otrÄdi.
TÄtad, Åemam TOML (ļoti lÄ«dzÄ«gs vecajiem Windows INI). Un sastÄdam konfigurÄciju, kurÄ aprakstÄm, kÄ pievienot sÄriju ÄÄ·u atkarÄ«bÄ no pÄdÄjo taustiÅu kodu kopuma no tastatÅ«ras. ZemÄk pa fragmentiem ā tas, kas Å”obrÄ«d ir izveidots, un paskaidrojumi, kÄpÄc es tÄ izlÄmu.
0. Pamata abstrakcijas
- TaustiÅu kodu apzÄ«mÄjumi. Ar to noteikti jÄdara kaut kas, jo vienkÄrÅ”i ciparu kodi ir absolÅ«ti necilvÄcÄ«gi lasÄmi (to es saku metaforiski). ).
Izguvu Ā«ecodes.goĀ» no Ā«golang-evdevĀ» (uz pirmavotu negribÄju iet, lai arÄ« autorÄ tas ir norÄdÄ«ts ļoti pieklÄjÄ«gi). Nedaudz (pagaidÄm) laboju pavisam briesmÄ«gus piemÄrus. PiemÄram, Ā«LEFTBRACEĀ» ā Ā«L_BRACEĀ». - TurklÄt ieviesu jÄdzienu Ā«taustiÅi ar stÄvokliĀ». Å emot vÄrÄ, ka izmantojamÄ regulÄrÄ gramatika neparedz garus teikumus. (TÄ Ä¼auj pÄrbaudÄ«t ar minimÄlÄm izmaksÄm. Ja izmantot tikai Ā«tieÅ”oĀ» ierakstu.)
- Tiks iebÅ«vÄts Ā«de-deduplicationĀ» uzspiestajam. TÄdÄjÄdi stÄvoklis Ā«atkÄrtotsĀ»=2 tiks ierakstÄ«ts. vienu reizÄm.
1. Šablonu sadalījums
[Templates] # "@name@" lai vienkÄrÅ”otu izteiksmes
# VÄrdi var sastÄvÄt no Ŕīm rakstzÄ«mÄm (regex)
"WORD" = "([0-9A-Z`;']|[LR]_BRACE|COMMA|DOT|SLASH|KP[0-9])"
No kÄ sastÄv cilvÄku valodas vÄrds ar fonÄtisko ierakstu. (nav runas par grafÄmÄm jeb Ā«hieroglifiemĀ»)? ŠŠ°ŠŗŠ°Ń-ŃŠ¾ ŃŠ¶Š°ŃŠ½Š°Ń Ā«ŠæŃŠ¾ŃŃŃŠ½ŃĀ». ŠŠ¾ŃŃŠ¾Š¼Ń ŃŃŠ°Š·Ń Š·Š°ŠŗŠ»Š°Š“ŃŠ²Š°Ń понŃŃŠøŠµ Ā«ŃŠ°Š±Š»Š¾Š½Š°Ā».
2. Ko darÄ«t, kad kaut kas tiek nospiests (ierodas jauns taustiÅa kods)
[ActionKeys]
# SavÄc taustiÅu un veic testu komandu secÄ«bai
# !!! AtkÄrtoto kodu (code=2) jÄievÄc tikai reizi katram taustiÅam!
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"]
# Izmet visus savÄkto taustiÅu, ieskaitot Å”o. Tas ir noklusÄjuma darbÄ«ba.
Drop = ["ESC", "-", "TAB", "ENTER", "KPENTER", "LINEFEED..POWER"]
# SaglabÄ papildus karti Å”iem taustiÅiem, kad kÄds ir Ā«nospiestsĀ» stÄvoklÄ«.
# StÄvoklis tiek pÄrbaudÄ«ts caur Ā«OFF:"|"ON:" nosacÄ«jumiem darbÄ«bÄ.
# (ArÄ«, Å”o taustiÅu stÄvoklim jÄnotur starp buferu izmetieniem.)
# ??? KÄ rÄ«koties ar CAPS un Ā«LOCKĀ»-taustiÅiem ???
StateKeys = ["L_CTRL", "L_SHIFT", "L_ALT", "L_META", "CAPS", "N_LOCK", "S_LOCK",
"R_CTRL", "R_SHIFT", "R_ALT", "R_META"]
# TestÄ tikai, bet neievÄc.
# PiemÄram, es izmantoju F12, nevis BREAK uz prastiem klÄpjdatoriem ar sliktÄm tastatÅ«rÄm (jauni ThinkPad modeļi)
Test = ["F1..F10", "ZENKAKUHANKAKU", "102ND", "F11", "F12",
"RO..KPJPCOMMA", "SYSRQ", "SCALE", "HANGEUL..YEN",
"STOP..SCROLLDOWN", "NEW..MAX"]
KopÄ ir paredzÄti 768 kodi. (Bet Ā«tikai gadÄ«jumÄĀ» es ievietoju kodÄ hswitcher noÄ·erÅ”anu Ā«pÄrsteigumiemĀ»).
IekÅ”Ä es detalizÄju masÄ«va aizpildÄ«jumu ar atsaucÄm uz funkcijÄm Ā«ko darÄ«tĀ». Uz golang tas izrÄdÄ«jÄs (pavisam negaidÄ«ti) izrÄdÄ«jÄs Ärti un acÄ«mredzami.
- Ā«DropĀ» Å”ajÄ vietÄ plÄnoju samazinÄt lÄ«dz minimumam. LabÄkai elastÄ«gai apstrÄdei (skatīŔu zemÄk).
3. Logu klaŔu tabula
# 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"
Tabulas rindas ā divos kvadrÄtiekavÄs ar tÄs nosaukumu. VienkÄrÅ”i uzreiz nesanÄca. AtkarÄ«bÄ no paÅ”reizÄjÄ aktÄ«vÄ loga var izvÄlÄties opcijas:
- Savs Ā«karsto taustiÅuĀ» komplekts Ā«Actions = ā¦Ā». Ja nav / tukÅ”s ā nekas nedarÄ«t.
- PÄrslÄdzÄjs Ā«MouseClickDropsĀ» ā ko darÄ«t, atklÄjot peles klikŔķi. TÄ kÄ izvÄrÅ”anas punktÄ xswitcher nav sÄ«kÄkas informÄcijas Ā«kur tur jÄklikŔķinaĀ», pÄc noklusÄjuma atiestata buferi. TaÄu terminÄlos (piemÄram) var to nemaz nedarÄ«t. (parasti).
4. Viens (vai vairÄki) pogu spiedienu secÄ«bas aktivizÄ konkrÄtu lÄpstiÅu
# 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)" ]
LÄpstiÅas sadalÄ«tas divos veidos. IebÅ«vÄtas, ar Ā«runÄjoÅ”iemĀ» nosaukumiem (NewWord, NewSentence, Compose) un programmÄjamas.
ProgrammÄjamo nosaukumi sÄkas ar Ā«Action.Ā». T.k. TOML v1.4, nosaukumiem ar punktiem jÄbÅ«t pÄdiÅÄs.
ZemÄk katram jÄbÅ«t aprakstÄ«tas sadaļai ar tÄdu paÅ”u nosaukumu.
Lai nesabojÄtu cilvÄku prÄtus ar Ā«tukÅ”iemĀ» regulÄriem izteiksmÄm (no pieredzes, tÄs uzrakstÄ«t- var tikai viens no desmit profesionÄļiem), uzreiz ievieÅ”u papildu sintaksi.
- Ā«OFF:Ā» (vai Ā«ON:Ā») pirms regexp (regulÄrÄ izteiksme) prasa, lai nÄkamÄs pogas bÅ«tu atbrÄ«votas (vai nospiestas).
TÄlÄk plÄnoju izveidot Ā«negodÄ«guĀ» regulÄro izteiksmi. Ar atseviŔķu pÄrbaudi gabaliem starp caurulÄm "|". Ar mÄrÄ·i samazinÄt ierakstu skaitu, piemÄram, "[LR]_SHIFT" (kur tas skaidri nav nepiecieÅ”ams). - Ā«SEQ:Ā» Ja iepriekÅ”Äjais nosacÄ«jums ir izpildÄ«ts (vai trÅ«kst), tÄlÄk pÄrbaudÄm attiecÄ«bÄ uz Ā«parastoĀ» regulÄro izteiksmi. Par sÄ«kÄku informÄciju uzreiz sÅ«tu uz^WbibliotÄku Ā«regexpĀ». Jo pats joprojÄm neesmu rÅ«pÄjies noskaidrot saderÄ«bu ar manÄm iecienÄ«tÄkajÄm pcre (Ā«perl compatibleĀ»).
- Izteiksmi uzraksta veidÄ Ā«POGA_1: KODS1, POGA_2: KODS2Ā» utt., ierakstu secÄ«bÄ skenÄÅ”anas kodus.
- PÄrbaude vienmÄr Ā«spiežasĀ» uz secÄ«bas beigÄm, tÄpÄc "$" beigÄs nav jÄliek.
- Visas pÄrbaudes vienÄ rindÄ tiek veiktas secÄ«gi un apvienotas ar Ā«UNĀ». Bet tÄ kÄ vÄrtÄ«ba aprakstÄ«ta masÄ«vÄ, pÄc komata var uzrakstÄ«t alternatÄ«vu pÄrbaudi. Ja tas ir kaut kam nepiecieÅ”ams.
- VÄrtÄ«ba Ā«SeqLength = 8Ā» ierobežo buferu lielumu, attiecÄ«bÄ uz kuru tiek veiktas visas pÄrbaudes. TÄ kÄ manÄ dzÄ«vÄ (lÄ«dz Å”im) nav bijusi iespÄja sastapt neierobežotas resursus.
5. Sakaru definÄÅ”ana, kas aprakstÄ«ta iepriekÅ”ÄjÄ sadaļÄ
# 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.
Galvenais Å”eit ā āAction = [MasÄ«vs]ā. LÄ«dzÄ«gi kÄ iepriekÅ”ÄjÄ sadaļÄ, ir ierobežots iekÅ”Äjo rÄ«cÄ«bu kopums. Un principÄ nav ierobežojumu pieteikÅ”anai (uzrakstÄ«t āAction.XXXā un neakcentÄt aprakstÄ«t vÄl vienu sadaļu zem tÄ).
Tostarp, vÄrdu pÄrrakstīŔana labotajÄ izkÄrtojumÄ tiek sadalÄ«ta divÄs daļÄs: āmainÄ«t izkÄrtojumu kÄ tur norÄdÄ«tsā un āpÄrrakstÄ«tā (āRetypeWordā).
PÄrÄjie parametri tiek ierakstÄ«ti āvÄrdnÄ«cÄā (āmapā golangÄ) attiecÄ«gajam rÄ«cÄ«bai, to saraksts ir atkarÄ«gs no rakstÄ«tÄ āActionā.
DažÄdas rÄ«cÄ«bas var aprakstÄ«t vienÄ grupÄ (sadaļÄs). Un tÄs var arÄ« izkliedÄt. KÄ es iepriekÅ” parÄdÄ«ju.
Uzreiz nosaku darbÄ«bu āExecā ā izpildÄ«t ÄrÄju skriptu. Ar iespÄju ievietot tam stdin ierakstÄ«to buferi.
- āWait = 1ā ā gaidÄ«t pabeigtÄ procesa pabeigÅ”anu.
- IespÄjams, āpapildusā vÄlos piedÄvÄt apkÄrtÄjo informÄciju, piemÄram, loga klases nosaukumu, no kura tika nozagts.
āVai vÄlaties pievienot savu apstrÄdÄtÄju? Jums Å”eit ir.ā
Uf (izelpoju). IzskatÄs, ka neko neesmu aizmirsis.
Op! Aha, neesmu aizmirsis...
Un kur ir palaiÅ”anas konfigurÄcija? CietajÄ kodÄ? Aptuveni tÄ:
[ScanDevices]
# JÄbÅ«t pastÄvÄ«gi. PaÅ”atjaunoties, ja tas ir jaunÄks par 30s.
Test = "\/dev\/input\/event0"
Respawn = 30
# MeklÄÅ”anas maska
Search = "\/dev\/input\/event*"
# Manos thinkPads ir Å”Ädi pseido-taustiÅi ar tonnÄm nevajadzÄ«gu notikumu
Bypass = "(?i)Video|Camera" # "(?i)" acÄ«mredzami atŔķiras no āklasiskÄ" pcre.
Un kur es aizmirsu / kļūdÄ«jos (bez tÄ ā nekÄ), ļoti ceru, ka apzinÄ«gajiem lasÄ«tÄjiem nepatiks iespÄja uzlikt degunu.
Veiksmi!
Avots: habr.com
