A piggy bank of commands, fixes, succinct reviews, some mini articles and technical opinions from a (mostly) Perl developer.

Windows macro recorders

List:

  • EZ Macros - good but very old
  • AutoHotkey - very good
  • AutoMate - ?
  • Workspace Macro - ?
  • Auto Macro Recorder - not intuitive, and I don't like the interface. Looks like Windows 3.1


How to set the follow up flag in Outlook 2007

Sometimes I click on the 'follow up' flag icon for an email in the inbox, and nothing happens. Or there's a message to say the flag was set but it doesn't change colour and doesn't appear in the to do list.

Workaround: Click on the follow up flag for a different email, then clear it, then click back on the first one.

Manual automatic accessors in Perl

If you don't have Moose, Mo* or Class::Accessor:

package Foo;

=head1 SYNOPSIS

    my $f = Foo->new(
        bar => 'rab',
        qux => 'xuq',
    );

=cut

use constant ACCESSOR_MAP => {
    'get_bar' => 'bar',
    'get_qux' => 'qux',
};

use constant ACCESSOR_ITEM => qw(ping ting zing);

sub new {
    my ( $c, %args ) = @_;
    my $class = ref $c || $c;
    bless {%args}, $class;
}

sub __mk_accessor {
    my ( $c, $name, $key ) = @_;
    $key ||= $name;
    my $pkg = ref $c || $c;
    my $sym = join( '::', $pkg, $name );
    no strict 'refs';
    *{$sym} = sub {
        my ($self) = @_;
        $self->{$key};
    };
}

# set up ping(), ting(), zing()
__PACKAGE__->__mk_accessor($_) foreach __PACKAGE__->ACCESSOR_ITEM;

# set up get_bar(), get_qux()
for my $k ( keys %{ __PACKAGE__->ACCESSOR_MAP } ) {
    my $v = __PACKAGE__->ACCESSOR_MAP->{$k};
    __PACKAGE__->__mk_accessor( $k, $v );
}

# not tested

Show tabs in GNU screen

~/.screenrc

hardstatus string "%{= g} %{= w}%-Lw%{=r}%n%f* %t%{-}%+LW"

(source)

See also byobu, which is one step better than screen.


Determine differences in an array with Perl

Not just checking whether or not two arrays are the same, but finding out how they are different, i.e. what has been added and what has been taken away:

use Algorithm::Diff 'sdiff';
use Data::Dumper;

my @a = (1, 2, 3, 4);
my @b = (2, 3, 4, 5);

my @c = sdiff(\@a, \@b);

print Dumper(\@c);

Output:

$VAR1 = [
          [ '-',  1, '' ],
          [ 'u',  2,  2 ],
          [ 'u',  3,  3 ],
          [ 'u',  4,  4 ],
          [ '+', '',  5 ]
        ];

You can see that 1 has a '-' indicating it has been removed, and 5 has a '+' indicating it has been added. The other items have a 'u', indicating they are unchanged.

(source)

However, if comparing (a b c) with (c b a), Algorithm::Diff::sdiff will fail to realise that nothing has been added or removed. A simpler algorithm might be:

sub determine_changes {
    my ($old, $new) = @_;

    # Compare two lists
    my %old_lookup = map { $_ => 1 } @$old;
    my %new_lookup = map { $_ => 1 } @$new;
    my @added = grep { ! $old_lookup{$_} } @$new;
    my @removed = grep { ! $new_lookup{$_} } @$old;

    my @changes;
    push @changes, map { { item => $_, operation => 'add'    } } @added;
    push @changes, map { { item => $_, operation => 'remove' } } @removed;

    my @sorted_changes = sort { $a->{item} cmp $b->{item} } @changes;
    return \@sorted_changes;
}