ื ื™ื• ืึทื ืึทืœืึธื’ ืคื•ืŸ Punto Switcher ืคึฟืึทืจ ืœื™ื ื•ืงืก: xswitcher

ื“ืขืจ ืกื•ืฃ ืคื•ืŸ ืงืกื ืขื•ืจ ืฉื˜ื™ืฆืŸ ื”ืื˜ ื’ืขืคึฟื™ืจื˜ ืžื™ืจ ืขื˜ืœืขื›ืข ืฆืึธืจืขืก ืื™ืŸ ื“ื™ ืœืขืฆื˜ืข ื–ืขืงืก ื—ื“ืฉื™ื. (ืžื™ื˜ ื“ื™ ืึทื“ื•ื•ืขื ื˜ ืคื•ืŸ OpenSUSE 15.1 ืื•ื™ืฃ ืžื™ื™ืŸ ื“ืขืกืงื˜ืึทืคึผืก: ืžื™ื˜ Xneur ืขื ื™ื™ื‘ืึทืœื“, Windows ืคืึทืจืœื™ืจืŸ ืคืึธืงื•ืก ืื•ืŸ ืคืœื™ืงืขืจ ืžืึธื“ื ืข ืื™ืŸ ืฆื™ื™ื˜ ืžื™ื˜ ืงืœืึทื•ื•ื™ืึทื˜ื•ืจ ืึทืจื™ื™ึทื ืฉืจื™ื™ึทื‘).

"ืึธื”, ืคืึทืจืฉื™ืœื˜ืŸ ืขืก, ืื™ืš ืกื˜ืึทืจื˜ืขื“ ื˜ื™ื™ืคึผื™ื ื’ ืื™ืŸ ื“ืขื ืื•ืžืจืขื›ื˜ ืื•ื™ืกืœื™ื™ื’ ื•ื•ื™ื“ืขืจ" - ืื™ืŸ ืžื™ื™ืŸ ืึทืจื‘ืขื˜ ื“ืึธืก ื›ืึทืคึผืึทื ื– ืึธืจื ื˜ืœื™ ืึธืคื˜. ืื•ืŸ ืขืก ื˜ื•ื˜ ื ื™ืฉื˜ ืœื™ื™ื’ืŸ ืขืคึผืขืก positive.

ื ื™ื• ืึทื ืึทืœืึธื’ ืคื•ืŸ Punto Switcher ืคึฟืึทืจ ืœื™ื ื•ืงืก: xswitcher
ืื™ืŸ ื“ืขืจ ื–ืขืœื‘ื™ืงืขืจ ืฆื™ื™ื˜, ืื™ืš (ื•ื•ื™ ืึท ืคึผืœืึทืŸ ื™ื ื–ืฉืขื ื™ืจ) ืงืขื ืขืŸ ื’ืึทื ืฅ ืงืœืืจ ืคืึธืจืžื•ืœื™ืจืŸ ื•ื•ืึธืก ืื™ืš ื•ื•ื™ืœืŸ. ืึธื‘ืขืจ ืื™ืš ื’ืขื•ื•ืืœื˜ (ืขืจืฉื˜ืขืจ ืคึฟื•ืŸ Punto Switcher, ืื•ืŸ ื“ืขืจื ืึธืš, ื“ืึทื ืง ืฆื• Windows Vista, ืœืขืกืึธืฃ ื‘ืึทืฉื˜ื™ืžืขืŸ ืฆื• ืœื™ื ื•ืงืก ืคึฟื•ืŸ Xneur) ืคึผื•ื ืงื˜ ืื™ื™ืŸ ื–ืึทืš. ื•ื•ื™ื™ืœ ืื™ื™ื ื’ืขื–ืขืŸ ืึทื– ื“ื™ ืžื™ืกื˜ ืื•ื™ืฃ ื“ืขื ืขืงืจืึทืŸ ืื™ื– ืื™ืŸ ื“ื™ ืื•ืžืจืขื›ื˜ ืื•ื™ืกืœื™ื™ื’ (ื“ืึธืก ื™ื•ื–ืฉืึทื•ื•ืึทืœื™ ื›ืึทืคึผืึทื ื– ืื™ืŸ ื“ื™ ืกื•ืฃ ืคื•ืŸ ื˜ื™ื™ืคึผื™ื ื’ ืึท ื ื™ื™ึท ื•ื•ืึธืจื˜), ืกื˜ืึทืžืคึผ ืื•ื™ืฃ "ืคึผืึธื– / ื‘ืจืขื›ืŸ". ืื•ืŸ ื‘ืึทืงื•ืžืขืŸ ื•ื•ืึธืก ืื™ืจ ื’ืขื“ืจื•ืงื˜.

