Xswitcher izkārtojuma korektors operētājsistēmai Linux: otrais solis

Kā iepriekŔējā publikācija (xswitcher ā€œkoncepcijas pierādÄ«jumaā€ stadijā) saņēma diezgan daudz konstruktÄ«vu atsauksmju (kas ir jauki), es turpināju pavadÄ«t savu brÄ«vo laiku, izstrādājot projektu. Tagad es vēlos pavadÄ«t nedaudz no jÅ«su... Otrais solis nebÅ«s gluži parasts: konfigurācijas dizaina priekÅ”likums/diskusija.

Xswitcher izkārtojuma korektors operētājsistēmai Linux: otrais solis

Kaut kā izrādās, ka parastiem programmētājiem ir neticami garlaicÄ«gi iestatÄ«t visas Ŕīs vadÄ«bas ierÄ«ces.

Lai nebÅ«tu nepamatoti, iekŔā ir piemērs tam, ar ko man ir darÄ«Å”ana.
Kopumā lieliski izstrādāts (un labi īstenots) Apache Kafka & ZooKeeper.
- Konfigurācija? Bet tas ir garlaicÄ«gi! Mēms xml (jo tas ir ā€œno kastesā€).
- Ak, vai jūs arī vēlaties ACL? Bet tas ir tik garlaicīgi! Tap-blooper... Kaut kas tamlīdzīgs.

Bet manā darbā tas ir tieÅ”i otrādi. Pa labi (diemžēl gandrÄ«z nekad pirmo reizi) konstruētais modelis ļauj viegli un dabiski turpināt tālāk (GandrÄ«z) salikt diagrammu.

Nesen uzgāju rakstu par Habrē par datu zinātnieku smago darbu...
Izrādās, ka viņiem Å”is brÄ«dis ir pilnÄ«bā realizēts. Un manā praksē, kā saka, ā€œvieglā versijaā€. Vairāku sējumu modeļi, pieredzējuÅ”i programmētāji ar gatavu OOP utt. ā€” tas viss parādÄ«sies vēlāk, kad/ja tas pacelsies. Taču dizainerim jāsāk kaut kur Å”eit un tagad.

Nonāc pie lietas. Es ņēmu TOML kā sintaktisko pamatu no Ŕī pilsoņa.

Tapēc ka viņŔ (TOML) no vienas puses, cilvēka rediģējams. No otras puses, tas tiek tulkots 1:1 jebkurā no biežāk sastopamajām sintaksēm: XML, JSON, YAML.
Turklāt implementācija, ko izmantoju no ā€œgithub.com/BurntSushi/tomlā€, lai gan tā nav vismodernākā (joprojām 1.4 sintakse), ir sintaktiski saderÄ«ga ar to paÅ”u (ā€œiebÅ«vētoā€) JSON.

Tas ir, ja vēlaties, varat vienkārÅ”i pateikt "ejiet cauri mežam ar savu TOML, es gribu XXX" un "pielāgot" kodu tikai ar vienu rindiņu.

Tādējādi, ja vēlaties rakstÄ«t dažus logus, lai konfigurētu xswitcher (ES neesmu pārliecināts) Nav gaidāmas nekādas problēmas ā€œar Å”o jÅ«su sasodÄ«to konfigurācijuā€.

Visiem pārējiem sintakses pamatā ir ā€œatslēga = vērtÄ«baā€ (un burtiski pāris sarežģītākas opcijas, piemēram, = [daži, tas, masÄ«vs]) man Ŕķiet
intuitīvi ērti.
Interesanti ir tas "sadedzis" aptuveni tajā paŔā laikā (ap 2013. gadu). Tikai atŔķirÄ«bā no manis TOML autors iegāja kārtÄ«gā mērogā.

Tāpēc tagad man ir vieglāk pielāgot tā ievieÅ”anu sev, nevis otrādi.

Kopumā mēs ņemam TOML (ļoti lÄ«dzÄ«gs vecajam Windows INI). Un mums ir konfigurācija, kurā mēs aprakstām, kā pievienot virkni āķu atkarÄ«bā no jaunāko skenÄ“Å”anas kodu kopas no tastatÅ«ras. Zemāk pa gabalu ir lÄ«dz Å”im notikuÅ”ais. Un paskaidrojums, kāpēc es tā izlēmu.

