рд▓рд┐рдирдХреНрд╕рд╕рд╛рдареА рдкреБрдВрдЯреЛ рд╕реНрд╡рд┐рдЪрд░рдЪреЗ рдирд╡реАрди рдЕреЕрдирд╛рд▓реЙрдЧ: xswitcher

xneur рдЪреНрдпрд╛ рд╕рдорд░реНрдердирд╛рдЪреНрдпрд╛ рд╕рдорд╛рдкреНрддреАрдореБрд│реЗ рдорд▓рд╛ рдЧреЗрд▓реНрдпрд╛ рд╕рд╣рд╛ рдорд╣рд┐рдиреНрдпрд╛рдВрдд рдХрд╛рд╣реА рд╡реЗрджрдирд╛ рдЭрд╛рд▓реНрдпрд╛ рдЖрд╣реЗрдд. (рдорд╛рдЭреНрдпрд╛ рдбреЗрд╕реНрдХрдЯреЙрдкрд╡рд░ OpenSUSE 15.1 рдЪреНрдпрд╛ рдЖрдЧрдордирд╛рдкрд╛рд╕реВрди: xneur рд╕рдХреНрд╖рдо рдХреЗрд▓реНрдпрд╛рдореБрд│реЗ, рдХреАрдмреЛрд░реНрдб рдЗрдирдкреБрдЯрд╕рд╣ рд╡рд┐рдВрдбреЛ рдлреЛрдХрд╕ рдЖрдгрд┐ рдордЬреЗрджрд╛рд░ рдлреНрд▓рд┐рдХрд░ рдЧрдорд╛рд╡рддрд╛рдд).

тАЬрдЕрд░реЗ, рдзрд┐рдХреНрдХрд╛рд░ рдЖрд╣реЗ, рдореА рдкреБрдиреНрд╣рд╛ рдЪреБрдХреАрдЪреНрдпрд╛ рдорд╛рдВрдбрдгреАрдд рдЯрд╛рдЗрдк рдХрд░рд╛рдпрд▓рд╛ рд╕реБрд░реБрд╡рд╛рдд рдХреЗрд▓реАтАЭ - рдорд╛рдЭреНрдпрд╛ рдХрд╛рдорд╛рдд рд╣реЗ рдЕрдиреЗрдХрджрд╛ рдЕрд╢реНрд▓реАрд▓рдкрдгреЗ рдШрдбрддреЗ. рдЖрдгрд┐ рд╕рдХрд╛рд░рд╛рддреНрдордХ рдЬреЛрдбрдд рдирд╛рд╣реА.

рд▓рд┐рдирдХреНрд╕рд╕рд╛рдареА рдкреБрдВрдЯреЛ рд╕реНрд╡рд┐рдЪрд░рдЪреЗ рдирд╡реАрди рдЕреЕрдирд╛рд▓реЙрдЧ: xswitcher
рддреНрдпрд╛рдЪ рд╡реЗрд│реА, рдореА (рдПрдХ рдбрд┐рдЭрд╛рдИрди рдЕрднрд┐рдпрдВрддрд╛ рдореНрд╣рдгреВрди) рдорд▓рд╛ рдЬреЗ рд╣рд╡реЗ рдЖрд╣реЗ рддреЗ рдЕрдЧрджреА рд╕реНрдкрд╖реНрдЯрдкрдгреЗ рдорд╛рдВрдбреВ рд╢рдХрддреЛ. рдЖрдгрд┐ рдорд▓рд╛ (рдкреНрд░рдердо Punto Switcher рд╡рд░реВрди, рдЖрдгрд┐ рдирдВрддрд░, Windows Vista рдЪреЗ рдЖрднрд╛рд░, рд╢реЗрд╡рдЯреА Linux рд╡рд░, xneur рд╡рд░реВрди) рдмрд░реЛрдмрд░ рдПрдХ рд╣рд╡реЗ рд╣реЛрддреЗ. рдХрдЪрд░рд╛ рдкрдбрджрд╛ рдЪреБрдХреАрдЪреНрдпрд╛ рдорд╛рдВрдбрдгреАрдд рдЖрд╣реЗ рд╣реЗ рд▓рдХреНрд╖рд╛рдд рдЖрд▓реНрдпрд╛рд╡рд░ (рд╣реЗ рд╕рд╣рд╕рд╛ рдирд╡реАрди рд╢рдмреНрдж рдЯрд╛рдЗрдк рдХрд░рдгреНрдпрд╛рдЪреНрдпрд╛ рд╢реЗрд╡рдЯреА рд╣реЛрддреЗ), "рд╡рд┐рд░рд╛рдо рджреНрдпрд╛/рд╡рд┐рд░рд╛рдо рджреНрдпрд╛" рд╡рд░ рдерд╛рдВрдмрд╛. рдЖрдгрд┐ рддреБрдореНрд╣реА рдЬреЗ рдЯрд╛рдЗрдк рдХреЗрд▓реЗ рддреЗ рдорд┐рд│рд╡рд╛.

