Xswitcher dhizaini yekugadziridza yeLinux: nhanho yechipiri

kubva bhuku rakamboburitswa (xswitcher padanho rekuratidza pfungwa) akagamuchira mhinduro dzakawanda dzinovaka (izvo zvakanaka), ndakaramba ndichipedza nguva yangu yekuzorora ndichigadzira chirongwa ichi. Zvino ndoda kushandisa mari yako shoma... Danho rechipiri richava risingawanzoitiki: kupa/kukurukura nezvekugadzirwa kwegadziriro.

Xswitcher dhizaini yekugadziridza yeLinux: nhanho yechipiri

Neimwe nzira zvinozoitika kuti vanogadzira mapurogiramu vanowanzoona zvichinetsa zvikuru kugadzirisa maknob ese aya.

Kuti ndisave nepfungwa dzisina hwaro, heino muenzaniso wezvandiri kubata nazvo.
Apache Kafka & ZooKeeper kazhinji vakagadzirwa zvakanaka (uye vakanyatso shandiswa).
— Kugadziriswa? Asi izvozvo zvinofinha! Kungori slapdash XML (nekuti "haisi yemubhokisi").
— Oh, uye unodawo ACL here? Asi izvozvo zvinonetsa! Rova-rova... Chimwe chinhu chakadaro.

Uye mubasa rangu zvakapesana chaizvo. Ndizvozvo. (zvinotyisa, hazvimboitiki kekutanga) modhi yakagadzirwa inobvumira kuti zvive nyore uye zvakasununguka (zvakanaka, anenge) unganidza dunhu.

Nguva pfupi yadarika ndakasangana nechinyorwa pamusoro peHabr nezvebasa rakaoma remasayendisiti edata…
Zvinozoonekwa kuti vari kushandisa zvizere chikamu ichi. Sekutaura kwavo, i "shanduro yakareruka." Mamodheru ane mavhoriyamu akawanda, vagadziri vemapurogiramu vane ruzivo rwakakwana vane OOP vakagadzirira, nezvimwewo—zvese izvozvo zvichauya gare gare, kana zvatanga/kana zvatanga. Asi mugadziri anofanira kutanga pane imwe nzvimbo pano neapo.

Ngatitaurei nezvenyaya yacho. Ndakashandisa TOML senzira yekunyora manyorerwo emazwi. kubva kumugari uyu.

Nekuti ndiye (TOML) Kune rumwe rutivi, inogona kugadziriswa nevanhu. Kune rumwe rutivi, inoshandura 1:1 kuita chero imwe yema syntaxes akajairika: XML, JSON, YAML.
Uyezve, kushandiswa kwandakashandisa kubva ku "github.com/BurntSushi/toml", kunyangwe kusiri kwefashoni zvakanyanya (kuchiri kushandisa syntax ye1.4), kunoenderana ne syntactically neJSON imwechete ("yakavakirwa mukati").

Kureva kuti, kana uchida, unogona kungoti "enda kugehena neTOML yako, ndinoda XXX" uye "gadzira" kodhi yacho nemutsetse mumwe chete.

Saka, kana uchida kunyora mamwe mawindow ekugadzirisa xswitcher (handisi ini zvechokwadi) Hapana matambudziko anotarisirwa ne "iyi gadziriro yako yakaipa".

Kune vamwe vese, matauriro acho akavakirwa pa "key = value". (uye chaizvo dzimwe sarudzo dzakaoma, senge = [dzimwe, array]) Ndinofunga
zviri nyore kunzwisisa.
Chinonakidza ndechekuti iye pachake "yakapiswa" Munguva imwe chete iyoyo (munenge muna 2013). Kusiyana neni, munyori weTOML akaita basa iri nepfungwa dzakakodzera.

Ndosaka zvava nyore kwandiri kugadzirisa mashandiro ayo kuti aenderane neni, pane kuti aenderane nepfungwa dzangu.

