App-Tk-Deparse

 view release on metacpan or  search on metacpan

lib/App/Tk/Deparse.pm  view on Meta::CPAN

package App::Tk::Deparse;
use strict;
use warnings;
use 5.008;

use Browser::Open qw(open_browser open_browser_cmd);
use Path::Tiny qw(path);
use Capture::Tiny qw(capture);

use Tk;
use Tk::Dialog;
use Tk::HyperText;
use Tk::BrowseEntry;

our $VERSION = '0.02';

# TODO: make fonts more readable
# TODO: Clear the output when we change the input (or maybe rerun the deparse process?)
# TODO: use nice temporary filename as we can see the name of the file with the -l flags
# TODO: Save window size upon exit; restore window size upon start
# TODO: If there is a syntax error in the code B::Deparse will fail. We sould display this.


my $sample = q{
# Paste your code in the top window and click the Deparse button to see what B::Deparse thinks about it
for (my $j=0, $j<3, ++$j) {
    print $j;
}

my $pi = 3.14;      # -d changes this to a string
my $answer = "42";  # single quote or no quote?

my @planets = ('Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn');

my %h = (
name => "Foo Bar",
age => 42,
fruits => qw(Apple Banana Peach),
);


my $gentlemen = "Some names";
my $me = 'Perl';

print "Hello, $pi, @ladies, \u$gentlemen\E, \u\L$me!";

# Trying to show -P without success
sub foo (\@) { 1 } foo @x
};

my $s = q{
};

# Removed l for now showing the temporary filename does not do much good.
my @flags = ('d', 'p', 'q', 'P');

sub new {
    my ($class) = @_;
    my $self = bless {}, $class;

    $self->{top} = MainWindow->new(
        -title => 'B::Deparse',
    );
    $self->create_menu;
    $self->create_app;
    $self->{incode}->insert("0.0", $sample);
    $self->deparse;

    return $self;
}

sub create_menu {
    my ($self) = @_;

    my $main_menu = $self->{top}->Menu();

    my $file_menu = $main_menu->cascade(-label => 'File', -underline => 0);

lib/App/Tk/Deparse.pm  view on Meta::CPAN

<li>Frank Kropp</li>
<li>John Andersen</li>
<li>Magnus Enger</li>
<li><a href="https://www.linkedin.com/in/mjgardner/">Mark Gardner</a></li>
<li>Markus Hechenberger</li>
<li>Matthew Mitchell</li>
<li>Matthew Persico</li>
<li>Meir Guttman</li>
<li>Mike Small</li>
<li><a href="https://www.linkedin.com/in/n8dgr8/">Nathan Schlehlein</a></li>
<li><a href="https://www.linkedin.com/in/pfmabry/">Paul Mabry</a></li>
<li><a href="https://perl.careers/">Perl Careers</a></li>
<li>Richard Leach</li>
<li>Robert Coursen</li>
<li><a href="https://www.linkedin.com/in/shajiindia/">Shaji Kalidasan</a></li>
<li><a href="https://www.linkedin.com/in/shanta-mcbain-7b644437/">Shanta McBain</a></li>
<li><a href="https://www.linkedin.com/in/slobodanmiskovic/">Slobodan Mišković</a></li>
<li><a href="https://www.linkedin.com/in/stephen-jarjoura-a684401/">Stephen A. Jarjoura</a></li>
<li>Tony Edwardson</li>
<li><a href="https://www.linkedin.com/in/tori-hunter-00009639/">Tori Hunter</a></li>
<li><a href="https://bruck.co.il/">Uri Bruck</a></li>
<li>Victor Moral</li>
<li>Wolfgang Odendahl</li>
<li>Yes2Crypto</li>
<li>... + many others</li>
</ul>

      </body>
      </html>
    });

    $dialog->Show;
}

