home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / perl / shell.pl < prev    next >
Text File  |  1998-04-23  |  6KB  |  249 lines

  1. require "Comm.pl";
  2.  
  3. #$Debug = 1;
  4. Comm::init();
  5.  
  6. my %shells = ();
  7.  
  8. sub terminal_emulation ($$);
  9.  
  10. #
  11. # Not meant to be complete.  Just enough so that I could use
  12. # bash
  13. #
  14.  
  15. sub terminal_emulation ($$) {
  16.     my ($vbp, $buf) = @_;
  17.  
  18.     my (@dot,@endot,@donedot);
  19.  
  20.     # Figure out what to do about DOT.  If it's near the end, then
  21.     # leave it alone.  Otherwise, move it to the end.
  22.  
  23.     @donedot = @dot = $vbp->dot;
  24.     @enddot = $vbp->dot('$','$$');
  25.  
  26.     if ($dot[0] >= $endot[0]-1) {
  27.     $vbp->dot(@dot);        # restore dot
  28.     @donedot = ();            # no finish dot
  29.     }
  30.     else {
  31.     @dot = @enddot;
  32.     }
  33.  
  34.     while (length($buf) > 0) {
  35.     if ($buf =~ /^([\x09\x20-\x377]+)(.*)$/s) {
  36.         # Handle sequence of printable characters
  37.         $vbp->setregion(@dot, $dot[0], $dot[1]+length($1))
  38.             ->delete;
  39.         print $vbp $1;
  40.         $buf = $2;
  41.         @dot = $vbp->dot;
  42.     }
  43.     elsif ($buf =~ /^\r(.*)$/s) {
  44.         # ^M                -- beginning of line
  45.         $dot[1] = 0;
  46.         $vbp->dot(@dot);
  47.         $buf = $1;
  48.     }
  49.     elsif ($buf =~ /^\n(.*)$/s) {
  50.         # ^J                -- down a line
  51.         #     (Normally, this should just move down one line,
  52.         #      but we've combined \n's with \r's before getting
  53.         #      here...)
  54.         $dot[0]++;
  55.         @enddot = $vbp->dot('$','$$');
  56.         if ($dot[0] > $enddot[0]) {
  57.         print $vbp "\n";
  58.         #if ($dot[1] > 0) {
  59.         #    print $vbp ' ' x $dot[1];
  60.         #}
  61.         @dot = $vbp->dot;
  62.         }
  63.         else {
  64.         $vbp->dot(@dot);
  65.         }
  66.         $buf = $1;
  67.     }
  68.     elsif ($buf =~ /^(\x08+)(.*)$/s) {
  69.         # Handle ^H
  70.         $dot[1] -= length($1);
  71.         if ($dot[1] < 0) {
  72.         $dot[1] = 0;
  73.         }
  74.         $buf = $2;
  75.         $vbp->dot(@dot);
  76.         
  77.         if ($vbp->setregion(@dot, $dot[0], '$')->fetch =~ /^\s+$/) {
  78.         # Delete 'til end of line if all spaces
  79.         $vbp->delete;
  80.         }
  81.         $vbp->dot(@dot);    # fetch moved dot on us
  82.     }
  83.     elsif ($buf =~ /^(\x07+)(.*)$/) {
  84.         Vile::beep();
  85.         $buf = $2;
  86.     }
  87.     elsif ($buf =~ /^\e\[(\d*)P(.*)$/s) {
  88.         # ESC, [, optional-digits, P    -- delete characters forward
  89.         my $digs;
  90.         $digs = ($1 eq "") ? 1 : $1;
  91.         $vbp->setregion(@dot, $dot[0], $dot[1]+$digs)->delete;
  92.         $buf = $2;
  93.     }
  94.     elsif ($buf =~ /^\e\[(\d*)@(.*)$/s) {
  95.         # ESC, [, optional-digits, @    -- insert N characters
  96.         my $digs;
  97.         $digs = ($1 eq "") ? 1 : $1;
  98.         $buf = $2;
  99.         # To do this right, we probably have an "insert" mode..
  100.         $buf =~ /^(.{,$digs})(.*)$/s;
  101.         print $vbp $1;
  102.         $buf = $2;
  103.     }
  104.     elsif ($buf =~ /^\e\[K(.*)$/s) {
  105.         # ESC, [, K                -- erase 'til eol
  106.         $vbp->setregion(@dot, $dot[0], '$$')->delete;
  107.         $buf = $1;
  108.     }
  109.     else {
  110.         # Unhandled control character(s)
  111.         # just print them out...
  112.         # (And when they annoy you enough, add a case to handle
  113.         # them above.)
  114.  
  115.         $buf =~ /^(.)(.*)$/s;
  116.  
  117.         $vbp->setregion(@dot, $dot[0], $dot[1]+length($1))
  118.             ->delete;
  119.         print $vbp $1;
  120.         $buf = $2;
  121.         @dot = $vbp->dot;
  122.     }
  123.     }
  124.  
  125.     if (@donedot) {
  126.     $vbp->dot(@donedot);
  127.     }
  128. }
  129.  
  130.  
  131.  
  132. sub shell {
  133.     my $oldworking = Vile::working();        # fetch old value of working
  134.     Vile::working(0);                # disable working... messages
  135.  
  136.     $| = 1;
  137.  
  138.     my $shell = $ENV{SHELL};
  139.     $shell = '/bin/sh' unless defined($shell);
  140.  
  141.     my ( $Proc_pty_handle, $Proc_tty_handle, $pid ) = &open_proc( $shell );
  142.     die "open_proc failed" unless $Proc_pty_handle;
  143.  
  144.     my $vbp = new Vile::Buffer;
  145.     $vbp->buffername("shell-$pid");
  146.     Vile->current_buffer($vbp);
  147.     print $vbp " \n";
  148.     $vbp->unmark()->dot('$$');
  149.     Vile::update();
  150.  
  151.  
  152.     $shells{$pid}{PTY_HANDLE} = $Proc_pty_handle;
  153.     $shells{$pid}{BUF_HANDLE} = $vbp;
  154.  
  155.     my $sanity_initialized = 0;
  156.  
  157.     Vile::watchfd(
  158.     fileno($Proc_pty_handle),
  159.     'read',
  160.     sub {
  161.         my $buf = ' ' x 4096;
  162.         my @olddot = $vbp->dot;
  163.         my $lastlnum;
  164.  
  165.         unless ($sanity_initialized) {
  166.         &stty_sane($Proc_tty_handle);    # use $Proc_pty_handle for HP
  167.         $sanity_initialized = 1;
  168.         }
  169.  
  170.         # Fetch data from input stream
  171.         sysread $Proc_pty_handle, $buf, 4096;
  172.  
  173.         $buf =~ s/\r\n/\n/gs;        # nuke ^M's
  174.  
  175.         @dot = $vbp->dot('$','$$');
  176.  
  177.  
  178.         if (length($buf) < 256
  179.             && ($buf =~ /[\x01-\x08\x11-\x1f]/
  180.                 || $olddot[0] != $dot[0] 
  181.             || $olddot[1] != $dot[1]))
  182.         {
  183.         # Yuck, it contain's control characters, or it's
  184.         # not at the end of the buffer
  185.         # ...we have some work to do
  186.         $vbp->dot(@olddot);
  187.         terminal_emulation($vbp, $buf)
  188.         }
  189.         else {
  190.         # Blast it out...
  191.         #print "Blast $blast"; $blast++;
  192.  
  193.         # Set Position to end of buffer and retrieve this line number
  194.  
  195.         # Write data to the editor's buffer
  196.         print $vbp $buf;
  197.  
  198.         # Reset old position of dot if not near end of buffer
  199.         if ($olddot[0] < $dot[0] - 1) {
  200.             $vbp->dot(@olddot);
  201.         }
  202.         }
  203.         # Nuke the [modified] message
  204.         $vbp->unmark();
  205.  
  206.         # Update the screen
  207.         Vile::update();
  208.         # Something to look into... uncomment the following line: segfault
  209.         #print "After update: ", join(',',$vbp->dot());
  210.     }
  211.     );
  212.  
  213.     my $c;
  214.     while (($c = Vile::keystroke()) != 7) {        # ^G escapes
  215.     print $Proc_pty_handle chr($c);
  216.     }
  217.  
  218.     Vile::working($oldworking);            # restore "working..." message
  219.                             # to previous state
  220. }
  221.  
  222. sub resume_shell {
  223.     my $pid;
  224.     ($pid) = ($Vile::current_buffer->buffername() =~ /^shell-(\d+)$/);
  225.  
  226.     if (!defined($pid) or !defined($shells{$pid}{PTY_HANDLE})) {
  227.     print "Not in a shell window!";
  228.     return;
  229.     }
  230.  
  231.     my $Proc_pty_handle = $shells{$pid}{PTY_HANDLE};
  232.     my $vbp = $shells{$pid}{BUF_HANDLE};
  233.  
  234.     my $oldworking = Vile::working();        # fetch old value of working
  235.     Vile::working(0);                # disable working... messages
  236.  
  237.     $vbp->dot('$','$$');
  238.     Vile::update();
  239.  
  240.     my $c;
  241.     while (($c = Vile::keystroke()) != 7) {        # ^G escapes
  242.     print $Proc_pty_handle chr($c);
  243.     }
  244.  
  245.     Vile::working($oldworking);            # restore "working..." message
  246. }
  247.  
  248. 1;
  249.