Chaizvoizvo, tinoshandisa TOML (yakafanana zvikuru neWindows INI yekare). Uye tinogadzira configuration yatinotsanangura maitirwo ekubatanidza nhevedzano dzemahooks zvichibva pamakodhi escan achangoburwa akapinda kubva kukhibhodi. Pazasi, muzvidimbu, ndizvo zvatinazvo kusvika pari zvino. Uye tsananguro yekuti sei ndakasarudza seizvi.

0. Basic abstractions

  • Skena makodhi akanyorwa. Pane chinofanira kuitwa nezvazvo, sezvo makodhi edhijitari chete asingaverengeki zvachose (ndiri kungotaura zvinosetsa). loloswitcher).
    Ndakatora "ecodes.go" kubva ku "golang-evdev" (ndaive nehusimbe hwekutsvaga kodhi yepakutanga, kunyangwe munyori akaitaura zvine hunhu). Ndakagadzirisawo zvishoma (pari zvino) chimwe chinhu chaive chisina kunaka zvachose. Sekuti "LEFTBRACE" → "L_BRACE".
  • Ndakatangawo pfungwa ye "stateful keys," sezvo girama rinoshandiswa nguva dzose risingakodzeri ndima refu. (Asi zvinokutendera kuti utarise nekukanganisa kushoma, kana ukashandisa kurekodha "kwakananga" chete.)
  • Pachava ne "deduplicator" yakavakirwa mukati mekiyi yakadzvanywa. Saka, mamiriro ekuti "dzokorora"=2 achanyorwa. один nguva.

1. Chikamu chematemplate

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

Izwi remutauro wevanhu rinosanganisirei ne fonetiki? (graphemes, inozivikanwawo se "hieroglyphs," inyaya yakasiyana)"Pepa" rakaipa sei. Saka ndinobva ndatanga pfungwa ye "template" pakarepo.

2. Zvekuita kana chimwe chinhu chadzvanywa (imwe kodhi yekuskena yagamuchirwa)

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

Kune makodhi mazana manomwe nemakumi matanhatu nemasere. (Asi "kana zvichibvira" ndakaisa "surprise catcher" mu xswitcher code.)
Mukati, ndakatsanangura maitirwo ekuzadza array nemazita emabasa ekuti "zvekuita". MuGo, izvi ndizvo (kamwe kamwe) Zvakazove nyore uye zviri pachena.

  • Ndiri kuronga kuderedza "kudonha" kwechinhu ichi kusvika padiki kuitira kuti kugadziriswa kwacho kuve nyore (ndichakuratidza pazasi).

3. Plate yekirasi yehwindo

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

Mitsetse yetafura iri mumabhuraketi ane sikweya mbiri ane zita rayo. Hazvigone kuve nyore ipapo ipapo. Zvichienderana nehwindo riri kushanda parizvino, unogona kusarudza sarudzo:

  • Seti ye "hotkey" yakagadzirirwa "Actions = ...". Kana pasina/isina chinhu, usaite chero chinhu.
  • Chinongedzo che "MouseClickDrops"—zvekuita kana mbeva yaonekwa. Sezvo nzvimbo yekugonesa xswitcher isingatsanangure nzvimbo dzekudzvanya dzakatarwa, maitiro ekutanga ndeekubvisa buffer. Zvisinei, mumaterminals (semuenzaniso), izvi hazvidiwi. (semutemo).

4. Kudzvanya kumwe chete (kana kupfuura) kunoburitsa chikochekedzo chakati

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

Ndakakamura mahooks kuita mhando mbiri: mahooks akavakirwa mukati ane mazita anotsanangura ega (NewWord, NewSentence, Compose) uye mahooks anogona kurongwa.

Mazita anorongwa anotanga ne "Chiito." Sezvo TOML v1.4, mazita ane ma "period" anofanira kunge ari mu "quotation marks".

Pazasi pechikamu chimwe nechimwe panofanira kunge paine tsananguro nezita rimwe chete.

