Serastkerê layout Xswitcher ji bo Linux: gav du

ji ber ku weşana berê (xswitcher di qonaxa "delîlên têgehê" de) gelek bertekên çêker wergirtin (ku xweş e), Min wextê xwe yê vala ji bo pêşxistina projeyê derbas kir. Niha ez dixwazim hinekî ji we xerc bikim... Pêngava duyemîn dê ne pir asayî be: pêşniyar / nîqaşa sêwirana veavakirinê.

Serastkerê layout Xswitcher ji bo Linux: gav du

Bi rengekî derdikeve holê ku bernamenûsên normal sazkirina van hemî kontrolan pir bêhêz dibînin.

Ji bo ku bêbingeh nebe, di hundurê de mînakek ku ez pê re mijûl dibim.
Bi tevahî Apache Kafka & ZooKeeper bi xweşikî hatî fikirîn (û baş hatî bicîh kirin).
- Veavakirin? Lê bêzar e! Xml lal (ji ber ku ew "ji qutîkê" ye).
- Oh, tu jî ACL dixwazî? Lê ew pir bêzar e! Tap-blooper... Tiştekî wisa.

Lê di karê min de tam berevajî ye. Rast (hey, hema qet cara yekem) modela çêkirî dihêle hûn bi hêsanî û xwezayî bêtir berdewam bikin (Hema hema) diagramekê bicivîne.

Ez vê dawiyê li gotarek li ser Habré li ser xebata dijwar a zanyarên daneyê rast hatim…
Derket holê ku ev gav ji bo wan bi tevahî tê fêhm kirin. Û di pratîka min de, wekî ku ew dibêjin, "guhertoya sivik". Modelên pir-cild, bernamenûsên demsalî yên bi OOP amade ne, hwd. - ev hemî dê paşê xuya bibe dema ku / heke ew hilkişe. Lê sêwiraner pêdivî ye ku ji cîhek vir û niha dest pê bike.

Biçe ser xalê. Min TOML wekî bingehek hevoksaziyê girt ji vî welatî.

Ji ber ku ew (TOML) ji aliyekî ve, mirov-guherbar. Ji hêla din ve, ew 1: 1 li yek ji hevoksaziyên gelemperî têne wergerandin: XML, JSON, YAML.
Digel vê yekê, pêkanîna ku min ji "github.com/BurntSushi/toml" bikar anî, her çend ne ya herî moda (hîn jî hevoksaziya 1.4) be jî, ji hêla hevoksaziyê ve bi heman ("avakirî") JSON re hevaheng e.

Ango, heke hûn bixwazin, hûn dikarin bi hêsanî bibêjin "bi wê TOML-a xwe re biçe nav daristanê, ez XXX dixwazim" û bi tenê yek rêzek kodê "patch" bike.

Bi vî rengî, heke hûn dixwazin hin pencereyan binivîsin da ku xswitcher mîheng bikin (Ez ne bawer im) "Bi vê konfigurasyona weya lanetkirî" pirsgirêk nayên hêvî kirin.

Ji bo hemî yên din, hevoksaz li ser bingeha "key = nirx" e. (û bi rastî çend vebijarkên tevlihevtir, mîna = [hin, ew, rêz]) Ez texmîn dikim
intuitive rehet.
Ya balkêş ew e "şewitî" di heman demê de (dora 2013). Tenê, berevajî min, nivîskarê TOML li ser pîvanek rast çû.

Ji ber vê yekê, naha ji min re hêsantir e ku ez pêkanîna wê li gorî xwe rast bikim, û ne berevajî.

Bi gelemperî, em TOML digirin (pir dişibin Windows INI-ya kevn). Û me veavakirinek heye ku tê de em rave dikin ka meriv çawa rêzek çengelan li gorî komek kodên paşîn ên herî paşîn ji klavyeyê ve girêdide. Li jêr, perçe perçe, heya niha çi bûye. Û ravekirinek çima min bi vî rengî biryar da.

0. Abstractions bingehîn

  • Navnîşanên kodê bişopînin. Tiştek bê guman hewce dike ku li ser vê yekê were kirin, ji ber ku kodên dîjîtal bi tevahî ji mirovan nayên xwendin (ew tenê ez im loloswitcher).
    Min "ecodes.go" ji "golang-evdev" hejand (ez pir tembel bûm ku li çavkaniya orîjînal binihêrim, her çend nivîskar ew bi rengek çandî destnîşan kir). Min hinekî (ji bo nuha) tiştek ku pir tirsnak bû rast kir. Wek "LEFTBRACE" → "L_BRACE".
  • Wekî din, wî têgeha "mifteyên dewletê" destnîşan kir. Ji ber ku rêzimanê birêkûpêk ku tê bikar anîn rê nade beşên dirêj. (Lê ew destûrê dide te ku hûn bi serdanek hindiktirîn kontrol bikin. Ger hûn tenê tomarkirina "rasterast" bikar bînin.)
  • Tiştê ku tê çap kirin dê "deduplicator"ek çêkirî hebe. Bi vî awayî, rewşa "repeat"=2 dê were nivîsandin один dem.

1. beşa Şablonên

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

Peyva zimanê mirovî ya bi nîşaneya dengnasî ji çi pêk tê? (an meseleya grafemayan an jî "hieroglyphs")? Cûreyek "pelek"ek tirsnak. Ji ber vê yekê, ez yekser têgeha "şablon" destnîşan dikim.

2. Dema ku tiştek tê klîk kirin (kodek din a şopandinê hat) çi bikin

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

