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

Hi

I want to transform a hash definition like this:

%some_hash = ( key => "value1", larger_key => "value2", even_larger_key => "value3", );
to something like this:
%some_hash = ( key => "value1", larger_key => "value2", even_larger_key => "value3", );
i.e. make the fat commas line up in perl source code.

By "transform" I mean a perl-script that takes the key-value lines from stdin and prints the prettyfied versions to stdout so I can call it from vim.

As this seems to be a quite natural requirement I assume some module does things like that already (lazyness is a virtue right).

So could someone please point me to such a modules (I am NOT looking for someone to code this for me).

Replies are listed 'Best First'.
Re: prettyfy hashes
by james28909 (Deacon) on Apr 03, 2016 at 01:49 UTC

    Not sure if it is what you specifically want, but you could check out perltidy. It cleans up source code pretty good and is configurable.

Re: prettyfy hashes
by BrowserUk (Patriarch) on Apr 03, 2016 at 02:13 UTC

    #! perl -sw use strict; use List::Util qw[ max ]; my $first = <>; my @ugly = <>; my $last = pop @ugly; my @bits = map[ m[(^\s+)(\S+)\s*=>\s*(\S+),\n] ], @ugly; my $largest = max( map{ length( $_->[1] ) } @bits ); print $first; printf "%s%-${largest}s => %s,\n", @$_ for @bits; print $last;

    Output:

    C:\test>1159396 C:\test>1159396 %some_hash = ( key => "value1", larger_key => "value2", even_larger_key => "value3", ); ^Z %some_hash = ( key => "value1", larger_key => "value2", even_larger_key => "value3", );

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: prettyfy hashes
by choroba (Cardinal) on Apr 03, 2016 at 02:07 UTC
    > so I can call it from vim.

    What a pity! In Emacs, you can use align-regex , which I usually bind to C-x l . I can then just select the region and press C-x l => Enter and voilą!

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      I normally move the cursor to the last => and type M-x align-current .

      One day I'll automatise it to happen with each auto indent. ..

      FWIW I seem to remember that perltidy can't do this.

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

        It aligns the assignment symbol = for me, too, which I don't want. Do you have any special align-rules-alist to prevent that?

        # here, instead of here # v V my %periods = (Mercury => { orbital => 0.24, rotation => +58.64 }, Venus => { orbital => 0.62, rotation => -243.02 }, Earth => { orbital => 1.00, rotation => 1.00 }, Mars => { orbital => 1.88, rotation => 1.03 }, Jupiter => { orbital => 11.86, rotation => 0.41 }, Saturn => { orbital => 29.46, rotation => 0.43 }, Uranus => { orbital => 84.01, rotation => -0.72 }, Neptune => { orbital => 164.8, rotation => 0.67 }, );

        Moving the structure from the assignment line doesn't help:

        my %periods = ( Mercury => { orbital => 0.24, rotation => 58.64 }, Venus => { orbital => 0.62, rotation => -243.02 }, # ...

        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      > In Emacs, you can use align-regex , which I usually bind to C-x l . I can then just select the region and press C-x l => Enter and voilą!

      There is room for much improvement...

      1. selecting the region:

      a combination of backward-up-list and mark-sexp will select the surrounding structure (repeating will extend the selection till statement (ie. ';') boundary.

      (please note that cperl-mode injects here some semantic knowledge about the code's structure which can't be reflected in a simple regexp rule)

      2. the rule for align-current has the advantage to harmonize the surrounding whitespaces too. And align-regexp seems to allow the same extended logic.

      So combining both steps bound to a key should make alignment of fat-commas quite easy.

      I experimented with a kmacro and it seemed quite nice. :)

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

Re: prettyfy hashes
by 1nickt (Canon) on Apr 03, 2016 at 18:18 UTC

    You could use Data::Dumper::Perltidy which uses a default perltidy config, but can be configured to use your own .perltidy.rc:

    perl -MData::Dumper::Perltidy -E' $href = { foo => "bar", longer => "baz", longest => "qux" }; say Dumper $href; '
    Output:
    $VAR1 = { 'foo' => 'bar', 'longer' => 'baz', 'longest' => 'qux' };

    Hope this helps!


    The way forward always starts with a minimal test.