Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical

<STDIN> "anticipate" input?

by johnnyjohnny (Initiate)
on Aug 11, 2008 at 18:46 UTC ( [id://703715] : perlquestion . print w/replies, xml ) Need Help??

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

Hi everyone! Great to be on such a competent forum! Since it might be quite impossible for me to hide the fact that I'm actually a real Perl newbie, I might just as well make this very clear right now. Still I wrote a little piece of programm which does some file editing for me, nothing big really. Anyway, for reasons of cosmetics and aesthetics I want to "anticipate the input for <STDIN>." By this I mean that when I print; "Please enter path of file:" It already says like "C:/Temp". Naturally the "C:/Temp/somedoc" term would have to be editable, so that I could write "D:/GPX/somedoc" instead; well what would be the point otherwise, right? So, thanks in advance for your help!

Replies are listed 'Best First'.
Re: <STDIN> "anticipate" input?
by EvanK (Chaplain) on Aug 11, 2008 at 20:01 UTC
    For simple prepackaged prompting, I'm rather fond of IO::Prompt. As far as "anticipating" input, I don't fully understand what you mean by that. If you just want to present a default option, that's fairly trivial with the module mentioned above:
    #!perl use strict; use warnings; use IO::Prompt; my $dir = prompt("Pick a directory", -default => "C:/Temp"); print "\n\nPicked: $dir\n";
    If you want anything more complex, then zentara's suggestion would be more apt.

    Systems development is like banging your head against a wall...
    It's usually very painful, but if you're persistent, you'll get through it.

Re: <STDIN> "anticipate" input?
by zentara (Archbishop) on Aug 11, 2008 at 20:48 UTC
    Here is a start on a Tk solution. Entries also have a "validatecommand", with which you can pretest the user's text to be valid. You will have to search for "Perl Tk Entry validate" for examples... it can get complex. A Tk::Text widget could also be used, but an Entry widget is simpler for this problem (i.e. no multiline text )
    #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = MainWindow->new(); $mw->fontCreate('medium', -family=>'arial', -weight=>'bold', -size=>int(-14*14/10)); my $frame = $mw->Frame()->pack(); my $bframe = $mw->Frame()->pack(); my $estring = 'C://foo/bar/'; my $lstring = 'Please enter file'; my $label = $frame->Label( -textvariable => \$lstring, -bg => 'white', -width => 25, -justify =>'right', -anchor => 'e', -font => 'medium', )->pack(-side=>'left',-padx=>5); my $entry = $frame->Entry( -textvariable => \$estring, -bg => 'white', -width => 25, -font => 'medium', )->pack(-side=>'left',-padx=>5); $entry->focus; $entry->icursor('end'); $entry->bind('<Return>', \&get_file); $bframe->Button( -text => 'Quit', -command => sub { exit } )->pack(-side=>'left',-padx=>5); $bframe->Button( -text => 'Change', -command => sub { $lstring = 'Enter another'; $estring = 'D://foo/fi/fum/'; $entry->focus; $entry->icursor('end'); } )->pack(-side=>'left',-padx=>5); MainLoop; sub get_file{ my ($widget) = @_; my $entered = $widget->get(); print "file = $entered\n"; }

    I'm not really a human, but I play one on earth Remember How Lucky You Are
Re: <STDIN> "anticipate" input?
by zentara (Archbishop) on Aug 11, 2008 at 19:02 UTC
    I don't know if it works on win32, but Term::ReadLine has a prompt. Are you willing to use a GUI, like Tk? If so, you could use a Text widget and you could manipulate it anyway you want.

    I'm not really a human, but I play one on earth Remember How Lucky You Are
      Yes, I would use a GUI. Though I never used one before. I'll do some research on how to use them... But without GUIs I suppose there's no way to do this, or is there?

        Term::Readline works without a GUI; "term" is short for "terminal", which generally indicates command-line, or at least a text-based UI.

Re: <STDIN> "anticipate" input?
by tptass (Sexton) on Aug 11, 2008 at 20:16 UTC

    What you are trying to do of "anticipating the input" cannot be done, with the value being editable on the command-line. You can like the others have kindly suggested use a method to give a default value, like Term::UI, which could even give the user(s) a list of option to choose from.

    Other than prompting the user on the command-line, the only way to accomplish what you are looking for is using Perl/Tk; where you would create a GUI display with the editable value.

      Yeah, that's kinda what I thought. Tryin' to use Perl/TK right now...

        You are probably way on your way with this, but I figure I would give you two examples in one. The first you will see is the Tk::FileSelect, which brings up a browser window for the user to select a file from (I prefer this solutions, simply because history has shown my not to trust the user). However, if what you are trying to do is a little more complex than you can simply implement this by using Tk::Entry, which is an easier solution than using a Textbox.

        #!/usr/bin/perl -w use Tk; use Tk::FileSelect; use strict; my $mw = MainWindow->new; #Solution #1 the next two lines! my $FSref = $mw->FileSelect(-directory=>"C:/"); my $dir = $FSref->Show; #solution #2 up until MainLoop $mw->Label(-text => 'File Name: ')->pack; my $filename = $mw->Entry(-width => 50, -textvariable => "$dir"); $filename->pack; $mw->Button( -text => 'Print', -command => sub{do_print($filename)} )->pack; MainLoop; #used by solution #2, to print the output to the terminal sub do_print { my ($file) = @_; my $file_val = $file->get; print "You selected $file_val\n"; }
      What you are trying to do of "anticipating the input" cannot be done, with the value being editable on the command-line.

      Very strong words, considering the shell does it all the time.

      There may not be a module to do this (and I am not fully convinced of this), but it most definitely can be done. At the very worst, you would need to push the prefill onto the line, and process the backspaces / ^H yourself.

      Update: See Term::ReadKey as a very possible tool to use to implement this, and Re: <STDIN> "anticipate" input? points to Term::ReadLine, which also looks like it could work (see addhistory as a possible method to do this).


Re: <STDIN> "anticipate" input?
by johnnyjohnny (Initiate) on Aug 11, 2008 at 22:21 UTC
    thank you very much for your support. got a variant of getOpenFile and getSaveFile working now.