0. Pamata abstrakcijas

  • Skenēt kodu apzÄ«mējumus. Kaut kas noteikti ir jādara lietas labā, jo vienkārÅ”i digitālie kodi absolÅ«ti nav cilvēkiem lasāmi (tas esmu tikai es loloswitcher).
    Es izkratÄ«ju ā€œecodes.goā€ no ā€œgolang-evdevā€ (biju slinks, lai paskatÄ«tos oriÄ£inālo avotu, lai gan autors to norādÄ«ja diezgan kulturāli). Es nedaudz izlaboju (pagaidām) kaut ko, kas bija diezgan bailÄ«gs. Piemēram, ā€œLEFTBRACEā€ ā†’ ā€œL_BRACEā€.
  • Turklāt viņŔ ieviesa jēdzienu ā€œstāvokļa atslēgasā€. Tā kā lietotā parastā gramatika nepieļauj garus fragmentus. (Bet tas ļauj pārbaudÄ«t ar minimālu pieskaitāmo izdevumu. Ja izmantojat tikai ā€œtieÅ”oā€ ierakstÄ«Å”anu.)
  • BÅ«s iebÅ«vēts nospiestā ā€œdedublikatorsā€. Tādējādi tiks ierakstÄ«ts stāvoklis "atkārtot"=2 viens reizes.

1. Veidņu sadaļa

[Templates] # "@name@" to simplify expressions
 # Words can consist of these chars (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 apzÄ«mējumu? (vai nu jautājums par grafēmām jeb "hieroglifiem")? Kaut kāda briesmÄ«ga "palags". Tāpēc es nekavējoties ievieÅ”u jēdzienu ā€œveidneā€.

2. Ko darÄ«t, ja kaut kas tiek noklikŔķināts (ir saņemts cits skenÄ“Å”anas kods)

[ActionKeys]
 # Collect key and do the test for command sequence
 # !!! Repeat codes (code=2) must be collected once per key!
 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"]

 # Drop all collected keys, including this.  This is default action.
 Drop = ["ESC", "-", "TAB", "ENTER", "KPENTER", "LINEFEED..POWER"]
 # Store extra map for these keys, when any is in "down" state.
 # State is checked via "OFF:"|"ON:" conditions in action.
 # (Also, state of these keys must persist between buffer drops.)
 # ??? How to deal with CAPS and "LOCK"-keys ???
 StateKeys = ["L_CTRL", "L_SHIFT", "L_ALT", "L_META", "CAPS", "N_LOCK", "S_LOCK",
              "R_CTRL", "R_SHIFT", "R_ALT", "R_META"]

 # Test only, but don't collect.
 # E.g., I use F12 instead of BREAK on dumb laptops whith shitty keyboards (new ThinkPads)
 Test = ["F1..F10", "ZENKAKUHANKAKU", "102ND", "F11", "F12",
          "RO..KPJPCOMMA", "SYSRQ", "SCALE", "HANGEUL..YEN",
          "STOP..SCROLLDOWN", "NEW..MAX"]

Kopā ir 768 kodi. (Bet ā€œkatram gadÄ«jumamā€ xswitcher kodā ievietoju ā€œpārsteigumuā€ uztverÅ”anu).
IekÅ”pusē es aprakstÄ«ju masÄ«va aizpildÄ«Å”anu ar saitēm uz funkcijām ā€œko darÄ«tā€. Golangā tas ir (pēkŔņi) Tas izrādÄ«jās ērti un acÄ«mredzami.

  • Es plānoju Å”ajā vietā samazināt ā€œDropā€ lÄ«dz minimumam. Par labu elastÄ«gākai apstrādei (to parādÄ«Å”u zemāk).

3. Tabula ar logu klasēm

# 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 ir dubultās kvadrātiekavās ar tās nosaukumu. Tas nevarēja bÅ«t vieglāk uzreiz. AtkarÄ«bā no paÅ”laik aktÄ«vā loga varat atlasÄ«t Ŕādas opcijas:

  • JÅ«su paÅ”u ā€œkarsto taustiņuā€ komplekts ā€œDarbÄ«bas =ā€¦ā€. Ja nav/tukÅ”s, nedari neko.
  • Pārslēgt ā€œMouseClickDropsā€ ā€” ko darÄ«t, ja tiek konstatēts peles klikŔķis. Tā kā vietā, kur ir ieslēgts xswitcher, nav informācijas par to, kur viņi noklikŔķina, mēs pēc noklusējuma atiestatām buferi. Bet termināļos (piemēram) jums tas nav jādara (parasti).

4. Viena (vai vairākas) klikŔķu secības iedarbina vienu vai otru āķ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)" ]

Āķi ir sadalÄ«ti divos veidos. IebÅ«vēts, ar "runājoÅ”iem" nosaukumiem (NewWord, NewSentence, Compose) un programmējams.

Programmējamie nosaukumi sākas ar ā€œdarbÄ«baā€. Jo TOML v1.4, nosaukumiem ar punktiem jābÅ«t pēdiņās.

Katra sadaļa ir jāapraksta tālāk ar tādu paŔu nosaukumu.