рдпрд╛ рдХреНрд╖рдгреА, рдЙрддреНрдкрд╛рджрдирд╛рдордзреНрдпреЗ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ / рдЬрдЯрд┐рд▓рддреЗрдЪреЗ рдЗрд╖реНрдЯрддрдо (рдорд╛рдЭреНрдпрд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдирд╛рддреВрди) рдЧреБрдгреЛрддреНрддрд░ рдЖрд╣реЗ. рд╢реЗрдЕрд░ рдХрд░рдгреНрдпрд╛рдЪреА рд╡реЗрд│ рдЖрд▓реА рдЖрд╣реЗ.

TL.DR

рд╕рд░реНрд╡ рдкреНрд░рдХрд╛рд░рдЪреНрдпрд╛ рддрд╛рдВрддреНрд░рд┐рдХ рддрдкрд╢реАрд▓рд╛рдВрдЪреЗ рдкрд╛рд▓рди рдХреЗрд▓реЗ рдЬрд╛рдИрд▓, рдореНрд╣рдгреВрди рдкреНрд░рдердо - рджреБрд╡рд╛ "рд╕реНрдкрд░реНрд╢ рдХрд░рдгреНрдпрд╛рд╕рд╛рдареА" рдЕрдзреАрд░ рд╕рд╛рдареА.

рдЦрд╛рд▓реАрд▓ рд╡рд░реНрддрди рд╕рдзреНрдпрд╛ рд╣рд╛рд░реНрдбрдХреЛрдб рдХреЗрд▓реЗрд▓реЗ рдЖрд╣реЗ:

  • "рдкреЙрдЬ/рдмреНрд░реЗрдХ": рдкреЕрдб (рдмреЕрдХрд╕реНрдкреЗрд╕) рд╢реЗрд╡рдЯрдЪрд╛ рд╢рдмреНрдж, рд╕рдХреНрд░рд┐рдп рд╡рд┐рдВрдбреЛрдордзреАрд▓ рд▓реЗрдЖрдЙрдЯ (0 рдЖрдгрд┐ 1 рджрд░рдореНрдпрд╛рди) рд╕реНрд╡рд┐рдЪ рдХрд░рддреЛ рдЖрдгрд┐ рдкреБрдиреНрд╣рд╛ рдЯрд╛рдЗрдк рдХрд░рддреЛ.
  • "рдХрд╛рд╣реАрд╣реА рдирд╕рд▓реЗрд▓реЗ Ctrl рдбрд╛рд╡реАрдХрдбреЗ": рд╕рдХреНрд░рд┐рдп рд╡рд┐рдВрдбреЛрдордзреНрдпреЗ рд▓реЗрдЖрдЙрдЯ рд╕реНрд╡рд┐рдЪ рдХрд░рддреЗ (0 рдЖрдгрд┐ 1 рджрд░рдореНрдпрд╛рди).
  • "рдХрд╛рд╣реАрд╣реА рдирд╕рддрд╛рдирд╛ рдбрд╛рд╡реАрдХрдбреЗ рд╢рд┐рдлреНрдЯ": рд╕рдХреНрд░рд┐рдп рд╡рд┐рдВрдбреЛрдордзреНрдпреЗ рд▓реЗрдЖрдЙрдЯ #0 рдЪрд╛рд▓реВ рдХрд░рддреЗ.
  • "рдХрд╛рд╣реАрд╣реА рдирд╕рддрд╛рдирд╛ рдЙрдЬрд╡реАрдХрдбреЗ рд╢рд┐рдлреНрдЯ": рд╕рдХреНрд░рд┐рдп рд╡рд┐рдВрдбреЛрдордзреНрдпреЗ рд▓реЗрдЖрдЙрдЯ # 1 рдЪрд╛рд▓реВ рдХрд░рддреЗ.