ืื™ืŸ ื“ืขื ืžืึธืžืขื ื˜, ื“ื™ ืคึผืจืึธื“ื•ืงื˜ ื”ืื˜ ื“ื™ ืึธืคึผื˜ื™ืžืึทืœ (ืคึฟื•ืŸ ืžื™ื™ืŸ ืคื•ื ื˜ ืคื•ืŸ ืžื™ื™ื ื•ื ื’) ืคืึทื ื’ืงืฉืึทื ืึทืœื™ื˜ื™ / ืงืึทืžืคึผืœืขืงืกื™ื˜ื™ ืคืึทืจื”ืขืœื˜ืขื ื™ืฉ. ืขืก ืื™ื– ืฆื™ื™ื˜ ืฆื• ื˜ื™ื™ืœืŸ.

TL.DR

ืขืก ื•ื•ืขื˜ ื–ื™ื™ืŸ ืึทืœืข ืกืึธืจืฅ ืคื•ืŸ ื˜ืขื›ื ื™ืฉ ื“ืขื˜ืึทื™ืœืก ืฉืคึผืขื˜ืขืจ, ืึทื–ื•ื™ ืขืจืฉื˜ืขืจ - ืœื™ื ืง "ืฆื• ืคืึทืจื‘ื™ื ื“ืŸ" ืคืืจ ื“ื™ ืื•ืžื’ืขื“ื•ืœื“ื™ืงืข.

ื“ืขืจื•ื•ื™ื™ึทืœ ื“ื™ ืคืืœื’ืขื ื“ืข ื ืึทื˜ื•ืจ ืื™ื– ืฉื•ื•ืขืจ ืงืึธื“ืขื“:

  • "ืคึผืึธื–ืข / ื‘ืจืขื›ืŸ": ื‘ืึทืงืกืคึผื™ื™ืก ื“ื™ ืœืขืฆื˜ืข ื•ื•ืึธืจื˜, ืกื•ื•ื™ื˜ืฉื™ื– ื“ื™ ืื•ื™ืกืœื™ื™ื’ ืื™ืŸ ื“ื™ ืึทืงื˜ื™ื•ื• ืคึฟืขื ืฆื˜ืขืจ (ืฆื•ื•ื™ืฉืŸ 0 ืื•ืŸ 1) ืื•ืŸ ื“ื™ืœื– ื•ื•ื™ื“ืขืจ.
  • "ืœื™ื ืงืก ืงื˜ืจืœ ืึธืŸ ืขืคึผืขืก": ืกื•ื•ื™ื˜ืฉื™ื– ื“ื™ ืื•ื™ืกืœื™ื™ื’ ืื™ืŸ ื“ื™ ืึทืงื˜ื™ื•ื• ืคึฟืขื ืฆื˜ืขืจ (ืฆื•ื•ื™ืฉืŸ 0 ืื•ืŸ 1).
  • "ืœื™ื ืงืก ืฉื™ืคื˜ ืึธืŸ ืขืคึผืขืก": ื˜ื•ืจื ืก ืื•ื™ืฃ ืื•ื™ืกืœื™ื™ื’ ื ื•ืž 0 ืื™ืŸ ื“ื™ ืึทืงื˜ื™ื•ื• ืคึฟืขื ืฆื˜ืขืจ.
  • "ืจืขื›ื˜ ืฉื™ืคื˜ ืึธืŸ ืขืคึผืขืก": ื˜ื•ืจื ืก ืื•ื™ืฃ ืื•ื™ืกืœื™ื™ื’ ื ื•ืž 1 ืื™ืŸ ื“ื™ ืึทืงื˜ื™ื•ื• ืคึฟืขื ืฆื˜ืขืจ.