sub onResource {
    my ($html, %info) = @_;
    my $url = $info{href};
    #print $url, "\n";
    #open_browser($url); # https://rt.cpan.org/Public/Bug/Display.html?id=133315
    #print "done\n";
    my $cmd = open_browser_cmd($url);
    # TODO: verify that the URL is well formatted before passing it to system
    if ($^O eq 'MSWin32') {
        system("$cmd $url");
    } else {
        system("$cmd $url &");
    }
}

sub changed {
    my ($self, $event) = @_;
    # TODO can we delay this and only run the deparse process if there were no changes for some time (e.g. 1 sec)
    $self->deparse;
    #print("changed\n");
}

sub create_app {
    my ($self) = @_;
    $self->{incode} = $self->{top}->Text(
        -state => 'normal',
        -font  => ['fixed', 12],
        -bg    => 'white',
    );
    $self->{incode}->bindtags([$self->{incode}, 'Tk::Text', $self->{top}, 'all']);
    #$self->{incode}->bind('<<Modified>>' => sub { I could not get this working
    $self->{incode}->bind('<Any-KeyPress>' => sub { $self->changed(shift); });
    $self->{incode}->pack(-fill => 'both', -expand => 1);

    $self->{flags} = $self->{top}->Frame();
    $self->{flags}->pack(-side => 'top');

    for my $flag (@flags) {
        $self->{"${flag}_flag"} = 0;

        $self->{"${flag}_flag_checkbox"} = $self->{flags}->Checkbutton(
        -text     => "-$flag",
        -variable => \$self->{"${flag}_flag"},
        -font     => ['fixed', 10],
        -command  => sub { $self->deparse },
        );
        $self->{"${flag}_flag_checkbox"}->pack(-side => 'left');
    }
    # $self->{"s_flag"} = '';
    # my @s_values = qw(C i T);
    # $self->{"s_flag_widget"} = $self->{flags}->BrowseEntry(
    #     -label => "-s",
    #     -width => 3,
    #     -variable => \$self->{"s_flag"},
    # );
    # for my $s (@s_values) {
    #     $self->{"s_flag_widget"}->insert("end", $s);
    # }
    # $self->{"s_flag_widget"}->pack;

    $self->{outcode} = $self->{top}->Text(
        -state => 'disabled',
        -font => ['fixed', 12],
    );
    $self->{outcode}->pack(-fill => 'both', -expand => 1);


    $self->{deparse} = $self->{top}->Button(
        -text    => 'Deparse',
        -command => sub { $self->deparse },
    );
    $self->{deparse}->pack()

}

sub deparse {
    my ($self) = @_;

    my $code = $self->{incode}->get("0.0", 'end');
    my $temp = Path::Tiny->tempfile;
    path($temp)->spew($code);
        
    my $cmd = 'perl -MO=Deparse';
    for my $flag (@flags) {
        if ($self->{"${flag}_flag"}) {
            $cmd .= ",-$flag";
        }
    }
    if ($self->{s_flag}) {
        $cmd .= ",-s$self->{s_flag}"
    }

    my ($stdout, $stderr, $exit) = capture { system("$cmd $temp"); };
    $self->{outcode}->configure('state' => 'normal');
    $self->{outcode}->delete("0.0", 'end');
    if ($exit) {
        $self->{outcode}->configure('fg' => 'red');
        $self->{outcode}->insert("0.0", $stderr);
    } else {
        $self->{outcode}->configure('fg' => 'black');
        $self->{outcode}->insert("0.0", $stdout);
    }
    $self->{outcode}->configure('state' => 'disabled');
}

sub run {
    my ($self) = @_;
    MainLoop;
}

sub exit_app {
    my ($self) = @_;

    # TODO: Save flags when exiting
    # TODO: Save content of the input window when exiting
    # TODO: Save current window size so we can start the same size next time.
    # my %config = (
    #     'geometry' => $self->{top}->geometry,
    # );
    # path($config_file)->spew(encode_json(\%config));

    exit;
}



( run in 1.792 second using v1.01-cache-2.11-cpan-ceb78f64989 )