Bi tevahî 768 kod hene. (Lê "tenê di rewşê de" min girtina "surprîz" xist nav koda xswitcher).
Di hundurê de min dagirtina rêzê bi girêdanên fonksiyonên "çi bikim" diyar kir. Li golan ev e (nişkê) Derket holê ku ew hêsan û eşkere ye.

  • Ez plan dikim ku li vê derê "Drop" kêm bikim. Di berjewendiya pêvajoyek maqûltir de (ez ê li jêr destnîşan bikim).

3. Tabloya bi çînên pencereyê

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

Rêzên tabloyê bi navê wê di dubendî de ne. Ew nikaribû hêsantir bûya rast ji bat. Li ser pencereya niha ya çalak ve girêdayî, hûn dikarin vebijarkên jêrîn hilbijêrin:

  • Koma weya "bişkojkên germ" "Çalak = ...". Heke ne / vala, tiştek nekin.
  • "MouseClickDrops" biguhezînin - gava ku klîkek mişkî were dîtin çi bikin. Ji ber ku li cîhê ku xswitcher tê vekêşandin de hûrgulî li ser "ku ew lê bikirtînin" tune ne, em tamponê ji hêla xwerû vesaz dikin. Lê di termînalan de (mînakek) hûn ne hewce ne ku vê yekê bikin (fêrane).

4. Yek (an çend) rêzikên klîk yek an çîçekek din vedike

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

Hooks li du celeb têne dabeş kirin. Avakirî, bi navên "axaftin" (NewWord, NewSentence, Compose) û bernamekirî.

Navên bernamekirî bi "Action" dest pê dikin. Bo TOML v1.4, navên bi deqan divê di kêşan de bin.

Divê her beş li jêr were diyar kirin bi heman navî.

Ji bo ku hişê mirovan bi rêgezên "tazî" (ji ezmûnê, wan nivîsandindibe ku yek ji deh profesyonel), Ez tavilê hevoksaziya zêde bicîh dikim.

  • "OFF:" (an "ON:") berî regexp (ragihana birêkûpêk) hewce dike ku bişkokên jêrîn werin berdan (an pêl kirin).
    Dû re ez ê îfadeyek birêkûpêk "neheq" bikim. Bi kontrolkirina cuda ya perçeyan di navbera boriyên "|". Ji bo kêmkirina hejmara tomarên mîna "[LR]_SHIFT" (ku ev eşkere ne hewce ye).
  • "SEQ:" Ger şerta berê pêk were (an tune be), wê hingê em li hember îfadeyek birêkûpêk "normal" kontrol dikin. Ji bo hûragahiyan, ez tavilê ji ^W re pirtûkxaneya "regexp" dişînim. Ji ber ku min hîna jî aciz nekiriye ku ez asta lihevhatina bi pcreya xweya bijare ("perl lihevhatî") bibînim.
  • Îfade di formê de hatiye nivîsandin "BUTTON_1: CODE1, BUTTON_2: CODE2" hwd., bi rêza ku kodên şopandinê têne wergirtin.
  • Çêk her tim li dawiya rêzê "teqandin" e, ji ber vê yekê ne hewce ye ku "$" li dûvê zêde bikin.
  • Hemî kontrolên di yek rêzê de li pey hev têne kirin û bi "ez"ê têne hev kirin. Lê ji ber ku nirx wekî rêzek tê binav kirin, hûn dikarin li dû komê kontrolek alternatîf binivîsin. Ger ji ber hin sedeman ev pêdivî ye.
  • nirxê "Nîrêjahî = 8" mezinahiya tamponê ya ku hemî kontrol li dijî wê têne kirin sînor dike. Bo Min (heta nuha) di jiyana xwe de tu carî rastî çavkaniyên bêdawî nehat.

5. Sazkirina çengelên ku di beşa berê de hatine diyarkirin

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

Ya sereke li vir e "Action = [Array]". Mîna beşa berê, komek tixûbdar a çalakiyên çêkirî hene. Û îmkana docking di prensîbê de ne sînorkirî ye ("Action.XXX" binivîsin û pir tembel nebin ku hûn ji bo wê beşek din binivîsin).
Bi taybetî, ji nû ve nivîsandina peyvekê di sêwirana rastkirî de li du beşan tê dabeş kirin: "Rêveberê wekî ku li wir hatî destnîşan kirin biguherînin" и "ji nû ve binivîsin" ("RetypeWord").

Parametreyên mayî li "ferhengê" têne nivîsandin ("nexşe" di golan de) ji bo çalakiyek diyarkirî, navnîşa wan bi tiştê ku di "Action" de hatî nivîsandin ve girêdayî ye.

Gelek çalakiyên cûda dikarin di yek komê de bêne şirove kirin (beş). An jî hûn dikarin wê ji hev veqetînin. Wekî ku min li jor nîşan da.

Min tavilê çalakiya "Exec" saz kir da ku skrîpta derveyî bicîh bîne. Bi vebijarka ku tampona tomarkirî di stdin de bikişîne.

  • "Li bendê = 1" - li benda qedandina pêvajoya xebitandinê bisekinin.
  • Dibe ku, "bi berdêlê" hûn ê bixwazin ku mirovên din li hawîrdorê bixin. agahiyên wekî navê çîna pencereyê ku jê hatiye girtin.
    "Ma hûn dixwazin destwerê xwe girêdin? Ev cihê ku divê hûn biçin ev e.”

Few (vexist). Xuya ye ku min tiştek ji bîr nekiriye.

Oops! Erê, min ji bîr nekir ...
Veavakirina destpêkirinê li ku ye? Di koda hişk de? Wisa:

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

Min li ku derê ji bîr kir / xeletiyek kir? (bêyî vê rê tune), Ez bi rastî hêvî dikim ku xwendevanên baldar pir tembel nebin ku pozê xwe bixin.

Bextê te xweş bî

Source: www.habr.com

Add a comment