ืคื•ืŸ ืื™ืฆื˜ ืื•ื™ืฃ ืื™ืš ืคึผืœืึทืŸ ืฆื• ืงืึทืกื˜ืึทืžื™ื™ื– ื“ื™ ื ืึทื˜ื•ืจ. ืึธืŸ ื‘ืึทืžืขืจืงื•ื ื’ืขืŸ, ืขืก ืื™ื– ื ื™ืฉื˜ ื˜ืฉื™ืงืึทื•ื•ืข (ืื™ืš ื‘ื™ืŸ ื’ื•ื˜ ืžื™ื˜ ืื™ื ืกื™ื™ึท ื•ื•ื™ ืกื™ื™ึท). ืื™ืš ื’ืœื™ื™ื‘ ืื– ืื•ื™ืฃ Habrรฉ ื•ื•ืขื˜ ื–ื™ื™ืŸ ื’ืขื ื•ื’ ืคืจืืฆืขื ื˜ ืคื•ืŸ ื“ืขื ืขื•ืœื ืžื™ื˜ ืขื ืœื™ื›ืข ืคืจืื‘ืœืขืžืขืŸ.

ื ื‘ ื•ื•ื™ื™ึทืœ ืื™ืŸ ื“ื™ ืงืจืึทื ื˜ ื•ื•ืขืจืกื™ืข, ื“ื™ ืงื™ื™ืœืึธื’ื’ืขืจ ืื™ื– ืึทื˜ืึทื˜ืฉื˜ ืฆื• "/dev/input/", xswitcher ืžื•ื–ืŸ ื–ื™ื™ืŸ ืœืึธื ื˜ืฉื˜ ืžื™ื˜ ื•ื•ืึธืจืฆืœ ืจืขื›ื˜:

chown root:root xswitcher
chmod +xs xswitcher

ื‘ื™ื˜ืข ื˜ืึธืŸ: ื“ืขืจ ื‘ืึทื–ื™ืฆืขืจ ืคื•ืŸ ื“ืขืจ ื˜ืขืงืข ืžื™ื˜ suid ืžื•ื–ืŸ ื–ื™ื™ืŸ ื•ื•ืึธืจืฆืœ, ื•ื•ื™ื™ึทืœ ื•ื•ืขืจ ืขืก ื™ื– ืื™ื– ื“ื™ ื‘ืึทื–ื™ืฆืขืจ ื•ื•ืขื˜ ื–ื™ื™ืŸ ืคืืจื•ื•ืื ื“ืœืขืŸ ืื™ืŸ ืกื•ื™ื“ ื‘ื™ื™ ืกื˜ืึทืจื˜ืึทืคึผ.

ืคึผืึทืจืึทื ืึธื™ื“ืก (ืื™ืš ื‘ื™ืŸ ืงื™ื™ืŸ ื•ื™ืกื ืขื) ืงืขื ืขืŸ ืงืœืึธื•ืŸ ืคื•ืŸ GIT ืื•ืŸ ืึทืกืขืžื‘ืึทืœ ืื•ื™ืฃ ืคึผืœืึทืฅ. ืื–ื•ื™:

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

ืœื™ื™ื’ ืึทื•ื˜ืึธืกื˜ืึทืจื˜ ืฆื• ื˜ืขื (ื“ื™ืคึผืขื ื“ื™ื ื’ ืื•ื™ืฃ ื“ืข).

ืขืก ืึทืจื‘ืขื˜, "ื˜ื•ื˜ ื ื™ืฉื˜ ืคืจืขื’ืŸ ืคึฟืึทืจ ืงืึทืฉืข" (โ‰ˆ30 ืกืขืงื•ื ื“ืขืก ืงืคึผื• ืคึผืขืจ ื˜ืึธื’, โ‰ˆ12 ืžื‘ ืื™ืŸ ืจืกืก).

ืคืจื˜ื™ื

ืื™ืฆื˜ - ื“ื™ ืคืจื˜ื™ื.