рдЖрддрд╛рдкрд╛рд╕реВрди, рдореА рд╡рд░реНрддрди рд╕рд╛рдиреБрдХреВрд▓рд┐рдд рдХрд░рдгреНрдпрд╛рдЪреА рдпреЛрдЬрдирд╛ рдЖрдЦрдд рдЖрд╣реЗ. рдЕрднрд┐рдкреНрд░рд╛рдпрд╛рд╢рд┐рд╡рд╛рдп, рддреЗ рдордиреЛрд░рдВрдЬрдХ рдирд╛рд╣реА (рддрд░реАрд╣реА рддреЗ рдорд▓рд╛ рдЕрдиреБрдХреВрд▓ рдЖрд╣реЗ). рдорд╛рдЭрд╛ рд╡рд┐рд╢реНрд╡рд╛рд╕ рдЖрд╣реЗ рдХреА Habr├й рд╡рд░ рд╕рдорд╛рди рд╕рдорд╕реНрдпрд╛ рдЕрд╕рд▓реЗрд▓реНрдпрд╛ рдкреНрд░реЗрдХреНрд╖рдХрд╛рдВрдЪреА рдкреБрд░реЗрд╢реА рдЯрдХреНрдХреЗрд╡рд╛рд░реА рдЖрд╣реЗ.

рдиреЛ рдмреЙрд▓ рдХрд╛рд░рдг рд╡рд░реНрддрдорд╛рди рдЖрд╡реГрддреНрддреАрдордзреНрдпреЗ, рдХреАрд▓реЙрдЧрд░ "/dev/input/" рд╢реА рд╕рдВрд▓рдЧреНрди рдЖрд╣реЗ, xswitcher рд░реВрдЯ рдореНрд╣рдгреВрди рдЪрд╛рд▓рд╡рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ:

chown root:root xswitcher
chmod +xs xswitcher

рдХреГрдкрдпрд╛ рд▓рдХреНрд╖рд╛рдд рдареЗрд╡рд╛: suid рд╕рд╣ рдлрд╛рдЗрд▓рдЪрд╛ рдорд╛рд▓рдХ рд░реВрдЯ рдЕрд╕рдгреЗ рдЖрд╡рд╢реНрдпрдХ рдЖрд╣реЗ, рдХрд╛рд░рдг рдорд╛рд▓рдХ рдХреЛрдг рдЖрд╣реЗ - рддреНрдпрд╛ рд╕реВрдЯрдордзреНрдпреЗ рдЖрдгрд┐ рд╕реНрдЯрд╛рд░реНрдЯрдЕрдкрд╡рд░ рдЪрд╛рд▓реВ рд╣реЛрдИрд▓.

Paranoids (рдореА рдЕрдкрд╡рд╛рдж рдирд╛рд╣реА) рдкрд╛рд╕реВрди рдХреНрд▓реЛрди рдХрд░реВ рд╢рдХрддрд╛ рдЬреАрдЖрдпрдЯреА рдЖрдгрд┐ рд╕рд╛рдЗрдЯрд╡рд░ рдЧреЛрд│рд╛ рдХрд░рд╛. рддрд╕реЗ:

go get "github.com/micmonay/keybd_event"
go get "github.com/gvalkov/golang-evdev"

### X11 headers for OpenSUSE/deb-based
zypper install libX11-devel libXmu-devel
apt-get install libx11-dev libxmu-dev

