Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Console Output Formatting Help Required

by tarunmudgal4u (Sexton)
on Sep 27, 2013 at 07:06 UTC ( [id://1055937]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

I want some help regarding console output formatting. As of now, I'm using print function rather printf. I don't know if printf can solve my problem.

I'm printing some informative message e.g "installing LUA.." and once this task gets over, based on the status, I print "done" or "failed". Now, the issue is, this done/failed status message is printed in scattered way (as first print size varies as per informative message length). How can I print all done/failed in one column from top to bottom (or if writing it to right side of console possible regardless of left side message size)?

Below is the output snippet I get as of now -

Mapping a drive to build machine 10.211.32.254.. done Mapped to V drive Deleting TestHarness_LUA directory.. done Deleting TestHarness_LUA-distribution.zip file.. done Copying TestHarness_LUA-distribution.zip from mapped V drive.. +done

Below is the output I'm looking for -

Mapping a drive to build machine 10.211.32.254.. done Mapped to V drive Deleting TestHarness_LUA directory.. done Deleting TestHarness_LUA-distribution.zip file.. done Copying TestHarness_LUA-distribution.zip from mapped V drive.. done

Please let me know your suggestions.

Replies are listed 'Best First'.
Re: Console Output Formatting Help Required
by mtmcc (Hermit) on Sep 27, 2013 at 07:34 UTC
    You could use printf (for a good tutorial, see Using (s)printf()), as in:

    #! /usr/bin/perl -w use strict; use warnings; printf("%-60s", 'this is the first message...'); print STDOUT "done\n"; printf("%-60s", 'this is the second message of different length...'); print STDOUT "done\n";

    The disadvantage is that it is a fixed space distance, and rolls around when the terminal window is too narrow...

      thanks for the help. But, it solves the problem partially. When the size of first field exceeds from 60, then alignment changes.

      I'm looking for something that, even if first field size exceeds, second field alignment should be maintained and first field text should be extended to next line.

        Hi, I've written two methods printR and printL to write text on the right side and left side respectively on the screen. It's working fine.

        sub printL { my $str = shift; my $widthL = 60; #my $widthR = 80; my @strWrap = (); for (1 .. int (length $str)/$widthL ) { push @strWrap, substr($str, 0, $widthL-1, '')."\n"; } #push @strWrap, $str; print "@strWrap"; printf ("%-80s", "$str"); } sub printR { if (@_ == 1){ my $status = shift; print "$status\n"; } elsif (@_ == 2){ my $status = shift; my $msg = shift; print "$status\n$msg\n"; } }

        Now there is one problem. In my code I've used multiple printL methods consecutively. So first printL writes at the left side of the screen and leaves the cursor at that place only and next consecutive printL continues from there. that's not what I want.

        I have a solution for this. I can find the current cursor coordinates and if x coordinate is greater than 0, next printL will add newline char at the beginning of the string. But, how to find current cursor position, I don't know. Can somebody help me with this?

        Perl tell function doesn't help me with this as it returns the position in bytes. Any suggestion would also fine.

Re: Console Output Formatting Help Required
by kcott (Archbishop) on Sep 27, 2013 at 08:47 UTC

    G'day tarunmudgal4u,

    Without knowing exactly how the data is generated, it's a little difficult to give a clear answer on how to format it. While you do say there's message/status pairs, that doesn't address 'Mapped to V drive' (line 2) which doesn't have a status nor the source or importance of the blank lines you show.

    In the code below, I've put the data you've posted into an Array of Arrays and processed that. You should be able to adapt the technique I've used for your needs.

    #!/usr/bin/env perl use strict; use warnings; my @messages = ( ['Mapping a drive to build machine 10.211.32.254..', 'done'], ['Mapped to V drive'], [], ['Deleting TestHarness_LUA directory..', 'done'], [], ['Deleting TestHarness_LUA-distribution.zip file..', 'done'], [], ['Copying TestHarness_LUA-distribution.zip from mapped V drive..', + 'done'], ); for my $msg (@messages) { for (scalar @$msg) { $_ == 0 && do { print "\n"; last }; $_ == 1 && do { print_long_line($msg->[0]); print "\n"; last } +; $_ == 2 && do { print_long_line($msg->[0]); print "$msg->[1]\n +" }; } } sub print_long_line { print join "\n" => map { sprintf "%-55s" => $_ } shift =~ /(.{1,52 +})\b\s*/g; }

    Output:

    $ pm_format_long_line_output.pl Mapping a drive to build machine 10.211.32.254 done Mapped to V drive Deleting TestHarness_LUA directory done Deleting TestHarness_LUA-distribution.zip file done Copying TestHarness_LUA-distribution.zip from mapped V drive done

    -- Ken

Re: Console Output Formatting Help Required
by hdb (Monsignor) on Sep 27, 2013 at 07:44 UTC

    For a fixed width $width, you want to wrap your text at that width, more precisely at a blank space just before that width. This can be achieved by a regex like this s/(.{1,$width}\s/$1\n/g.

    You then want to pad the last line with blanks to that specified width and then print done.. The padding can be achieved by using the following expression: $1.(' 'x($width-length($1)))."\n" instead of the one above. This would pad each line with blanks but that should not be a problem. In order to make it work, you have to specify /e in your substitution operator.

Re: Console Output Formatting Help Required
by wjw (Priest) on Sep 27, 2013 at 07:29 UTC
    Stuck my foot in it... should have read the doc myself... guess that is used primarily to write to a file handle. (Tis what I get for being at this hour) Sorry for the chaff...

    ...figure I might take a gander at Format.

    Been a long time since I used it, but seem to recall being able to tune things nicely using it...

    But it has been a long time... :-)

    • ...the majority is always wrong, and always the last to know about it...
    • ..by my will, and by will alone.. I set my mind in motion

      I see no reason not to use format for this case. eg:

      #!/usr/bin/perl -Tw use strict; use warnings; my @foo = ( "Mapping a drive to build machine 10.211.32.254..\rMapped to V dri +ve", 'Deleting TestHarness_LUA directory..', 'Deleting TestHarness_LUA-distribution.zip file..', 'Copying TestHarness_LUA-distribution.zip from mapped V drive..' ); for (@foo) { my $status = "done."; format STDOUT = ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ^<<<<< $_, $status . write while $_; }
      Stuck my other foot in it... I was wrong about being wrong. Thanks for pointing that out!

      Perhaps I should stick with my first instincts... and try them before posting. Lesson learned. And thank for the code. If I had done that to begin with I would be tasting two less samples of shoe leather. Have a great day!

      • ...the majority is always wrong, and always the last to know about it...
      • ..by my will, and by will alone.. I set my mind in motion

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1055937]
Approved by hdb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2024-03-29 10:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found