in reply to how to use validatecommand for string checking

Here is something I had in my library, written by someone else, called entry_auto_complete.pl. I adapted it to your problem, you may like it.
#!/usr/bin/perl -w #entry_auto_complete.pl use Tk; use strict; my $mw = MainWindow->new; #list of recognized words/phrases #perhaps read in from a file of recognized words/phrases my (@list) = ( "apo\'strophe", "Upper", "this one", "that one", "the other one", "the something", "go west", "go east", "go north", "go south", ); @list = sort(@list); #show the list print "Upper, lower, space, apostrophe and all case insensitive\n"; print "\n"; foreach (@list) { print "$_\n"; } print "\n"; my $text = ''; my $entry = $mw->Entry( -textvariable => \$text, -width => 60 )->pack( +); $entry->bind( '<Key>' => sub { my ($w) = @_; #widget referenced my $ev = $w->XEvent; #get the event object my $A = $ev->A; #get ascii char from the event print "---------------------$A---------------\n"; #if the character entered is [lowercase] OR #[uppercase] OR [a space] OR [an apostrophe] ... if ( $A =~ m/[a-z]|[A-Z]| |'/ ) { foreach (@list) { #compare the entered text to the items in the list if ( $text ne '' and $_ =~ m/^$text/i ) { print "$text -- $_\n"; my $input_length = length($text); my $match_length = length($_); $text = $_; #highlight/select the tail end of the entry field +text $entry->selectionFrom($input_length); $entry->selectionTo($match_length); } #if } #foreach } #end if } #sub ); #end bind $mw->Button( -text => 'Quit', -command => sub { exit } )->pack( -fill +=> 'x' ); $entry->focus(); MainLoop;

I'm not really a human, but I play one on earth. Cogito ergo sum a bum

Replies are listed 'Best First'.
Re^2: how to use validatecommand for string checking
by dannytrannox (Initiate) on Aug 27, 2007 at 16:09 UTC
    Thanks for your response Monks jdporter and zentara.
    Your responses have confirmed my guess that the validatecommand doesn't check for string without us to do some fancy things. By the way, the reason I have to check for "go " in the beginning but avoid appendding "go " after reading the content of the Entry is because in fact I have to check for two keywords, not just one, "go " and "fly ". Depeding on which keyword the user enters, I will treat the data entered after these two keywords differently. I only mentioned "go " in the original post just for brevity.

    So I based on your code and crafted one to hopefully do what I want. The code is written to the best of my knowledge below. However, it appears that the validatecommand only check ONCE in this case. For example, if I type "gh" it will flag error as expected. But after I delete "gh" and retype "gn" it won't flag error anymore! The print command inside the sub is even not invoked at the 2nd mistake I intended to make! Would you please help if you see if there's something wrong here?

    #!/usr/bin/env perl use English; require Tk; use Tk; use Tk; my $mw = MainWindow->new(); my $entry = $mw->Entry()->pack(); $entry->configure( -textvariable => \$content , -validate => 'key' , -validatecommand => sub { my $newvalue = shift; my $changedchars = shift; my $currentvalue = shift; my $index = shift; my $type = shift; print "newval-> $newvalue\nchangedchars-> $changedchars\n". "curvalue-> $currentvalue\n index-> $index\n\n\n"; if( ($index == 0) and ($newvalue ne 'g')){return 0} if( ($index == 1) and ($newvalue ne 'go')){return 0} if( ($index == 2) and ($newvalue ne 'go ')){return 0} return 1; }, -invalidcommand => [ \&errorsub , \$entry ] ) ; MainLoop; sub errorsub { print "ERROR.\n"; $content = "" ; $entry->focus; $entry->icursor(0); }
    Thanks,

    Danny

      Another alternative which you may be overlooking, is to forget the -validate stuff, and just bind on the Return keypress, so you get the whole string at once. Then you can regex it.
      #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = MainWindow->new(); my $content = ''; my $entry = $mw->Entry(-textvariable => \$content)->pack(); $entry->bind('<Return>',sub{ my $val = $entry->get; print "check with regex here and do what is needed $val\n" }); $entry->focus; MainLoop;

      I'm not really a human, but I play one on earth. Cogito ergo sum a bum