Last active
December 28, 2017 09:40
-
-
Save unclechu/ef3e19cc902f015ce7f484ae685bc74c to your computer and use it in GitHub Desktop.
kbd.pl6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env perl6 | |
| use v6.c; | |
| close $*IN; | |
| my $HOME := IO::Path.new: '/home/unclechu'; | |
| my $BINDIR := $HOME.child: '.local/bin'; | |
| my $LOCKFILE := %*ENV{'HOME'}.IO.child: '.kbd.pl6.lock'; | |
| sub MAIN( Bool :f(:$force) = False | |
| , Bool :v(:$verbose) = False | |
| , Bool :$internal-bg = False | |
| ) | |
| { | |
| my &s = &safe-spawn.assuming: $verbose; | |
| if $internal-bg.not { | |
| if !$force && $LOCKFILE.f && how-old-is-lockfile() < 60 { | |
| note "Couldn't start, lock file exists: '$LOCKFILE'!\n" | |
| , "Start with [-f|--force] to force start."; | |
| exit 1; | |
| } else { | |
| $LOCKFILE.IO.open(:w).close; | |
| } | |
| s True, ( | |
| qw<sudo -->, | |
| $HOME.child("dev/apple-keyboard/apply-apple-keyboard-configs.sh").Str | |
| ); | |
| s True, qw<setxkbmap -layout us,ru -option grp:shifts_toggle>; | |
| s True, qw<numlockx off>; | |
| s True, qw<numlockx on>; | |
| "'$*PROGRAM' will do last part in background…".note if $verbose; | |
| given Proc::Async.new( | |
| :w, $*EXECUTABLE, $*PROGRAM, |@*ARGS.append: '--internal-bg') | |
| { .start; .close-stdin; exit 0; } | |
| } else { | |
| "'$*PROGRAM' is waiting for promises…".note if $verbose; | |
| await Promise.allof( | |
| start { | |
| "'$*PROGRAM' is restarting 'xbindkeys' in own thread…".note if $verbose; | |
| s False, qw<killall xbindkeys>; | |
| await Promise.in: 1; | |
| s True, qw<xbindkeys>; | |
| "'$*PROGRAM' is done with restarting 'xbindkeys'.".note if $verbose; | |
| }, | |
| start { | |
| "'$*PROGRAM' is restarting 'xlib-keys-hack' in own thread…".note | |
| if $verbose; | |
| s False, qw<killall xlib-keys-hack.sh>; | |
| s False, qw<killall xlib-keys-hack>; | |
| await Promise.in: 1; | |
| walking-zombie $verbose, $BINDIR.child: 'xlib-keys-hack.sh'; | |
| "'$*PROGRAM' is done with restarting 'xlib-keys-hack'.".note if $verbose; | |
| } | |
| ); | |
| "'$*PROGRAM' is done waiting for promises.".note if $verbose; | |
| "'$*PROGRAM' is removing its lockfile: '$LOCKFILE'…".note if $verbose; | |
| $LOCKFILE.unlink; | |
| "'$*PROGRAM' is done.".note if $verbose; | |
| } | |
| } | |
| ### helpers ### | |
| sub walking-zombie(Bool $verbose, *@run-args) { | |
| my $cmd = @run-args.join: ' '; | |
| "'$*PROGRAM' is spawning zombie: '$cmd'…".note if $verbose; | |
| given Proc::Async.new(:w, |@run-args) | |
| { .stdout.tap.close; .stderr.tap.close; .start; .close-stdin; } | |
| "'$*PROGRAM' is done with spawning zombie: '$cmd'…".note if $verbose; | |
| } | |
| sub safe-spawn(Bool $verbose, Bool $warn, *@run-args) { | |
| my $timeout := 2; | |
| my $cmd = @run-args.join: ' '; | |
| ("'$*PROGRAM' is spawning: '$cmd'…").note if $verbose; | |
| my &runit = sub (Proc::Async $proc) { | |
| my $promise = $proc.start; | |
| $proc.close-stdin; | |
| return ($proc, $promise); | |
| }; | |
| try { | |
| my ($proc, $promise) = runit Proc::Async.new(:w, |@run-args); | |
| await Promise.anyof( | |
| $promise, | |
| Promise.in($timeout).then: { | |
| my $what = (@run-args[0] == 'killall') ?? 'dying' !! 'killing it'; | |
| "'$*PROGRAM' command '$cmd' is out of time, $what…".note if $verbose; | |
| $proc.kill: SIGKILL; | |
| if @run-args[0] == 'killall' { | |
| my @args = @run-args; | |
| @args.shift; | |
| @args.prepend('killall', '-KILL'); | |
| $cmd = @args.join: ' '; | |
| "'$*PROGRAM' is spawning new killing command '$cmd'…".note | |
| if $verbose; | |
| my ($proc, $promise) = runit Proc::Async.new(:w, |@args); | |
| await Promise.anyof( | |
| $promise, | |
| Promise.in($timeout).then: { | |
| "'$*PROGRAM' command '$cmd' is out of time, dying…".note | |
| if $verbose; | |
| $proc.kill: SIGKILL; | |
| exit 1; | |
| } | |
| ); | |
| } else { | |
| exit 1; | |
| } | |
| } | |
| ); | |
| CATCH { | |
| default { | |
| "'$*PROGRAM' is failed spawning: '$cmd', error: $_.".note if $verbose; | |
| warn $_ if $warn; | |
| } | |
| } | |
| } | |
| "'$*PROGRAM' is done with spawning: '$cmd'.".note if $verbose; | |
| } | |
| sub how-old-is-lockfile() of Duration { | |
| (run 'stat', $LOCKFILE, :out).out.slurp ~~ /Modify\:\s (.+?) \n/; | |
| $_ = $0.split(' '); | |
| $_ = "$_[0]T" ~ $_[1].split('.')[0] ~ $_[2].subst(/(\d\d)(\d\d)/, {"$0:$1"}); | |
| DateTime.now - DateTime.new: $_; | |
| } | |
| # vim:et:ts=2:sts=2:sw=2: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment