Happy Programmers Day

Today is Programmers Day! To celebrate, I just tried my hand at a Rust program. Rust is a fairly new programming language that has been in development for five or so years and just had its 1.0 release earlier this year.

If we wanted to check if today was Programmers Day, we’d probably discover the familiar struct Tm in the time crate. Just as in C, it has tm_yday, which is just what we need. To use it, we could start a new project with Cargo.

$ cargo new programmers_day --bin

Now add

[dependencies]
time = "0.1"

to our Cargo.toml and the following in our src/main.rs

extern crate time;

fn main() {
    if time::now().tm_yday == 255 {
        println!("Happy Programmers Day!");
    } else {
        println!("Ho hum, just another day.");
    }
}

et voilà!

$ cargo run
   Compiling programmers_day v0.1.0 (file:///home/tim/rust/programmers_day)
     Running `target/debug/programmers_day`
Happy Programmers Day!
Advertisements
Happy Programmers Day

Say time

This morning, I read on Hacker News that, “You’ll be more productive if your computer announces the time.” The link was to a click-baity article on a number of “productivity hacks,” the first of which was, “Have your computer announce the time.” As is often the case, this article comes from a world that contains only two kinds of computers. “Here’s how to do it on a Mac, and here are instructions for Windows users.”

My machine runs Linux, so I wondered how I might have it announce the time.

It’s easy to get the current time with GNU date

$ date
Sun Sep  6 14:31:30 EDT 2015

and to synthesize some simple text with espeak

$ echo "Hello, world!" | espeak

so a first pass at a solution might be

$ date | espeak

But that’s not very satisfying. A human knows what that string means, but espeak just reads it off as is, “sun sep six…”

Time::Human

Turns out CPAN already contains a Perl module which does exactly what we need: Time::Human.

$ perl -MTime::Human -E 'say "The time is now ", humanize(localtime)'
The time is now a little after half past two in the afternoon

That string is much more suitable for piping to espeak!

$ perl -MTime::Human -E 'say "The time is now ", humanize(localtime)' | espeak

Not bad!

Festival

Espeak sounds okay, but perhaps we can do better. There’s another synthesizer called Festival, which sounds a little smoother. And there’s even a lite version, written in C.

$ sudo apt-get install flite
$ perl -MTime::Human -E 'say "The time is now ", humanize(localtime)' | flite

Flite has a number of voices from which to choose. The one that seems to sound the best for this is awb_time

$ perl -MTime::Human -E 'say "The time is now ", humanize(localtime)' | flite -voice awb_time

Nice!

Cron

Now, how to get it to say the time automatically every hour? Cron. I edit my personal crontab file with

crontab -e

and add an entry like so

0 * * * * /usr/bin/perl -MTime::Human -E 'say "The time is now ", humanize(localtime)' | flite -voice awb_time

That will invoke that one-liner at the top of every hour.

Normally, I use plenv to install Perl in my own space, so I installed Time::Human with

cpanm Time::Human

To get the cron job to work with /usr/bin/perl, I had to install Time::Human against the system Perl with

sudo apt-get install libtime-human-perl

Now my system tells me the time every hour on the hour! We’ll see if that helps my productivity.

Random voice

Here’s a little Perl script I wrote to choose from all of flite’s voices randomly

#!/usr/bin/env perl

use v5.20;
use warnings;
use Time::Human;

my $time_string = "The time is now " . humanize(localtime);

die "$time_string\n" if @ARGV;

my $voices = `flite -lv`;

my @voices = split ' ', $voices =~ s/^Voices available: //r;

my $voice = $voices[rand @voices];

system "flite -voice $voice -t '$time_string'";

I didn’t end up using it because I thought the awb_time voice sounded better and I wanted to use it all the time.

Say time