Korretur tat-tqassim Xswitcher għal Linux: it-tieni pass

Kif pubblikazzjoni preċedenti (xswitcher fl-istadju "prova tal-kunċett") irċieva pjuttost ħafna feedback kostruttiv (li huwa sabiħ), Bqajt inqatta' l-ħin liberu tiegħi niżviluppa l-proġett. Issa rrid inqatta' ftit minn tiegħek... It-tieni pass mhux se jkun pjuttost normali: proposta/diskussjoni tad-disinn tal-konfigurazzjoni.

Korretur tat-tqassim Xswitcher għal Linux: it-tieni pass

B'xi mod jirriżulta li l-programmaturi normali jsibuha oerhört boring biex iwaqqfu dawn il-kontrolli kollha.

Biex ma jkunx infondat, ġewwa huwa eżempju ta 'dak li qed nittratta.
B'mod ġenerali maħbubin (u implimentati tajjeb) b'mod eċċellenti Apache Kafka & ZooKeeper.
- Konfigurazzjoni? Imma huwa boring! Dumb xml (għax huwa "barra mill-kaxxa").
- Oh, tridu wkoll ACL? Imma tant boring! Tap-blooper... Xi ħaġa bħal dik.

Imma fix-xogħol tiegħi huwa eżattament l-oppost. Dritt (sfortunatament, kważi qatt l-ewwel darba) il-mudell mibni jippermettilek tkompli aktar faċilment u b'mod naturali (Kważi) għaqqad dijagramma.

Dan l-aħħar iltqajt ma' artiklu dwar Habré dwar ix-xogħol iebes tax-xjenzati tad-data...
Jirriżulta li dan il-mument huwa realizzat bis-sħiħ għalihom. U fil-prattika tiegħi, kif jgħidu, "verżjoni ħafifa". Mudelli b'ħafna volumi, programmaturi imħawwar b'OOP lest, eċċ. — dan kollu jidher aktar tard meta/jekk jitlaq. Iżda d-disinjatur jeħtieġ li jibda x'imkien hawn u issa.

Wasal sal-punt. Ħadt TOML bħala bażi sintattika minn dan iċ-ċittadin.

Għax hu (TOML) minn naħa waħda, editable mill-bniedem. Min-naħa l-oħra, huwa tradott 1:1 fi kwalunkwe mis-sintassi l-aktar komuni: XML, JSON, YAML.
Barra minn hekk, l-implimentazzjoni li użajt minn "github.com/BurntSushi/toml", għalkemm mhix l-aktar moda (għadha s-sintassi 1.4), hija sintattikament kompatibbli mal-istess JSON ("inkorporat").

Jiġifieri, jekk tixtieq, tista 'sempliċement tgħid "għaddi mill-imsaġar b'dak TOML tiegħek, irrid XXX" u "impjatta" il-kodiċi b'linja waħda biss.

Għalhekk, jekk trid tikteb xi twieqi biex tikkonfigura xswitcher (M'inix ċert) Mhi mistennija l-ebda problemi "b'din il-konfigurazzjoni kkritikata tiegħek."

Għall-oħrajn kollha, is-sintassi hija bbażata fuq "ċavetta = valur" (u litteralment ftit għażliet aktar ikkumplikati, bħal = [xi, dik, firxa]) naħseb
intuwittivament konvenjenti.
X'inhu interessanti huwa li "maħruqa" madwar l-istess żmien (madwar 2013). Biss, b'differenza minni, l-awtur ta 'TOML daħal fuq skala xierqa.

Għalhekk, issa huwa aktar faċli għalija li naġġusta l-implimentazzjoni tagħha biex jaqbel lili nnifsi, u mhux viċi versa.

B'mod ġenerali, nieħdu TOML (simili ħafna għall-Windows INI l-antik). U għandna konfigurazzjoni li fiha niddeskrivu kif tehmeż serje ta 'ganċijiet skont is-sett tal-aħħar kodiċi tal-iskanjar mit-tastiera. Hawn taħt, biċċa biċċa, hemm dak li ġara s'issa. U spjegazzjoni għaliex iddeċidejt b'dan il-mod.

0. Astrazzjonijiet bażiċi

  • Skenja deżinjazzjonijiet tal-kodiċi. Żgur li trid issir xi ħaġa dwar dan, peress li sempliċement kodiċijiet diġitali assolutament ma jinqrawx mill-bniedem (dan jien biss loloswitcher).
    Ħajt "ecodes.go" minn "golang-evdev" (Kont għażżien wisq biex inħares lejn is-sors oriġinali, għalkemm l-awtur indikah pjuttost kulturalment). I kkoreġu ftit (għalissa) xi ħaġa li kienet pjuttost biża. Bħal “LEFTBRACE” → “L_BRACE”.
  • Barra minn hekk, introduċa l-kunċett ta '"ċwievet tal-istat". Peress li l-grammatika regolari użata ma tippermettix siltiet twal. (Iżda jippermettilek tiċċekkja b'overhead minimu. Jekk tuża biss reġistrazzjoni "diretta".)
  • Se jkun hemm "deduplicator" inkorporat ta 'dak li huwa ppressat. Għalhekk, l-istat "repeat"=2 se jinkiteb 1 żminijiet.

1. Taqsima Mudelli

[Templates] # "@name@" to simplify expressions
 # Words can consist of these chars (regex)
 "WORD" = "([0-9A-Z`;']|[LR]_BRACE|COMMA|DOT|SLASH|KP[0-9])"

Fiex tikkonsisti kelma tal-lingwa umana b'notazzjoni fonetika? (jew kwistjoni ta’ grafemi magħrufa bħala “ġeroglifi”)? Xi tip ta '"folja" terribbli. Għalhekk, immedjatament nintroduċi l-kunċett ta '"mudell".

2. X'għandek tagħmel meta xi ħaġa tiġi kklikkjata (wasal kodiċi ta' skanjar ieħor)

[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"]

B'kollox hemm 768 kodiċi. (Imma "biss fil-każ" I inserit qbid "sorpriżi" fil-kodiċi xswitcher).
Ġewwa ddeskriviet li timla l-firxa b'links għal funzjonijiet "x'għandek tagħmel". Fil golang dan huwa (f'daqqa waħda) Irriżulta li kien konvenjenti u ovvju.

  • Qed nippjana li nnaqqas "Drop" għal minimu f'dan il-post. Favur ipproċessar aktar flessibbli (se nurih hawn taħt).

3. Tabella bil-klassijiet tat-twieqi

# 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"

Ir-ringieli tat-tabella huma f'parentesi kwadri doppji bl-isem tagħha. Ma setax ikun aktar faċli mill-ewwel. Skont it-tieqa attiva bħalissa, tista' tagħżel l-għażliet li ġejjin:

  • Is-sett tiegħek ta' "hot keys" "Azzjonijiet = ...". Jekk le/vojta, tagħmel xejn.
  • Aqleb "MouseClickDrops" - x'għandek tagħmel meta tiġi skoperta klikk tal-maws. Peress li fil-punt fejn xswitcher jinxtegħel m'hemm l-ebda dettalji dwar "fejn jikklikkjaw", aħna reset il-buffer awtomatikament. Imma fit-terminals (per eżempju) m'għandekx għalfejn tagħmel dan (ġeneralment).

4. Sekwenza waħda (jew diversi) ta 'klikks iqanqlu ganċ wieħed jew ieħor

# 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)" ]

Il-ganċijiet huma maqsuma f'żewġ tipi. Mibni, b'ismijiet "li jitkellmu" (NewWord, NewSentence, Compose) u programmabbli.

Ismijiet programmabbli jibdew b'"Azzjoni." Għax TOML v1.4, l-ismijiet bit-tikek għandhom ikunu bil-kwotazzjonijiet.

Kull taqsima għandha tiġi deskritta hawn taħt bl-istess isem.

Sabiex ma jonfħux moħħ in-nies ma 'nies regolari "mikxufa" (mill-esperjenza, tagħhom tiktebforsi wieħed minn kull għaxra professjonisti), immedjatament nimplimenta sintassi addizzjonali.

  • "OFF:" (jew "ON:") qabel regexp (espressjoni regolari) jeħtieġu li l-buttuni li ġejjin jiġu rilaxxati (jew ippressat).
    Sussegwentement ser nagħmel espressjoni regolari "inġusta". B'kontroll separat ta' biċċiet bejn il-pajpijiet "|". Sabiex jitnaqqas in-numru ta 'rekords bħal "[LR]_SHIFT" (fejn dan huwa ċar li mhux meħtieġ).
  • "SEQ:" Jekk il-kundizzjoni preċedenti hija sodisfatta (jew assenti), allura niċċekkjaw kontra espressjoni regolari "normali". Għad-dettalji, immedjatament nibgħat lil ^W il-librerija “regexp”. Għax għadni ma ddejjaqx insib il-grad ta 'kompatibilità mal-pcre favorit tiegħi ("perl compatible").
  • L-espressjoni hija miktuba fil-forma "BUTTON_1: CODE1, BUTTON_2: CODE2" eċċ., fl-ordni li fiha jiġu riċevuti l-kodiċijiet tal-iskannjar.
  • Il-kontroll huwa dejjem "snugged" sa l-aħħar tas-sekwenza, għalhekk m'hemmx bżonn li żżid "$" mad-denb.
  • Il-kontrolli kollha f'linja waħda jsiru wieħed wara l-ieħor u huma magħquda minn "I". Iżda peress li l-valur huwa deskritt bħala firxa, tista 'tikteb verifika alternattiva wara l-virgola. Jekk dan huwa meħtieġ għal xi raġuni.
  • Valur "SeqLength = 8" jillimita d-daqs tal-buffer li miegħu jitwettqu l-kontrolli kollha. Għax Jien (s'issa) qatt ma ltqajt ma' riżorsi bla tarf f'ħajti.

5. L-issettjar tal-ganċijiet deskritti fit-taqsima preċedenti

# 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.

Il-ħaġa prinċipali hawnhekk hija "Azzjoni = [Array]". Simili għat-taqsima preċedenti, hemm sett limitat ta 'azzjonijiet mibnija. U l-possibbiltà ta 'docking mhix limitata fil-prinċipju (ikteb “Action.XXX” u tkun għażżien wisq biex tikteb taqsima oħra għaliha).
B'mod partikolari, it-tajpjar mill-ġdid ta' kelma fit-tqassim korrett huwa maqsum f'żewġ partijiet: "Ibdel it-tqassim kif speċifikat hemmhekk" и “retype” (“RetypeWord”).

Il-bqija tal-parametri jinkitbu fid-“dizzjunarju” ("mappa" fil-golang) għal azzjoni partikolari, il-lista tagħhom tiddependi fuq dak miktub f'"Azzjoni".

Diversi azzjonijiet differenti jistgħu jiġu deskritti f'borġ wieħed (taqsimiet). Jew tista 'tiġbedha barra. Kif urejt hawn fuq.

Immedjatament nistabbilixxi l-azzjoni "Exec" biex tesegwixxi l-iskrittura esterna. Bl-għażla li timbotta l-buffer irreġistrat fi stdin.

  • “Stenna = 1” — stenna biex jitlesta l-proċess li qed jaħdem.
  • Probabbilment, "għall-borġ" tkun trid tpoġġi nies addizzjonali fl-ambjent. informazzjoni bħall-isem tal-klassi tat-tieqa li minnha ġiet interċettata.
    “Trid tikkonnettja l-handler tiegħek? Dan huwa fejn trid tmur."

Phew (exhaled). Jidher li ma nsejt xejn.

Oops! Iva, ma nsejtx...
Fejn hi l-konfigurazzjoni tat-tnedija? Fil-kodiċi iebes? Hekk:

[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.

Fejn insejt/għamilt żball? (bl-ebda mod mingħajr dan), Nittama tassew li l-qarrejja attenti ma jkunux għażżien wisq biex ipoġġu mnieħrhom.

Xorti tajba!

Sors: www.habr.com

Żid kumment