ื“ื™ ื’ืื ืฆืข ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ ืื™ื– ื˜ื›ื™ืœืขืก ื“ืขื“ืึทืงื™ื™ื˜ืึทื“ ืฆื• ืžื™ื™ืŸ ืœื™ื‘ืœื™ื ื’ ืคึผืจื•ื™ืขืงื˜, ืื•ืŸ ืื™ืš ื‘ื™ืŸ ืฆื• ืคื•ื™ืœ ืฆื• ืึธื ื”ื™ื™ื‘ืŸ ืืŸ ืื ื“ืขืจ ืื™ื™ื ืขืจ. ืึทื–ื•ื™, ืึทืœืฅ ืื™ื– ืคึผื™ื™ืœื“ ืึทืจื•ื™ืฃ (ื ืึธืจ ืื™ืŸ ืคืึธืœื“ืขืจืก) ืื•ืŸ ื‘ืื“ืขืงื˜ ื“ื•ืจืš AGPL ("ืคืึทืจืงืขืจื˜ ืคึผืึทื˜ืขื ื˜").

ื“ื™ ืงืกืกื•ื•ื™ื˜ื˜ืฉืขืจ ืงืึธื“ ืื™ื– ื’ืขืฉืจื™ื‘ืŸ ืื™ืŸ ื’ืึธืœืึทื ื’, ืžื™ื˜ ืžื™ื ื™ืžืึทืœ ื™ื ืงืœื•ื–ืฉืึทื ื– ืคื•ืŸ C. ืขืก ืื™ื– ืื ื’ืขื ื•ืžืขืŸ ืึทื– ื“ืขืจ ืฆื•ื’ืึทื ื’ ื•ื•ืขื˜ ืจืขื–ื•ืœื˜ืึทื˜ ืื™ืŸ ื“ืขืจ ืžื™ื ื“ืกื˜ืขืจ ืกื•ืžืข ืคื•ืŸ โ€‹โ€‹ืžื™ (ืึทื–ื•ื™ ื•ื•ื™ื™ึทื˜ ืขืก ื”ืื˜). ื‘ืฉืขืช ืžื™ื™ื ื˜ื™ื™ื ื™ื ื’ ื“ื™ ืคื™ื™ื™ืงื™ื™ื˜ ืฆื• ืคืึทืจื‘ื™ื ื“ืŸ ื•ื•ืึธืก ืื™ื– ืคืขืœื ื“ื™ืง ืžื™ื˜ ืงื’ืึธ.

ื“ืขืจ ื˜ืขืงืกื˜ ื›ึผื•ืœืœ ื‘ืึทืžืขืจืงื•ื ื’ืขืŸ ื•ื•ืขื’ืŸ ื•ื•ื• ืขืก ืื™ื– ื‘ืึทืจืึธื•ื“ ืื•ืŸ ื•ื•ืึธืก. ื•ื•ื™ื™ึทืœ ื“ื™ ืงืกื ืขื•ืจ ืงืึธื“ "ื”ืื˜ ื ื™ืฉื˜ ื™ื ืกืคึผื™ืจื™ืจืŸ ืžื™ืจ", ืื™ืš ื’ืขื ื•ืžืขืŸ ืขืก ื•ื•ื™ ืึท ืกื˜ืึทืจื˜ื™ื ื’ ืคื•ื ื˜ ืœืึธืœืึธืกื•ื•ื™ื˜ื˜ืฉืขืจ.

ื ื™ืฆืŸ "/dev/input/" ื”ืื˜ ื‘ื™ื™ื“ืข ื–ื™ื™ึทืŸ ืึทื“ื•ื•ืึทื ื˜ื™ื“ื–ืฉื™ื– (ืึทืœืฅ ืื™ื– ืงืขื ื˜ื™ืง, ืึทืจื™ื™ึทื ื’ืขืจืขื›ื ื˜ ื“ื™ ื’ืขื“ืจื™ืงื˜ ืึทื•ื˜ืึธ ืื™ื‘ืขืจื—ื–ืจืŸ ืฉืœื™ืกืœ) ืื•ืŸ ื“ื™ืกืึทื“ื•ื•ืึทื ื˜ื™ื“ื–ืฉื™ื–. ื“ื™ ื—ืกืจื•ื ื•ืช ื–ืขื ืขืŸ:

  • ืึทื•ื˜ืึธ ืื™ื‘ืขืจื—ื–ืจืŸ (ื’ืขืฉืขืขื ื™ืฉืŸ ืžื™ื˜ ืงืึธื“ "2") ืื™ื– ื ื™ืฉื˜ ืงืึธืจืึทืœื™ื™ื˜ืึทื“ ืžื™ื˜ ื™ื‘ืขืจื›ืึทื–ืขืจื•ื ื’ ืžื™ื˜ X.
  • ืึทืจื™ื™ึทื ืฉืจื™ื™ึทื‘ ื“ื•ืจืš X11 ื™ื ื˜ืขืจืคื™ื™ืกื™ื– ืื™ื– ื ื™ื˜ ืงืขื ื˜ื™ืง (ื“ืึธืก ืื™ื– ื•ื•ื™ VNC ืึทืจื‘ืขื˜, ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ).
  • ื“ืึทืจืคึฟืŸ ื•ื•ืึธืจืฆืœ.

