#! /usr/bin/perl # make-addresss-book.pl # process an abook file and produce LaTeX table body (and optionally, # the headers, and actual tabular/longtable environment) for a printed # address book. # Put header and footer files into a directory in your home directory # with a name the same as this file, minus the extension .pl, but # starting with a dot. # Copyright (C) 2005 Nick Urbanik # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. use warnings; use strict; use File::Basename; #use Unicode::String; use constant HEADER => "address-book-header.tex"; use constant FOOTER => "address-book-footer.tex"; my $config_dir = "$ENV{HOME}/.@{[basename $0, '.pl']}"; sub usage() { my $prog = basename $0; print < qw/ address address2 city state zip country /; use constant EMAIL_FIELDS => qw/ email email2 email3 email4 /; foreach ( ADDR_FIELDS ) { push @address, $data->{$_} if exists $data->{$_}; } unless ( @address ) { foreach ( EMAIL_FIELDS ) { push @address, $data->{$_} if exists $data->{$_}; } } unless ( @address ) { push @address, $data->{notes} if exists $data->{notes}; } return "" unless @address; return join ", ", @address; } sub get_phones(\%) { my $data = shift; my @phones; use constant PHONE_KEYS => qw/ phone mobile workphone fax /; my %abbreviations = ( phone => "h: ", mobile => "m: ", workphone => "w: ", fax => "f: " ); foreach ( PHONE_KEYS ) { push @phones, $abbreviations{$_} . $data->{$_} if exists $data->{$_}; } return join ", ", @phones; } sub read_header_or_footer($) { my ( $file_to_insert ) = @_; if ( -r $file_to_insert ) { open HEAD_OR_FOOT, '<', $file_to_insert or die "unable to open $file_to_insert: $!"; print ; close HEAD_OR_FOOT or die "unable to close $file_to_insert: $!"; } } my $found; foreach ( @ARGV ) { $found = 1 if -r $_; } usage unless $found; read_header_or_footer "$config_dir/@{[HEADER]}"; { # paragraph mode; one record is one paragraph. local $/ = ""; while ( <> ) { chomp; my @lines = split "\n", $_; next unless ( shift @lines ) =~ /^\[\d+\]$/; my %data; foreach ( @lines ) { # convert from utf8 to latin1, which LaTeX can handle: #$_ = Unicode::String::utf8($_)->latin1(); my ( $key, $field ) = split /=/, $_, 2; $data{$key} = $field; } my $address = get_addresses %data; my $phone = get_phones %data; no warnings; foreach my $funny_char ( qw!\\\\ \$ _ & #! ) { use warnings; $address =~ s!$funny_char!\\$funny_char!g; # Some email addresses are in a long, comma separated list. # Break them up with spaces so LaTeX can wrap them $address =~ s/,(\S)/, $1/g; $phone =~ s!$funny_char!\\$funny_char!g; $data{name} =~ s!$funny_char!\\$funny_char!g; if ( not $phone and exists $data{notes} and $data{notes} ne $address ) { $phone = $data{notes}; } } print "$data{name} & $phone & $address \\\\\n\\hline%\n"; } } read_header_or_footer "$config_dir/@{[FOOTER]}";