Skip to content

Instantly share code, notes, and snippets.

@siers
Last active April 30, 2017 06:04
Show Gist options
  • Save siers/19981104ca7223361842 to your computer and use it in GitHub Desktop.
Save siers/19981104ca7223361842 to your computer and use it in GitHub Desktop.
a more natural alarm clock command line interface
#!/usr/bin/env ruby
require 'time'
def die(str)
$stderr.puts str
exit
end
def usage
die "Usage: nap { for <float>[<h|m|s>] | until <date(1) parsable datestr> | cycles [<int>[+<int>]] }" +
"\ne.g. nap for 3h\n nap until 10AM\n nap cycles 4\n " +
"nap cycles 4+10 # 10 minutes to brush teeth"
end
def hourminutes(hours)
wholes = hours.to_i
minutes = (hours - hours.to_i) * 60
"#{ wholes }:#{ ("0" + minutes.to_i.to_s)[-2..-1] }"
end
def kind_for(time)
aliases = {'m' => 60, 'h' => 3600, 's' => 1}
prefix = aliases[(time.match('[hms]$') || ['s'])[0]]
yield "# date format bogus" unless time.match(/^\d+(\.\d+)?([hms])?$/)
"sudo rtcwake -m mem -s #{ time.to_f.*(prefix).to_i }"
end
def successfully(args)
errors, pipe = IO.pipe
IO.popen(args, err: pipe) do |p| p.read end.tap do
pipe.close
die errors.read unless $?.success?
end
end
def kind_until(time)
date = successfully(%w{date -d} + [time])
secs = successfully(%w{date -d} + [time] + %w{+%s}).to_i
hours = (((secs.to_i - Time.now.to_i) / 36) / 100.0)
yield "# %s hours" % hourminutes(hours) if (0.40..60).include? hours
yield "# #{ date }"
"sudo rtcwake -m mem -t #{ secs }"
end
def kind_cycles(n = nil, &block)
# Print time, if n = nil.
# n = '1' -> sleep one cycle + 14 minutes
# n = '1+20' -> sleep one cylce + 14 minutes + 20 minutes to brush teeth
gen = proc do |i, j|
cycle = 3600 * 3 / 2
tts = 14 * 60 # a joke on Time To Live
(Time.now + (cycle * i + tts + (j || 0) * 60)).strftime('%H:%M')
end
enough = 6
times = (1..enough).map { |i| gen.call i }
if n
m, o = n.split('+').map(&:to_i)
unless (1..enough).include? m
yield "# only cycles 1 through #{ enough } are meant to be used"
end
kind_until(gen.call(m, o), &block)
else
yield "# according to http://sleepyti.me"
yield "# you should wake up at:"
yield("# " + times.join(', '))
end
end
kind = ARGV[0]
timedescr = ARGV[1..-1]
if ARGV.length == 2
usage if !kind.match(/^(until|for|cycles)$/)
elsif ARGV.length == 1
usage if kind != 'cycles'
else
usage
end
cmd = send(:"kind_#{ kind }", *timedescr) { |info| $stderr.puts info }
puts cmd if cmd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment