Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Avoid warnings while formatting with repeated format lines

by hexcoder (Curate)
on Aug 24, 2022 at 11:47 UTC ( [id://11146361]=perlquestion: print w/replies, xml ) Need Help??

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

Hi dear brothers,

finally I had a task for the format/write functionality in Perl. While toying around with Perl 5.26.2, I could not find a way however to feed multiple field values into a repeated format line without getting warnings. Probably I am doing something wrong, but what?

Thanks for any insights!

use strict; use warnings; use open ':locale'; sub print_data { my ($name, @f); format START = .===================. |@<<<<<<| | $name | | | .=======.===========. |@<<<<<<| @<</@>> |~~ splice( @f, 0, 3 ) .=======.===========. . binmode STDOUT, ':raw:crlf'; my $ofh = select(STDOUT); $~ = "START"; $name = 'TAB'; @f = ('Step2', 0, 4, 'Step3', 4, 4); write; } print_data;
gives
perl -w .\TryFormat.pl Not enough format arguments at .\TryFormat.pl line 16. Not enough format arguments at .\TryFormat.pl line 16. Not enough format arguments at .\TryFormat.pl line 16. .===================. |TAB | | | | | .=======.===========. |Step2 | 0 / 4 | |Step3 | 4 / 4 | .=======.===========.

Replies are listed 'Best First'.
Re: Avoid warnings while formatting with repeated format lines
by Athanasius (Archbishop) on Aug 24, 2022 at 14:04 UTC

    Hello hexcoder,

    I don’t know much about Perl’s format command, but a search found Re^2: Use of uninitialized value in formline? which seems to have the answer:

    use strict; use warnings; use open ':locale'; sub print_data { my ($name, @f); format START = .===================. |@<<<<<<| | $name | | | .=======.===========. |@<<<<<<| @<</@>> |~~ shift(@f) || '', shift(@f) || '', shift(@f) || '' .=======.===========. . binmode STDOUT, ':raw:crlf'; my $ofh = select(STDOUT); $~ = "START"; $name = 'TAB'; @f = ('Step2', 0, 4, 'Step3', 4, 4); write; } print_data;

    Output:

    0:01 >perl 2079_SoPW.pl .===================. |TAB | | | | | .=======.===========. |Step2 | / 4 | |Step3 | 4 / 4 | .=======.===========. 0:01 >

    Looks like a limitation of the format function: it wants to see a separate argument for each placeholder, and it doesn’t like undef.

    Anyway, hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      If the Perl in question is at least 5.10, your solution could use shift(@f) // '', shift(@f) // '', shift(@f) // '' to duplicate the original output.

      Thanks a lot, Athanasius!

      I did some super search before posting, but obviously I missed this one. This special handling should be added to the official documentation, I think!

      Greetings, hexcoder
Re: Avoid warnings while formatting with repeated format lines
by kcott (Archbishop) on Aug 24, 2022 at 16:30 UTC

    G'day hexcoder,

    Here's a generic solution to your issue.

    #!/usr/bin/env perl use strict; use warnings; my $multi_data_1 = [qw{ 123 456 789 0 _-=+ qwe rty uio p {[]} asd fgh jkl :; '" zxc vbn m <>?/ }]; print_table(MULTI_COL => 'QWERTY Keyboard', $multi_data_1, 5); my $step_data = [qw{Step2 0 4 Step3 4 4}]; print_table(STEP => 'TAB', $step_data, 3); my $multi_data_2 = [ 'skip1', '', 'skip2', '', '', 'skip2', '', '', 'skip1', '', 'skip', 'rest', ]; print_table(MULTI_COL => 'Skipped Cells', $multi_data_2, 5); sub print_table { my ($form, $title, $all_data, $cols) = @_; format STEP = .===================. |@<<<<<<<<<<<<<<<<< | $title .=======.===========. |@<<<<<<| @<</@>> |~~ get_col_data($all_data, $cols) .=======.===========. . format MULTI_COL = /=======================================\ | @|||||||||||||||||||||||||||||||||||| | $title |---------------------------------------| | @<<<< | @<<<< | @<<<< | @<<<< | @<<<< |~~ get_col_data($all_data, $cols) \=======================================/ . local $~ = $form; write; return; } sub get_col_data { my ($all_data, $cols) = @_; my @cols_data = splice @$all_data, 0, $cols; return @cols_data, ('') x ($cols - @cols_data); }

    Output:

    /=======================================\ | QWERTY Keyboard | |---------------------------------------| | 123 | 456 | 789 | 0 | _-=+ | | qwe | rty | uio | p | {[]} | | asd | fgh | jkl | :; | '" | | zxc | vbn | m | <>?/ | | \=======================================/ .===================. |TAB | .=======.===========. |Step2 | 0 / 4 | |Step3 | 4 / 4 | .=======.===========. /=======================================\ | Skipped Cells | |---------------------------------------| | skip1 | | skip2 | | | | skip2 | | | skip1 | | | skip | rest | | | | \=======================================/

    Update: In get_col_data(), I changed three instances of @step_data to @cols_data. The output is unchanged. The original @step_data was from when I was initially testing with the OP's format (with Step2 & Step3). The change is in line with my opening statement that this was a "generic solution".

    — Ken

      Thanks kcott!

      That is appreciated a lot! I will definitively bookmark this solution for later reference.

      What would also be really cool, is using format also dynamically in the horizontal direction. That would probably mean to use eval and hook into the lowlevel formatting, I guess.

      hexcoder
        What would also be really cool, is using format also dynamically in the horizontal direction.

        I'll just mention that Text::Table exists so that you (and I) don't have to wrestle with such things. OTOH, if you were intent on a challenge ...


        🦛

        "What would also be really cool, is using format also dynamically in the horizontal direction. That would probably mean to use eval and hook into the lowlevel formatting, I guess."

        You would need eval but shouldn't need to mess around with *STEP{FORMAT} or anything like that. There's an example in "perlform: NOTES"; search for "The truly desperate can ...". :-)

        I used to use format quite regularly 20-25 years ago (probably a couple of times a week for generating all manner of reports). Although fairly proficient back then, I often encountered pulling-my-hair-out-in-frustration situations. These days, I'd generally look to other solutions; I don't think I've used it this millenium.

        — Ken

Re: Avoid warnings while formatting with repeated format lines
by Anonymous Monk on Aug 24, 2022 at 15:03 UTC

    I also am not a serious user of format, and it may be that it does not get as much love lately as it should. Since the format does what you want, another way to handle the problem is just to suppress the warning:

    use strict;
    use warnings;
    use open ':locale';
    
    sub print_data
    {
    my ($name, @f);
    
      do {
        no warnings 'syntax';
        format START =
    .===================.
    |@<<<<<<|           |
    $name
    |       |           |
    .=======.===========.
    |@<<<<<<|  @<</@>>  |~~
    splice( @f, 0, 3 )
    .=======.===========.
    .
      };
      binmode STDOUT, ':raw:crlf';
      my $ofh = select(STDOUT);
      $~ = "START";
      $name = 'TAB';
      @f = ('Step2', 0, 4, 'Step3', 4,   4);
      write;
    }
    
    print_data;
    

    produces

    .===================.
    |TAB    |           |
    |       |           |
    .=======.===========.
    |Step2  |  0  /  4  |
    |Step3  |  4  /  4  |
    .=======.===========.
    

    without any warnings. The no warnings ... and format ... were enclosed in a do { ... } simply to limit the scope of the no warnings .... An explicit use warnings 'syntax' after the format would have done the same.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (2)
As of 2024-04-26 03:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found