cd "x switcher/src/"
go build -o xswitcher -ldflags "-s -w" --tags static_all src/*.go

рдЪрд╡реАрдиреБрд╕рд╛рд░ рдСрдЯреЛрд░рди рдЬреЛрдбрд╛ (DE рд╡рд░ рдЕрд╡рд▓рдВрдмреВрди).

рдХрд╛рд░реНрдп рдХрд░рддреЗ, "рд▓рд╛рдкрд╢реА рдорд╛рдЧрдд рдирд╛рд╣реА" (тЙИ30 CPU рд╕реЗрдХрдВрдж рдкреНрд░рддрд┐рджрд┐рди, тЙИ12 MB RSS рдордзреНрдпреЗ).

рддрдкрд╢реАрд▓

рдЖрддрд╛ - рддрдкрд╢реАрд▓.

рд╕рдВрдкреВрд░реНрдг рд░реЗрдкреЙрдЬрд┐рдЯрд░реА рдореВрд│рддрдГ рдорд╛рдЭреНрдпрд╛ рдкрд╛рд│реАрд╡ рдкреНрд░рд╛рдгреНрдпрд╛рдВрдЪреНрдпрд╛ рдкреНрд░рдХрд▓реНрдкрд╛рд╕рд╛рдареА рд╕рдорд░реНрдкрд┐рдд рд╣реЛрддреА рдЖрдгрд┐ рджреБрд╕рд░рд╛ рдПрдХ рд╕реБрд░реВ рдХрд░рдгреНрдпрд╛рд╕ рдореА рдЦреВрдк рдЖрд│рд╢реА рдЖрд╣реЗ. рддрд░, рд╕рд░реНрд╡рдХрд╛рд╣реА рдвреАрдЧ рдХреЗрд▓реЗрд▓реЗ рдЖрд╣реЗ (рдлрдХреНрдд рдлреЛрд▓реНрдбрд░реНрд╕рдордзреНрдпреЗ) рдЖрдгрд┐ AGPL ("рдкреЗрдЯрдВрдЯ рдЗрди рд░рд┐рд╡реНрд╣рд░реНрд╕") рд╕рд╣ рдЭрд╛рдХрд▓реЗрд▓реЗ рдЖрд╣реЗ.

xswitcher рдХреЛрдб рдЧреЛрд▓рд╛рдВрдЧрдордзреНрдпреЗ рд▓рд┐рд╣рд┐рд▓рд╛ рдЖрд╣реЗ, рдЬреНрдпрд╛рдордзреНрдпреЗ рдХрд┐рдорд╛рди C рд╕рдорд╛рд╡реЗрд╢ рдЖрд╣реЗ. рдпрд╛ рджреГрд╖реНрдЯрд┐рдХреЛрдирд╛рдиреЗ (рдЖрддрд╛рдкрд░реНрдпрдВрдд) рдХрдореАрдд рдХрдореА рдкреНрд░рдпрддреНрди рдХрд░рдгреЗ рдЕрдкреЗрдХреНрд╖рд┐рдд рдЖрд╣реЗ. cgo рджреНрд╡рд╛рд░реЗ рдЧрд╣рд╛рд│ рдХрдиреЗрдХреНрдЯ рдХрд░рдгреНрдпрд╛рдЪреА рдХреНрд╖рдорддрд╛ рд░рд╛рдЦреВрди рдареЗрд╡рдгреЗ.

рдЯрд┐рдкреНрдкрдгреНрдпрд╛ рдордЬрдХреВрд░рд╛рдд рдШрд╛рддрд▓реНрдпрд╛ рдЖрд╣реЗрдд, рддреНрдпрд╛рдВрдиреА рдХреБрдареВрди рдХрд╛рд╣реА рдШреЗрддрд▓реЗ рдЖрдгрд┐ рдХрд╛. рдХрд╛рд░рдг xneur рдХреЛрдбрдиреЗ рдорд▓рд╛ "рдкреНрд░реЗрд░рдгрд╛" рджрд┐рд▓реА рдирд╛рд╣реА, рддреЛ рдкреНрд░рд╛рд░рдВрдн рдмрд┐рдВрджреВ рдореНрд╣рдгреВрди рдШреЗрддрд▓рд╛ loloswitcher.

"/dev/input/" рд╡рд╛рдкрд░рдгреНрдпрд╛рдЪреЗ рддреНрдпрд╛рдЪреЗ рдлрд╛рдпрджреЗ (рд╕реНрд╡рдпрдВ-рдкреБрдирд░рд╛рд╡реГрддреНрддреАрд╕рд╣ рджрд╛рдмрд▓реЗрд▓реНрдпрд╛ рдХреАрд╕рд╣ рд╕рд░реНрд╡ рдХрд╛рд╣реА рджреГрд╢реНрдпрдорд╛рди рдЖрд╣реЗ) рдЖрдгрд┐ рддреЛрдЯреЗ рджреЛрдиреНрд╣реА рдЖрд╣реЗрдд. рдмрд╛рдзрдХ рдЖрд╣реЗрдд:

  • рд╕реНрд╡рдпрдВ-рдкреБрдирд░рд╛рд╡реГрддреНрддреА (рдХреЛрдб "2" рд╕рд╣ рдЗрд╡реНрд╣реЗрдВрдЯ) xx рд╕рд╣ рдкреБрдиреНрд╣рд╛ рдкреНрд░рдпрддреНрди рдХрд░рдгреНрдпрд╛рд╢реА рд╕рдВрдмрдВрдзрд┐рдд рдирд╛рд╣реА.
  • X11 рдЗрдВрдЯрд░рдлреЗрд╕рджреНрд╡рд╛рд░реЗ рдЗрдирдкреБрдЯ рдкрд╛рд╣реВ рд╢рдХрдд рдирд╛рд╣реА (рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде VNC рдХрд╕реЗ рдХрд╛рд░реНрдп рдХрд░рддреЗ).
  • рд░реВрдЯ рдкрд╛рд╣рд┐рдЬреЗ.

рджреБрд╕рд░реАрдХрдбреЗ, рддреБрдореНрд╣реА "XSelectExtensionEvent()" рджреНрд╡рд╛рд░реЗ X рдЗрд╡реНрд╣реЗрдВрдЯрдЪреА рд╕рджрд╕реНрдпрддрд╛ рдШреЗрдК рд╢рдХрддрд╛. рдЖрдкрдг рдпреЗрдереЗ рдбреЛрдХрд╛рд╡реВ рд╢рдХрддрд╛ xinput рдХреЛрдб. рдорд▓рд╛ рдЬрд╛рдгреНрдпрд╛рд╕рд╛рдареА рдЕрд╕реЗ рдХрд╛рд╣реАрд╣реА рд╕рд╛рдкрдбрд▓реЗ рдирд╛рд╣реА рдЖрдгрд┐ рдорд╕реБрджрд╛ рдЕрдВрдорд▓рдмрдЬрд╛рд╡рдгреАрдиреЗ рдЬрд╛рддрд╛ рдЬрд╛рддрд╛ рд╕реА-рдХреЛрдбрдЪреНрдпрд╛ рд╢рдВрднрд░ рдУрд│реА рджрд┐рд▓реНрдпрд╛. рдЖрддрд╛рд╕рд╛рдареА, рдмрд╛рдЬреВрд▓рд╛ рдареЗрд╡рд╛.

рд╡рд░реНрдЪреНрдпреБрдЕрд▓ рдХреАрдмреЛрд░реНрдб рд╕реНрдХреНрд░реВ рдХрд░реВрди "рдкрд░рдд" рдирд┐рд╖реНрдХрд░реНрд╖ рдХрд╛рдврд▓рд╛ рдЬрд╛рддреЛ. keybd_event рдЪреНрдпрд╛ рд▓реЗрдЦрдХрд╛рд╕ рдзрдиреНрдпрд╡рд╛рдж, рдкрд░рдВрддреБ рдЦреВрдк рдЙрдЪреНрдЪ-рд╕реНрддрд░реАрдп рдЕреЕрдмреНрд╕реНрдЯреНрд░реЕрдХреНрд╢рди рдЖрд╣реЗ рдЖрдгрд┐ рддреЗ рдкреБрдиреНрд╣рд╛ рдХрд░рд╛рд╡реЗ рд▓рд╛рдЧреЗрд▓. рдЙрджрд╛рд╣рд░рдгрд╛рд░реНрде, рдЙрдЬрд╡реА рд╡рд┐рди-рдХреА рдорд╛рдЭреНрдпрд╛рд╕рд╛рдареА 3рд░реА рдкрдВрдХреНрддреА рдирд┐рд╡рдбрддреЗ. рдЖрдгрд┐ рдлрдХреНрдд рдбрд╛рд╡реАрдХрдбреАрд▓ Win рдкрд░рдд рдЕрдиреБрд╡рд╛рджрд┐рдд рдЖрд╣реЗ.

рдЬреНрдЮрд╛рдд рдмрдЧ

  • рдЖрдореНрд╣рд╛рд▓рд╛ "рд╕рдВрдорд┐рд╢реНрд░" рдЗрдирдкреБрдЯрдмрджреНрджрд▓ рдХрд╛рд╣реАрд╣реА рдорд╛рд╣рд┐рдд рдирд╛рд╣реА (рдЙрджрд╛рд╣рд░рдг: ┬╜). рддреНрдпрд╛рдЪреА рдЖрддреНрддрд╛ рдЧрд░рдЬ рдирд╛рд╣реА.
  • рдпреЛрдЧреНрдп рд╡рд┐рдирдЪреЗ тАЛтАЛрдЪреБрдХреАрдЪреЗ рдкреБрдирд░реБрддреНрдкрд╛рджрди рдХрд░рд╛. рдорд╛рдЭреНрдпрд╛ рдмрд╛рдмрддреАрдд, рддреЗ рдЙрдЪреНрдЪрд╛рд░рд╛рдВрдЪреЗ рд╕реНрдерд╛рди рдЦрдВрдбрд┐рдд рдХрд░рддреЗ.
  • рдХреЛрдгрддреЗрд╣реА рд╕реБрдЧрдо рдЗрдирдкреБрдЯ рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдирд╛рд╣реА. рддреНрдпрд╛рдРрд╡рдЬреА, рдЕрдиреЗрдХ рдлрдВрдХреНрд╢рдиреНрд╕ рдЖрд╣реЗрдд: Compare(), CtrlSequence(), RepeatSequence(), SpaceSequence(). ╨б╨┐╨░╤Б╨╕╨▒╨╛ nsmcan рджрдХреНрд╖рддреЗрд╕рд╛рдареА: рдХреЛрдбрдордзреНрдпреЗ рдЖрдгрд┐ рдпреЗрдереЗ рджреБрд░реБрд╕реНрдд рдХреЗрд▓реЗ рдЖрд╣реЗ. рдПрдХрд╛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рдВрднрд╛рд╡реНрдпрддреЗрд╕рд╣, рдЖрдкрдг рдмрджрд▓рддрд╛рдирд╛ рдмрдЧ рдкрдХрдбреВ рд╢рдХрддрд╛.
    рдпрд╛ рдард┐рдХрд╛рдгреА, рдорд▓рд╛ "рдХрд╕реЗ рдХрд░рд╛рд╡реЗ" рд╣реЗ рдорд╛рд╣рд┐рдд рдирд╛рд╣реА рдЖрдгрд┐ рдорд▓рд╛ рдХреЛрдгрддреНрдпрд╛рд╣реА рд╕реВрдЪрдирд╛рдВрдмрджреНрджрд▓ рдЖрдирдВрдж рд╣реЛрдИрд▓.
  • (рдЕрд░реЗ рджреЗрд╡рд╛) рдЪреЕрдиреЗрд▓рдЪрд╛ рд╕рдорд╡рд░реНрддреА рд╡рд╛рдкрд░ (рдХреАрдмреЛрд░реНрдб рдЗрд╡реНрд╣реЗрдВрдЯреНрд╕, рдорд╛рдИрд╕ рдЗрд╡реНрд╣реЗрдВрдЯреНрд╕).

рдирд┐рд╖реНрдХрд░реНрд╖

рдХреЛрдб рд╕рд░реНрд╡рд╛рдд рд╕реЛрдкрд╛ рдкреНрд░рдХреНрд░рд┐рдпрд╛рддреНрдордХ рдЖрд╣реЗ. рдЖрдгрд┐ рдорд╛рдЭреНрдпрд╛рд╕рд╛рд░рдЦрд╛ рдореВрд░реНрдЦ. рдореНрд╣рдгреВрди, рдореА рдпрд╛ рдЖрд╢реЗрдиреЗ рд╕реНрд╡рддрдГрд▓рд╛ рд╕рд╛рдВрддреНрд╡рди рджреЗрддреЛ рдХреА рдЬрд╡рд│рдЬрд╡рд│ рдХреЛрдгрддрд╛рд╣реА рддрдВрддреНрд░рдЬреНрдЮ рддреНрдпрд╛рд▓рд╛ рдкрд╛рд╣рд┐рдЬреЗ рддреЗ рдкреВрд░реНрдг рдХрд░рдгреНрдпрд╛рд╕ рд╕рдХреНрд╖рдо рдЕрд╕реЗрд▓. рдЖрдгрд┐ рдпрд╛рдореБрд│реЗ, рд╣реЗ рдЙрддреНрдкрд╛рджрди рд╕рдорд░реНрдердирд╛рд╢рд┐рд╡рд╛рдп рдирд╖реНрдЯ рд╣реЛрдгрд╛рд░ рдирд╛рд╣реА, рдЬрд╕реЗ рдХреА рдЕрдЧрджреА рдордиреЛрд░рдВрдЬрдирд╛рд╕рд╛рдареА.

рдирд╢реАрдм!

рд╕реНрддреНрд░реЛрдд: www.habr.com

рдПрдХ рдЯрд┐рдкреНрдкрдгреА рдЬреЛрдбрд╛