Lai nepÅ«stu cilvēku prātus ar ā€œplikiemā€ pastāvÄ«gajiem apmeklētājiem (pēc pieredzes, viņu rakstÄ«tvarbÅ«t viens no desmit profesionāļiem), es nekavējoties ievieÅ”u papildu sintaksi.

  • "OFF:" (vai "ON:") pirms regexp (regulārā izteiksme) ir jāatlaiž (vai jānospiež) tālāk norādÄ«tās pogas.
    Tālāk es izveidoÅ”u ā€œnetaisnÄ«guā€ regulāro izteiksmi. Ar atseviŔķu gabalu pārbaudi starp caurulēm "|". Lai samazinātu tādu ierakstu skaitu kā "[LR]_SHIFT" (kur tas noteikti nav nepiecieÅ”ams).
  • "SEQ:" Ja iepriekŔējais nosacÄ«jums ir izpildÄ«ts (vai tā nav), mēs pārbaudām, vai tiek izmantota ā€œnormālaā€ regulāra izteiksme. Lai iegÅ«tu sÄ«kāku informāciju, es nekavējoties nosÅ«tu uz ^W ā€œregexpā€ bibliotēku. Tā kā es joprojām neesmu pacenties noskaidrot saderÄ«bas pakāpi ar savu iecienÄ«tāko pcre (ā€œperl saderÄ«gsā€).
  • Izteiciens ir rakstÄ«ts formā "BUTTON_1: CODE1, BUTTON_2: CODE2" utt., secÄ«bā, kādā tiek saņemti skenÄ“Å”anas kodi.
  • Čeks vienmēr tiek ā€œpievilktsā€ lÄ«dz secÄ«bas beigām, tāpēc astei nav jāpievieno ā€œ$ā€.
  • Visas pārbaudes vienā rindā tiek veiktas viena pēc otras un tos apvieno ar ā€œesā€. Bet, tā kā vērtÄ«ba ir aprakstÄ«ta kā masÄ«vs, aiz komata varat ierakstÄ«t alternatÄ«vu pārbaudi. Ja kāda iemesla dēļ tas ir nepiecieÅ”ams.
  • VērtÄ«ba "SeqLength = 8" ierobežo bufera lielumu, pret kuru tiek veiktas visas pārbaudes. Jo Es (lÄ«dz Å”im) savā dzÄ«vē neesmu saskāries ar bezgalÄ«giem resursiem.

5. IepriekŔējā sadaļā aprakstÄ«to āķu iestatÄ«Å”ana

# 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 ir "DarbÄ«ba = [masÄ«vs]". LÄ«dzÄ«gi kā iepriekŔējā sadaļā, ir ierobežots iebÅ«vēto darbÄ«bu kopums. Un dokstacijas iespēja principā nav ierobežota (rakstiet ā€œAction.XXXā€ un neesiet pārāk slinks, lai uzrakstÄ«tu tam citu sadaļu).
Jo Ä«paÅ”i vārda atkārtota ievadÄ«Å”ana labotajā izkārtojumā ir sadalÄ«ta divās daļās: ā€œmainÄ«t izkārtojumu, kā norādÄ«ts turā€ Šø ā€œpārrakstÄ«tā€ (ā€œRetypeWordā€).

Pārējie parametri tiek ierakstÄ«ti "vārdnÄ«cā" ("karte" golangā) konkrētai darbÄ«bai to saraksts ir atkarÄ«gs no tā, kas rakstÄ«ts sadaļā ā€œDarbÄ«baā€.

Vienā kaudzē var aprakstÄ«t vairākas dažādas darbÄ«bas (sadaļas). Vai arÄ« varat to izjaukt. Kā es parādÄ«ju iepriekÅ”.

Es nekavējoties iestatÄ«ju darbÄ«bu ā€œIzpildÄ«tā€, lai izpildÄ«tu ārējo skriptu. Ar iespēju nospiest ierakstÄ«to buferi stdin.

  • ā€œPagaidiet = 1ā€ ā€” pagaidiet, lÄ«dz tiek pabeigts darbÄ«bas process.
  • Iespējams, ā€œlÄ«dz kaudzeiā€ gribēsies ielikt vidē papildus cilvēkus. informācija, piemēram, tās loga klases nosaukums, no kuras tas tika pārtverts.
    ā€œVai vēlaties savienot savu apstrādātāju? Å eit jums jāiet."

Fu (izelpots). Å Ä·iet, ka es neko neesmu aizmirsusi.

Hmm! Jā, es neaizmirsu...
Kur ir palaiŔanas konfigurācija? Cietajā kodā? Tāds:

[ScanDevices]
 # Must exist on start. Self-respawn in case it is younger then 30s
 Test = "/dev/input/event0"
 Respawn = 30
 # Search mask
 Search = "/dev/input/event*"
 # In my thinkPads there are such a pseudo-keyboards whith tons of unnecessary events
 Bypass = "(?i)Video|Camera" # "(?i)" obviously differs from "classic" pcre's.

Kur es aizmirsu/kļūdÄ«jos? (bez Ŕī nekādā gadÄ«jumā), ļoti ceru, ka vērÄ«giem lasÄ«tājiem nebÅ«s slinkums bāzt degunu.

Good luck!

Avots: www.habr.com

Pievieno komentāru