ืื•ื™ืฃ ื“ื™ ืื ื“ืขืจืข ื”ืึทื ื˜, ืขืก ืื™ื– ืžืขื’ืœืขืš ืฆื• ืึทื‘ืึธื ื™ืจืŸ ืฆื• X events ื“ื•ืจืš "XSelectExtensionEvent ()". ืื™ืจ ืงืขื ืขืŸ ืงื•ืงืŸ ืื™ืŸ ืงืกื™ื ืคึผื•ื˜ ืงืึธื“. ืื™ืš ื”ืึธื‘ ื ื™ื˜ ื’ืขืคึฟื•ื ืขืŸ ืขืคึผืขืก ื•ื•ื™ ื“ืึธืก ืคึฟืึทืจ ื’ื™ื™ืŸ, ืื•ืŸ ื“ื™ ืคึผืจืึธืกื˜ ื™ืžืคึผืœืึทืžืขื ื˜ื™ื™ืฉืึทืŸ ืžื™ื“ ื’ืขื ื•ืžืขืŸ ืึท ื”ื•ื ื“ืขืจื˜ ืฉื•ืจื•ืช ืคื•ืŸ C ืงืึธื“. ืฉื˜ืขืœืŸ ืขืก ื‘ืึทื–ื•ื ื“ืขืจ ืคึฟืึทืจ ืื™ืฆื˜.

ื“ืขืจ "ืคืึทืจืงืขืจื˜" ืจืขื–ื•ืœื˜ืึทื˜ ืื™ื– ื“ืขืจื•ื•ื™ื™ึทืœ ื’ืขืžืื›ื˜ ื“ื•ืจืš ืกืงืจื•ื™ื ื’ ื“ื™ ื•ื•ื™ืจื˜ื•ืึทืœ ืงืœืึทื•ื•ื™ืึทื˜ื•ืจ. ื“ืึทื ืง ืฆื• ื“ืขื ืžื—ื‘ืจ ืคื•ืŸ keybd_event, ืึธื‘ืขืจ ื“ื™ ืึทื‘ืกื˜ืจืึทืงืฆื™ืข ื“ืึธืจื˜ ืื™ื– ืฆื• ื”ื•ื™ืš-ืžื“ืจื’ื” ืื•ืŸ ื•ื•ืขื˜ ื”ืึธื‘ืŸ ืฆื• ื–ื™ื™ืŸ ืจื™ื“ืึทืŸ ื•ื•ื™ื™ึทื˜ืขืจ. ืคึฟืึทืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืื™ืš ื ื•ืฆืŸ ื“ื™ ืจืขื›ื˜ Win ืฉืœื™ืกืœ ืฆื• ืื•ื™ืกืงืœื™ื™ึทื‘ืŸ ื“ื™ 3 ืจื•ื“ืขืจืŸ. ืื•ืŸ ื‘ืœื•ื™ื– ื“ื™ ืœื™ื ืงืก ื’ืขื•ื•ื™ื ืขืŸ ืื™ื– ื˜ืจืึทื ืกืžื™ื˜ื˜ืขื“ ืฆื•ืจื™ืง.