Kuti vanhu vasafunge nezvevanhu vanogara "vasina kupfeka" (kubva pane zvakaitika kwavari, ivo nyora- pamwe mumwe chete pagumi nyanzvi), ndinobva ndatanga kushandisa mamwe ma syntax ipapo ipapo.

  • "Dzima:" (kana "Dzima:") regexp (regular expression) isati yasvika, mabhatani anotevera anofanira kusunungurwa (kana kudzvanywa).
    Tevere, ndichagadzira chirevo che "kusatendeseka" chenguva dzose. Nekutarisa kwakasiyana kwezvikamu zviri pakati pemapombi e "|". Izvi zvichaderedza huwandu hwe "[LR]_SHIFT" (kwazviri pachena kuti hazvidiwi).
  • "SEQ:" Kana mamiriro ekare akazadzikiswa (kana kuti asipo), tinozoongorora zvakare kuti "regular" regular expression haishande. Kuti uwane rumwe ruzivo, ndichakutumira zvakananga ku "regexp" library. Nekuti handisati ndambozvinetsa kuti ndione kuti pcre yangu yandinoda inoenderana sei (“perl compatible”).
  • Mashoko acho akanyorwa se "BHUTON_1: CODE1, BUTON_2: CODE2" nezvimwewo, zvichienderana nehurongwa hwekugamuchira makodhi ekuskena.
  • Cheki yacho inogara "yakadzvanywa" kusvika kumagumo ekutevera, saka hapana chikonzero chekuwedzera "$" kumuswe.
  • Kuongororwa kwese mumutsara mumwe kunoitwa mumwe mushure memumwe uye zvinosanganiswa uchishandisa "AND." Asi sezvo kukosha kwacho kuchitsanangurwa se array, imwe cheki inogona kunyorwa mushure me comma. Kana zvichidikanwa nekuda kwechimwe chikonzero.
  • ukoshi "Kureba kweSeq = 8" inoganhurira saizi yebuffer iyo macheki ese anoitirwa. Nekuti muhupenyu hwangu (kusvika pari zvino) handisati ndambosangana nezvinhu zvisingaperi.

5. Kuisa zvikorekedzo zvakatsanangurwa muchikamu chapfuura

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

Chinhu chikuru pano ndechekuti - "Chiito = [Array]"Kufanana nechikamu chapfuura, kune zviito zvishoma zvakavakirwa mukati. Uye mukana wekuisa padhoki hauna muganho. (nyora "Action.XXX" uye usave neusimbe wonyora chimwe chikamu chayo).
Zvikuru sei, kunyorazve izwi muchimiro chakarongeka kwakakamurwa kuita zvikamu zviviri: "Chinja marongerwo ekhibhodi sezvakatsanangurwa uko." и "nyorazve" ("TaipazveShoko").

Zvimwe zvikamu zvakanyorwa mu "duramazwi" (mepu iri mugolang) Pachiito chakapihwa, runyorwa rwavo runoenderana nezvakanyorwa mu "Chiito".

Zviito zvakasiyana-siyana zvinogona kutsanangurwa mudutu rimwe chete (zvikamu)Kana kuti unogona kuibvisa. Sezvandaratidza pamusoro apa.

Ndakabva ndangoisa chiito che "Exec" kuti ndiite script yekunze. Nesarudzo yekusundira buffer yakanyorwa mu stdin yayo.

  • "Mirira = 1" - mirira kuti maitiro ekushanda apedziswe.
  • Ungangodawo kuwedzera rumwe ruzivo kune nharaunda, senge zita rekirasi rehwindo rayakabviswa.
    "Unoda kubatanidza processor yako here? Apa ndipo pauchaiwana."

Phew (aburitsa mweya). Zvinoita sekunge handina kukanganwa chero chinhu.

Maiwe! Aha, handina kukanganwa...
Ko gadziriro yekuvhurwa iri kupi? Mu hardcode? Chinhu chakadai:

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

Wakakanganwa/wakakanganisa kupi? (hapana imwe nzira)Ndinovimba kuti vaverengi vanoteerera havazove neusimbe hwekutaura izvi.

Good luck!

Source: www.habr.com