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

I just wrote a function for operating seperate "command line histories" in Tk entries (generically). Since I'm chuffed to bits about it and will now be using it in most of my tk apps, I wanted to simplify it's inclusion the way you would #include a header in a C program. Does that mean I have to turn it into a module or something? Where should I start researching this? For posterity's sake (and, of course, to invite some healthy criticism, etc) here's the code/example:
#!/usr/bin/perl -w use strict; use Tk; my $MW = MainWindow->new(); my $entry1 = $MW->Entry; my $enhist = history(\$entry1,"new"); $entry1->bind("<Key-Return>"=>sub{history(\$entry1,"add", $enhist)}); $entry1->bind("<Key-Up>"=>sub{history(\$entry1,"up", $enhist)}); $entry1->bind("<Key-Down>"=>sub{history(\$entry1,"down", $enhist)}); my $entry2 = $MW->Entry; my $enhist2 = history(\$entry2,"new"); $entry2->bind("<Key-Return>"=>sub{history(\$entry2,"add", $enhist2)}); $entry2->bind("<Key-Up>"=>sub{history(\$entry2,"up", $enhist2)}); $entry2->bind("<Key-Down>"=>sub{history(\$entry2,"down", $enhist2)}); ##GRID## $entry1->grid(-row=>0,-column=>0); $entry2->grid(-row=>2,-column=>0); MainLoop;################## sub history { my $entry = shift; my $cmand = shift; my $hist; if ($cmand eq "new") { my %hash; my @list; $hash{hlist} = \@list; $hash{place} = 0; my $ref = \%hash; return $ref; } else {$hist = shift;} if ($cmand eq "add") { my $string = $$entry->get; $$entry->delete('0','end'); push(@{$hist->{hlist}},$string); $hist->{place}++; } elsif ($cmand eq "up") { if ($hist->{place} <= 0) {$hist->{place} = $#{$hist->{hlist}}} else {$hist->{place}--}; $$entry->delete('0','end'); $$entry->insert('1',$hist->{hlist}[$hist->{place}]); } elsif ($cmand eq "down") { $$entry->delete('0','end'); if ($hist->{place} == $#{$hist->{hlist}}) { $hist->{place} = -1; return} $hist->{place}++; $$entry->insert('1',$hist->{hlist}[$hist->{place}]); } }
history() is the function in question (what else)

Replies are listed 'Best First'.
Re: What to do with my "Tk entry command-history" function
by shmem (Chancellor) on Sep 06, 2008 at 09:44 UTC

    Yes, a module would be the way to go. You could go writing a generic Tk::History package, but if you want to deal just with entries, this is what a derived HistEntry package looks like, based on your post (and Tk::LabEntry):

    package Tk::HistEntry; use vars qw($VERSION); $VERSION = '0.001'; use base qw(Tk::Frame); use Tk::widgets qw(Frame Entry); Construct Tk::Widget 'HistEntry'; sub Populate { require Tk::Entry; # HistEntry constructor. # my($cw, $args) = @_; $cw->SUPER::Populate($args); # Advertised subwidgets: entry. my $e = $cw->Entry(); $e->pack('-expand' => 1, '-fill' => 'both'); $cw->Advertise('entry' => $e ); $cw->ConfigSpecs(DEFAULT => [$e]); $cw->Delegates(DEFAULT => $e); $cw->AddScrollbars($e) if (exists $args->{-scrollbars}); $e->{history} = { hlist => [], place => 0, }; $e->bind("<Key-Return>"=> [ \&addHistory ]); $e->bind("<Key-Up>" => [ \&upHistory ]); $e->bind("<Key-Down>" => [ \&downHistory ]); } sub addHistory { my $entry = shift; my $hist = $entry->{history}; push @{$hist->{hlist}}, $entry->get() ; $hist->{place}++; } sub upHistory { my $entry = shift; my $hist = $entry->{history}; if ($hist->{place} <= 0) { $hist->{place} = $#{$hist->{hlist}} } else { $hist->{place}--; } $entry->delete('0','end'); $entry->insert('1',$hist->{hlist}[$hist->{place}]); } sub downHistory { my $entry = shift; my $hist = $entry->{history}; $entry->delete('0','end'); if ($hist->{place} == $#{$hist->{hlist}}) { $hist->{place} = -1; return } $hist->{place}++; $entry->insert('1',$hist->{hlist}[$hist->{place}]); } 1;

    In your Code, you can now use HistEntry instead of Entry.

      shmem++. If I could vote this one twice I would.
Re: What to do with my "Tk entry command-history" function
by binf-jw (Monk) on Sep 06, 2008 at 09:27 UTC
    Simple answer is yes but modules are pretty easy.
    You'd prob want more then just one function though to make a module. But if it's just for personal use then something like the following would work:
    #!usr/bin/perl -w use strict; # Filename 'Linehist.pm' same as package name, Module in same director +y as the code you wish to call it from use Tk; package Linehist; # Package name (might go before the use Tk I'm nev +er sure ) sub history { my $entry = shift; my $cmand = shift; my $hist; if ($cmand eq "new") { my %hash; my @list; $hash{hlist} = \@list; $hash{place} = 0; my $ref = \%hash; return $ref; } else {$hist = shift;} if ($cmand eq "add") { my $string = $$entry->get; $$entry->delete('0','end'); push(@{$hist->{hlist}},$string); $hist->{place}++; } elsif ($cmand eq "up") { if ($hist->{place} <= 0) {$hist->{place} = $#{$hist->{hlist}}} else {$hist->{place}--}; $$entry->delete('0','end'); $$entry->insert('1',$hist->{hlist}[$hist->{place}]); } elsif ($cmand eq "down") { $$entry->delete('0','end'); if ($hist->{place} == $#{$hist->{hlist}}) { $hist->{place} = -1; return} $hist->{place}++; $$entry->insert('1',$hist->{hlist}[$hist->{place}]); } } 1; # Module is loaded by use or require

    Then to call it.
    #!usr/bin/perl -w use stirct; use Linehist; my $entry = 'What ever you had'; Linehist->history(\$entry, 'new');

    There are of course alternative ways of calling it. And there's definitely a way of exporting it so you can just call
    history(\$entry, 'one');
    come to think of it might be something like this actually
    use Linehist qw(history);
    Although something in the modules may have to change to do that.
    Hope that helps.

    - John
Re: What to do with my "Tk entry command-history" function
by broomduster (Priest) on Sep 06, 2008 at 14:36 UTC
Re: What to do with my "Tk entry command-history" function
by zentara (Cardinal) on Sep 06, 2008 at 15:11 UTC
    Also read "perldoc Tk::Derived" for more info on making your own module, you can google for some info on it too. If you want to get fancier with your module, like pass in custom options, use cget, or configure on it, you may be smart to use Tk::Derived. shmem's example uses "base", but you can add Tk::Derived with little effort, as shown in the perldoc.

    I'm not really a human, but I play one on earth Remember How Lucky You Are