ื‘ืึทื•ื•ื•ืกื˜ ื‘ืึทื’ื–

  • ืžื™ืจ ื˜ืึธืŸ ื ื™ื˜ ื•ื•ื™ืกืŸ ืขืคึผืขืก ื•ื•ืขื’ืŸ "ืงืึธืžืคึผืึธืกื™ื˜ืข" ืึทืจื™ื™ึทื ืฉืจื™ื™ึทื‘ (ื‘ื™ื™ึทืฉืคึผื™ืœ: ยฝ). ืขืก ืื™ื– ื ื™ื˜ ื“ืืจืฃ ืจืขื›ื˜ ืื™ืฆื˜.
  • ืžื™ืจ ื–ืขื ืขืŸ ืคึผืœื™ื™ื™ื ื’ ื“ื™ ืจืขื›ื˜ ื’ืขื•ื•ื™ื ืขืŸ ื™ื ืงืขืจืขืงื˜ืœื™. ืื™ืŸ ืžื™ื™ืŸ ืคืึทืœ, ืขืก ื‘ืจื™ื™ืงืก ื“ื™ ื˜ืจืึธืคึผ.
  • ืขืก ืื™ื– ืงื™ื™ืŸ ืงืœืึธืจ ืึทืจื™ื™ึทื ืฉืจื™ื™ึทื‘ ืคึผืึทืจืกื™ื ื’. ืึทื ืฉื˜ืึธื˜, ืขืก ื–ืขื ืขืŸ ืขื˜ืœืขื›ืข ืคืึทื ื’ืงืฉืึทื ื–: ืคืึทืจื’ืœื™ื™ึทื›ืŸ (), CtrlSequence (), RepeatSequence (), SpaceSequence (). ื“ืึทื ืง nsmcan ืคึฟืึทืจ ื“ื™ื™ืŸ ื–ืึธืจื’: ืงืขืจืขืงื˜ืึทื“ ืขืก ืื™ืŸ ื“ื™ ืงืึธื“ ืื•ืŸ ื“ืึธ. ืžื™ื˜ ืึท ื–ื™ื›ืขืจ ืžืึทืฉืžืึธืขืก, ืื™ืจ ืงืขื ืขืŸ ื›ืึทืคึผืŸ ื‘ืึทื’ื– ื•ื•ืขืŸ ืจื™ืคึผืœื™ื™ืกื™ื ื’.
    ืื™ืŸ ื“ืขื ืคื•ื ื˜ ืื™ืš ื˜ืึธืŸ ื ื™ื˜ ื•ื•ื™ืกืŸ "ื•ื•ื™ ืฆื•" ืื•ืŸ ื•ื•ืึธืœื˜ ื‘ืึทื’ืจื™ืกืŸ ืงื™ื™ืŸ ืคึฟื™ืจืœื™ื™ื’ืŸ.
  • (ืื•ื™ ื’ืึธื˜) ืงืึทืžืคึผืขื˜ื™ื˜ื™ื•ื• ื ื•ืฆืŸ ืคื•ืŸ ื˜ืฉืึทื ืึทืœื– (ืงื™ื‘ืึธืจื“ ืขื•ื•ืขื ื˜, ืžื™ืกืข ืขื•ื•ืขื ื˜).

ืกืึธืฃ

ื“ืขืจ ืงืึธื“ ืื™ื– ื“ื™ ืกื™ืžืคึผืœืึทืกื˜ ืคึผืจืึทืกื™ื“ื–ืฉืขืจืึทืœ. ืื•ืŸ ื ืึทืจื™ืฉ ื•ื•ื™ ืžื™ืจ. ืึทื–ื•ื™, ืื™ืš ื›ืึทื ืคืขื ืขืŸ ื–ื™ืš ืžื™ื˜ ื“ืขืจ ื”ืึธืคืขื ื•ื ื’ ืึทื– ื›ึผืžืขื˜ ื™ืขื“ืขืจ ื˜ืขื›ื ื™ืงืขืจ ื•ื•ืขื˜ ืงืขื ืขืŸ ืฆื• ืคืึทืจืขื ื“ื™ืงืŸ ื•ื•ืึธืก ืขืจ ื•ื•ื™ืœ. ืื•ืŸ ื“ืึทื ืง ืฆื• ื“ืขื, ื“ืขื ืคึผืจืึธื“ื•ืงื˜ ื•ื•ืขื˜ ื ื™ืฉื˜ ืื•ืžืงื•ืžืขืŸ ืึธืŸ ืฉื˜ื™ืฆืŸ, ื•ื•ื™ ืจื•ื‘ึฟ ืคึฟืึทืจ ืฉืคึผืึทืก.

ื’ื•ื˜ ื’ืœื™ืง!

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’