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

Hey,

Can someone try this out and explain to me why! I just put same code into a module (to make it more modular), but in Windows I get some wierd "←[0J" output every time I press a key! Where does this come from? I didn't have this problem when not having the code as a module! However, I want it as a module, but I dunno how to solve the problem.

AceShell.pm
#!/usr/bin/env perl package AceShell; use Term::ANSIScreen qw/:color :cursor :screen :keyboard/; use Term::ReadKey; use Time::HiRes qw( usleep ); use Time::localtime; use Data::Dumper; use strict; use warnings; sub new { my $class = shift; my @history = (); my $history_at = 0; my $word = ""; my $word_ghost = ""; my $prompt = "AceShell> "; my $pos = 0; my $self = { 'Applied_Commands' => {}, 'History' => \@history, 'History_At' => $history_at, 'Word' => $word, 'Word_Ghost' => $word_ghost, 'Prompt' => $prompt, 'Pos' => $pos, }; return bless($self, $class); } sub startShell { my $self = shift; # Disable CTRL keys ReadMode(4); $| = 1; while(1){ my $char; while (!defined ($char = ReadKey(-1))){ usleep 1_100; print "\r" . formatTime(time) . " | " . $self->{'Prompt'} . $self +->{'Word'}; } cldown; my $ord = ord($char); last if ($ord == 3); last if ($ord == 4); if ($ord == 10 or $ord == 13) { # "Enter" print "\n"; $self->{'Word'} = ""; $self->{'Pos'} = 0; next; } elsif ($ord == 8 || $ord == 127) { # ie "Backspace") if ($self->{'Pos'} == 0) { print " "; next; } --$self->{'Pos'}; print chr(8) . ' ' . chr(8); chop($self->{'Word'}); $self->{'Wword_Ghost'} = ""; next; } if($ord >= 32 && $ord < 155) { ++$self->{'Pos'}; $self->{'Word'} .= chr($ord); } } ReadMode(0); } sub formatTime { my $t_time = shift; my $temp_time = localtime($t_time); my $time = "1900-01-01 01:01:01"; if (defined ($temp_time)) { $time = sprintf "%04d-%02d-%02d %02d:%02d:%02d", $temp_time->y +ear+1900, $temp_time->mon+1, $temp_time->mday, $temp_time->hour, $tem +p_time->min, $temp_time->sec; } return $time; } sub formatText { my $subform = "@<<<<<<<<<<< - @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<<<<<<<<<<<<<<"; formline($subform, @_); my $formated = $^A; $^A = ""; return $formated; } 1
aceShellTest.pl:
#!/usr/bin/env perl use AceShell; use lib "."; use strict; use warnings; my %COMMANDS = ( 'help' => "Show help information.", 'history' => "Show history of typed commands.", 'quit' => "Quit the Shell.", ); my $aceshell = AceShell->new(); $aceshell->startShell();

Thanks,
Ace

2006-07-15 Retitled by Arunbear, as per Monastery guidelines
Original title: 'AceShell'

Replies are listed 'Best First'.
Re: Weird screen output in my AceShell module
by ikegami (Patriarch) on Jul 15, 2006 at 06:11 UTC

    Sending ANSI escape sequences to something that amounts to a TTY is like trying to run a Perl program using the Java compiler. What you see are the ANSI escape sequences you are sending to the console. Not knowing they're suppose to be special, the console simply displays them. Forunately, it's possible to add support for ANSI escape sequences in this case. Simply add the line use Win32::Console::ANSI; to your script (after installing the module).

    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Weird screen output in my AceShell module
by liverpole (Monsignor) on Jul 15, 2006 at 14:18 UTC
    The "←[0J" you are seeing is actually, as ikegami said, a mis-renderend escape sequence.  The "←" is what happens when the command window tries to directly print an escape (\e).

    It's probably unnecessary to install 'Win32::CONSOLE::ANSI', though, as it's already part of the ActiveState Perl core (at least in the latest 5.8.7 version).  Here's an experiment you can try.  I've changed the escape sequence to the one for clearing the screen, "\e[H\e[J", which is very easy to see when it occurs.  (It also works in Linux and other places where the ANSI escape sequences are honored):

    use strict; use warnings; $|++; print "\e[H\e[J"; print "\nPress <RETURN> to clear the screen: "; <STDIN>; require Win32::CONSOLE::ANSI; print "\e[H\e[J";

    The first time time it prints "\e[H\e[J", it doesn't handle it gracefully, and you'll see escape rendered as "←" again:  "←[H←[J".  The second time, though, since you are now using "Win32::CONSOLE::ANSI", the screen will be cleared.


    s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
      Hmm, seens that I fooled myself little. Apparently I loaded that in some Constants.pm I've made. However, it still doesn't seem to work with the AceShell.pm module, even if I explicitly add this in the module:
      # This so one can use \e ourselfes... on both Linux and Windows! Else # the Win32::Console::ANSI have its on functions for outputting in col +or! if ($^O eq "MSWin32") { eval { require Win32::Console::ANSI; }; } elsif ($^O eq "Linux") { eval { require Term::ANSIColor; }; } use Term::ANSIScreen qw/:color :cursor :screen :keyboard/; ...
      After some testing, I seem to need to do this before loading in the Term::ANSIScreen module.
        elsif ($^O eq "Linux") { eval { require Term::ANSIColor; }; }

        is useless. You're using the functions from Term::ANSIScreen instead of those from Term::ANSIColor. Term::ANSIColor is a subset of Term::ANSIScreen, not the non-Windows equivalent of Win32::Console::ANSI.

        Furthermore, you can simplify your program using the if pragma:

        # Load ANSI driver if running in Windows. use if $^O eq 'MSWin32', 'Win32::Console::ANSI'; use Term::ANSIScreen qw/:color :cursor :screen :keyboard/; ...

        Using the simpler code shouldn't fix anything, but since it will load Win32::Console::ANSI at compile time as if you had said use Win32::Console::ANSI;, it might.

        Update: Added missing quotes as per reply.

Re: Weird screen output in my AceShell module
by planetscape (Chancellor) on Jul 15, 2006 at 03:50 UTC

    Oh, my. That's quite a lot of code for someone unfamiliar with the purpose, design decisions, etc. to dig through... Could you narrow it down to a small test case? (That is, identify what part of your main code is misbehaving?) IMHO, that would greatly increase your chances of finding someone motivated enough to help you with your bug hunt...

    HTH,

    planetscape
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Weird screen output in my AceShell module
by Khen1950fx (Canon) on Jul 15, 2006 at 10:25 UTC
    ikegami is right. Adding  use Win32::Console::ANSI to your script will fix that problem. As to what is the meaning of "<--[0J"---the closest thing that I could find is this:

    [0J - erase from current position to bottom of screen inclusive.

    See: http://www.inwap.com/pdp10/ansicode.txt

    A reply falls below the community's threshold of quality. You may see it by logging in.