Aldebaran has asked for the wisdom of the Perl Monks concerning the following question:

Hello monks,

I'm making a series of lists that I want to cobble together and eventually be able to print out with some reasonable spacing and formatting. If the process works, eventually, this particular list of things I fear will grow smaller and more-manageable. For the purpose at hand, I am to read them to a third party when I'm done compiling them, so I will have to have a hard copy that would come from a windows-based machine. I notice that anything I print off now that I've written on this linux partition gets rendered without any carriage returns, so that's definitely an issue. I've decided to handle them as arrays, so I've made my lists to begin with 0:

$ cat fears2.txt 0. Dying 1. Abject poverty 2. Being homeless 3. Cancer, disease $ cat causes2.txt 0. It's everyone's greatest terror, likely laden with pain. 1. My earning power has been decreasing and a regime is on the ascenda +nce that wants to crush my class. 2. It's awful and the result of 1. 3. It runs in the family and can happen spontaneously with appreciable + probability. It's expensive. $

I zip these together with "exists because" between item and same-numbered cause. Here's the caller, callee, and output:

#!/usr/bin/perl -w use strict; use 5.010; use lib "template_stuff"; use steps1; # main data structure my %vars = ( fears => 'fears2.txt', causes => 'causes2.txt', width => 50, ); my $rvars = \%vars; my $return = pop_texts( $rvars ); say "returned was \n $$return"; __END__
package steps1; require Exporter; our @ISA = qw(Exporter); our @EXPORT = qw( pop_texts ); sub pop_texts { use strict; use 5.010; use File::Slurp; my ($rvars) = shift; my %vars = %$rvars; my @fears = read_file( $vars{fears} ); my @causes = read_file( $vars{causes} ); for (@fears) { s/\s+$/ /; } for (@causes) { s/^\d+\./exists because/; } #say "causes are @causes"; my $text1 =''; for my $i ( 0 .. $#causes ) { $text1 = $text1 . $fears[$i] . $causes[$i] . "\n"; } my $reftext = \$text1; return $reftext; } 1;
$ perl fears1.pl returned was 0. Dying exists because It's everyone's greatest terror, likely laden + with pain. 1. Abject poverty exists because My earning power has been decreasing +and a regime is on the ascendance that wants to crush my class. 2. Being homeless exists because It's awful and the result of 1. 3. Cancer, disease exists because It runs in the family and can happen + spontaneously with appreciable probability. It's expensive. $

Q1) How do I change the unwanted capitalization of the beginning letter in the cause?

Q2) How do I constrain the text to the width indicated in the main data structure, and on a windows machine? Should I use a differing file extension?

Thanks for your comment,

