Ce site a pour vocation de me présenter, moi, Hugo Vacher. Vous retrouverez ici mes créations, mon Curiculum Vitae. Se site comporte également une partie "blog" qui contiendras des conseils et ressources pour developpeurs.

PHPCommand v0.9 passons aux choses sérieuses !

Par Hugo Vacher | Catégories : Créations | Posté : 26-08-2009

1

EDIT: Comme vous l’aurez surement constaté, j’ai plus ou moins abandonné le développement de PHPc, mais je viens de découvrir php-shell qui après un rapide test semble très aboutis.

Voila, après avoir découvert php -a qui fait pratiquement la même chose que PHPCommand v0.1 (Merci @paraboul), je me suis dit que mon script n’aurait aucun intérêt si je ne l’améliorais pas.

Voici donc un liste des amélioration de la version 0.9:

  • ATTENTION: ce script utilise des commandes Unix spécifique, il ne fonctionne donc plus windows.
  • Fonctionne sous Max OS X, et sur la plupart des distributions linux (support des « VT220 terminal escape sequences » et des commandes stty et dd nécessaire).
  • Support de l’historique, utilisez les touches haut et bas pour naviguer dans l’historique.
  • Support de la navigation horizontale pour corriger/inserer des caracteres, support des touches Del et Ret arrière.
  • Si votre script affiche un message ne se términant pas par « \n » celui-ci est ajouté automatiquement.

Todo list:

  • Ajouter l’aide avec F1 et avec –help
  • Naviguer avec la souris
  • Coloration syntaxique (merci @un_geek) ?
  • D’autres idées ?

Voila le nouveau code (beaucoup plus long, ici on gere tout à la main (position du curseur, gestion des touches etc…):

#! /usr/bin/php
<?php /**  * Class used to isolate functions and vars that needs to keep defined while  * evaluating users code.  */ class PHPc{   const PROMPT = 'php>';
  const PSIZE = 5;//Prompt's size +1
 
  public static $lines = array();
  public static $code_to_eval;
  public static function readChar(){
    $ret = exec('stty cbreak -echo;c=`dd bs=1 count=1 2>/dev/null`;stty -cbreak echo;echo "$c."');
    if($ret=='.') return "\n";
    return substr($ret, 0, 1);
  }
  public static function delChar(&$line, $pos){
    $line = substr($line, 0, $pos).substr($line, $pos+1);
  }
  public static function setLine(&$from, $to){
    $size = strlen($from);
    $goto = strlen($to)+self::PSIZE;
    echo "\033[".self::PSIZE."G\033[{$size}P{$to}\033[{$goto}G";
    $from = $to;
    return $goto;
  }
}
echo <<<INTRO PHP Command 0.9 Created by Hugo Vacher (korri.fr) Code is interpreted when line end with ';' or '}' and that all '{' are closed. You are free to use, modify and redistribute this code, please leave me a comment if you do it. INTRO;   while(true){     PHPc::$code_to_eval = '';     $continue = true;     while($continue){       //Reset history index       $index = 0;       //Say that line isn't finished       $ln = true;       //Reset cursor pos       $c = PHPc::PSIZE;       $total = PHPc::PSIZE;       $line = '';       echo PHPc::PROMPT;       //Add empty line       array_unshift(PHPc::$lines, '');       while($ln){         $char = PHPc::readChar();         $cod = ord($char);         //Gonna parse each key         if($cod == 10){//Enter           echo "\033[".PHPc::PSIZE."G\n";           $ln = false;         }else if($cod == 127){//Ret arriere           if($c > PHPc::PSIZE){
            PHPc::delChar($line, --$c-PHPc::PSIZE);
            --$total;
            echo "\033[D\033[1P";
          }
        }else if($cod == 4){//Ctrl + D
          break 3;//We exit programm
        }else if($cod == 27){
          $key = PHPc::readChar().PHPc::readChar();
          switch($key){
            case '[3'://Del
              PHPc::readChar();
              if($c < $total){                 PHPc::delChar($line, $c-PHPc::PSIZE);                 --$total;                 echo "\033[1P";               }               break;             case '[A'://up               if(isset(PHPc::$lines[$index+1])){                 if($index==0) PHPc::$lines[0] = $line;                 $to = PHPc::$lines[++$index];                 $c = PHPc::setLine($line, $to);                 $total = $c;               }               break;             case '[B'://down               if($index > 0){
                $to = PHPc::$lines[--$index];
                $c = PHPc::setLine($line, $to);
                $total = $c;
              }
              break;
            case '[D'://left
              if($c > PHPc::PSIZE) echo "\033[".--$c.'G';
              break;
            case '[C'://right
              if($c<$total) echo "\033[".++$c.'G';               break;             default:               //We don't do nothing, here we'll handle F1 key           }         }else{           echo "\033[4h$char\033[4l";//Echo char in insert mode 		  //Get the 2 next chars (special keys are at least 3chars           $line  = substr($line, 0, $c - PHPc::PSIZE); 		  $line .= $char.substr($line, $c - PHPc::PSIZE);           ++$c; ++$total;         }       }       PHPc::$lines[0] = $line;       PHPc::$code_to_eval .= $line;       if(substr($line,-1)==';' || substr($line,-1)=='}'){         $cnto = substr_count(PHPc::$code_to_eval, '{');         $cntc = substr_count(PHPc::$code_to_eval, '}');         if($cntc >= $cnto){
          $continue = false;
        }
      }
    }
    //Clear local vars
    unset($c, $total, $line, $continue, $char, $cod, $cnto, $cntc, $to, $index);
 
    ob_start();
    eval(PHPc::$code_to_eval);
    $txt = ob_get_contents();
    ob_end_flush();
    if($txt!='' && substr($txt, -1) != "\n") echo "\n";
  }
  echo "\nExit\n";
?>

Le code seul ici: phpc.php

PS: Je ferais une version plus propre et mieux documentée, quand je sortirais la 1.0, pour le moment ce code n’a qu’un but utilitaire et non un but d’apprentissage.

Commentaires (1)

[...] EDIT: Retrouvez la nouvelle version ici : PHPCommand 0.9 [...]

Laisser un commentaire