Replies are listed 'Best First'.
Re: combining lists, formatting and printing on windows
by Laurent_R (Canon) on Apr 18, 2015 at 11:24 UTC
    Q1: look at the lc and lcfirst functions.

    Q2: look that the length and substr functions. Although some CPAN modules might be able to help.

    Je suis Charlie.

      Alright, thanks, lcfirst works well, but I'll be darned if I can cobble the whole thing together yet. I want now to insert 'Fear of' at the beginnning of the sentence, and I can't accomplish it. It makes no sense to me why it doesn't appear while the numbered match variables do:

      $ ./fears1.pl enter basename for file rt2 returned was 0. dying exists because it's everyone's greatest terror, likely laden + with pain. 1. abject poverty exists because my earning power has been decreasing +and a regime is on the ascendance that wants to crush my class. 2. being homeless exists because it's awful and the result of 1. 3. cancer, disease exists because it runs in the family and can happen + spontaneously with appreciable probability. it's expensive. $

      The caller has changed a bit, but the substitution happens here:

      sub pop_texts { use strict; use 5.010; use File::Slurp; my ($rvars) = shift; my %vars = %$rvars; my @fears = read_file( $vars{fears} ); my @causes = read_file( $vars{causes} ); for (@fears) { s/\s+$/ /; $_ = lc($_); s/^(\d+\. )(.) /$1 Fear of $2/; } for (@causes) { s/^\d+\./exists because/; $_ = lc($_); } #say "causes are @causes"; my $text1 = ''; for my $i ( 0 .. $#causes ) { $text1 = $text1 . $fears[$i] . $causes[$i] . "\n"; } my $reftext = \$text1; return $reftext; }

      I tried putting it in single quotes to no avail....

Re: combining lists, formatting and printing on windows
by soonix (Chancellor) on Apr 18, 2015 at 11:36 UTC

    Easiest answer for Q1 probably is lcfirst, at least as long as none of your causes don't start out with a proper name, which lcfirst also would mercilessly "downsize" :-)

    As for Q2, first thing that comes to my mind is fmt, but perhaps Text::Format suits your needs better. For a solution without CPAN, your function would look for the last spaces before your width, output that substring, and then work on the rest of the string.

    The OS wouldn't make a difference, as long as you use a monospaced font. Otherwise, I'd preferredly output something like RTF (e.g. RTF::Writer), which can be shown/printed by even the older versions of Windows' text processors such as Write; or PDF, which you have heard of :-)

    Update: I thought you'd run perl on the same system where you want the output - then you'd get the correct line endings by default (at least Strawberry does this for me).
    Perhaps the :crlf Layer from PerlIO might help... Looks like the easiest way for you is to use "\r\n" in place of pure "\n" - see the thread hinted to by FreeBeerReekingMonk. But if by "printing" (in the subject) mean "sending to paper", RTF (which is to TeX what PHP is to Perl) is better, because every Windows can print that "out of the box".

      Wow, you researched that well enough to have found my previous struggles with it. I went away from rtf before, but this time I thought I'd try it, getting farther in a day than expected. Caller and callee look like this now:

      #!/usr/bin/perl -w use strict; use 5.010; use lib "template_stuff"; use steps1; say "enter basename for file"; my $word = <>; chomp $word; # main data structure my %vars = ( fears => 'fears2.txt', causes => 'causes2.txt', width => 50, word => $word .'.rtf', ); my $rvars = \%vars; my $return = pop_texts( $rvars ); say "returned was \n $$return"; my $return2 = format_texts( $rvars, $return ); __END__
      sub format_texts { use strict; use 5.010; use RTF::Writer; my ( $rvars, $reftext1 ) = @_; my %vars = %$rvars; my $text1 = $$reftext1; my $rtf = RTF::Writer->new_to_file( $vars{word} ); $rtf->prolog( 'title' => "List of fears" ); $rtf->number_pages; $rtf->print($text1); $rtf->close; return 1; }

      Surprisingly, the rtf file printed out beautifully on windows, albeit without prolog, numbering, and with default margins. This will suffice for me to read it to someone else, so it is good enough for now. RTF Cookbook on CPAN is one of the better resources out there. What puzzles me specifically is how to brook the chasm between the method calls of RTF::Writer and the mark-up language itself. To blurt it out:

      Q1) Where do I put the backslash sequences to create a right margin of 4000 twips?

      Thanks for your comments and attention to detail.

        Where do I put the backslash sequences to create a right margin of 4000 twips?

        I seem to have figured this out by a lot of error and trial:

        sub format_texts { use strict; use 5.010; use RTF::Writer; my ( $rvars, $reftext1 ) = @_; my %vars = %$rvars; my $text1 = $$reftext1; my $rtf = RTF::Writer->new_to_file( $vars{word} ); $rtf->prolog( 'title' => "List of fears", ); $rtf->number_pages; $rtf->paragraph(\'\qc\f0\fs120\b ', "Fears"); $rtf->paragraph(\'\ri3000\li-500\f0\fs30\b0\ql',$text1); $rtf->close;

        This creates a centered, oversized headline and then sets a left indent of negative 500 twips (moving it left a centimeter or so), and a right indent of 3000 twips, which, with the rather large default margins creates the space on the right side of the page that I wanted. Screenshot of output on Tinypic

        I was wrong to expect the title to print out: it's not supposed to. I was also wrong that the page number didn't print out. The reference that got me over the hump on rtf syntax was Sean Burke's summary of rtf syntax . Also informative was MS specification of rtf on sourceforge

        Still puzzled why "Fear of" doesn't get inserted with this substitution:

        for (@fears) { s/\s+$/ /; $_ = lc($_); s/^(\d+\. )(.) /$1 Fear of $2/; }
Re: combining lists, formatting and printing on windows
by FreeBeerReekingMonk (Deacon) on Apr 18, 2015 at 12:57 UTC

    1. Read this: Carrige Return and Line Feed in Perl.
    2. Attempt either to print to DOS ^M format like so:

    print "hello\r\n", (you can also play with $/ but I do not recommend it)

    Or, use dos2unix and unix2dos on your unix machine (hopefully they are installed)

      And just an additional note in the interoperability department, I install Cygwin anywhere I am allowed to on the Windows side and ensure those utilities are available on either side of the pipe.

      Or, use dos2unix and unix2dos on your unix machine (hopefully they are installed)
      If they are not installed (for example, they don't exist on the AIX platforms used at my workplace), it is possible and easy to create some aliases using Perl oneliners to add or remove the \r character. For example:

      dos2unix:

      perl -pi -e 's/\r//g;' <filename>
      unix2dos:
      perl -pi -e 's/\n/\r\n/g;' <filename>

      Je suis Charlie.