///////////////////////////////////////////////////////////////////////////////
//                              Lisaac Example                               //
//                                                                           //
//                   LSIIT - ULP - CNRS - INRIA - FRANCE                     //
//                                                                           //
//   This program is free software: you can redistribute it and/or modify    //
//   it under the terms of the GNU General Public License as published by    //
//   the Free Software Foundation, either version 3 of the License, or       //
//   (at your option) any later version.                                     //
//                                                                           //
//   This program is distributed in the hope that it will be useful,         //
//   but WITHOUT ANY WARRANTY; without even the implied warranty of          //
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           //
//   GNU General Public License for more details.                            //
//                                                                           //
//   You should have received a copy of the GNU General Public License       //
//   along with this program.  If not, see <http://www.gnu.org/licenses/>.   //
//                                                                           //
//                     http://isaacproject.u-strasbg.fr/                     //
///////////////////////////////////////////////////////////////////////////////
Section Header
  
  + name    := SHELL;
     
  - author  := "Benoit Sonntag";
  
  - comment := "Small Shell, example File System manager";
  
Section Inherit
  
  - parent_object:OBJECT := OBJECT;
  
Section Private  
  
  - cmds:FAST_ARRAY[STRING];
  
  - dir:DIRECTORY;
  
  - string_tmp:STRING := STRING.create 255;
  
  - execute <-
  ( + cmd:STRING;
    
    cmd := cmds.first;
    //
    // Entry command.
    //
    (cmd == "help").if {
      help;
    }.elseif {cmd == "ls"} then {
      ls;
    }.elseif {cmd == "version"} then {
      "Small Lisaac shell Version 0.1\n".print;
    }.elseif {cmd == "rm"} then {
      rm;      
    }.elseif {cmd == "rename"} then {
      rename;
    //  
    // Directory Manager.  
    //
    }.elseif {cmd == "cd"} then {
      cd;
    }.elseif {cmd == "mkdir"} then {
      mkdir;
    //  
    // File Manager.  
    //
    }.elseif {cmd == "cat"} then {
      cat;
    }.elseif {cmd == "mkfile"} then {
      mkfile;
    } else {
      '`'.print;
      cmd.print;
      "\': Command not found.\n".print;
    };
  );
  
  - help <-
  (
    "Shell manager:\n\
    \  help                : Display this help.\n\
    \  exit / bye          : Exit Lisaac Shell.\n\
    \  version             : Print version.\n\
    \  \n\
    \Entry manager:\n\
    \  ls                  : List information about the files.\n\
    \  rm <src>            : Remove file or directory <src>.\n\
    \  rename <src> <name> : Rename file or directory <src> with new <name>.\n\
    \  \n\
    \Directory manager:\n\
    \  cd <dst>            : Change current directory.\n\
    \  mkdir <dir>         : Create the directory.\n\
    \  \n\
    \File manager:\n\
    \  cat <src>           : Open and display file <src>.\n\
    \  mkfile <src> <text> : Creat <src> file with <text>.\n".print;
  );
  
  //
  // Entry manager.
  //
  
  - ls <-
  ( + e:ENTRY;
    
    "----Access----  ----Update----  ---Size--   ----Name----\n".print;
    dir.lower.to (dir.upper) do { i:INTEGER;
      e := dir.item i;
      string_tmp.clear;
      // Access.
      e.access_date.append_short_in string_tmp;
      string_tmp.add_last ' ';
      e.access_time.append_short_in string_tmp;
      string_tmp.append "  ";
      // Update.
      e.update_date.append_short_in string_tmp;
      string_tmp.add_last ' ';
      e.update_time.append_short_in string_tmp;
      string_tmp.append "  ";
      // Size.
      e.size.append_in string_tmp format 9;
      // Name.
      (e.is_directory).if {
        string_tmp.append " d ";
      } else {
        string_tmp.append " - ";
      };
      string_tmp.append (e.name);
      string_tmp.add_last '\n';
      string_tmp.print;
    };
  );
    
  - rename <-
  ( + e:ENTRY;
    + src,dst:STRING;
    (cmds.count < 3).if {
      "`rename\': Too few arguments.\n".print;
    }.elseif {cmds.count != 3} then {
      "`rename\': Too many arguments.\n".print;
    } else {
      src := cmds.item 1;
      dst := cmds.item 2;
      (dst.index_of '/' since 1 != 0).if {
        '`'.print;
        dst.print;
        "\': Invalid name.".print;
      } else {
        e := dir.get src;
        (e = NULL).if {
          "`rename\': cannot stat `".print;
          src.print;
          "\': No such file or directory.\n".print;
        } else {
          (e.rename dst).if_false {
            "`rename\': cannot rename file `".print;
            dst.print;
            "\': Permission denied.\n".print;
          };
        };
      };
    };
  );

  - rm <-
  ( + e:ENTRY;
    + param:STRING;
    (cmds.count = 1).if {
      "`rm\': Too few arguments.\n".print;
    }.elseif {cmds.count != 2} then {
      "`rm\': Too many arguments.\n".print;
    } else {
      param := cmds.item 1;
      e := dir.get param;
      (e = NULL).if {
        "`rm\': cannot remove `".print;
        param.print;
        "\': No such file or directory.\n".print;
      } else {
        (e.remove).if_false {
          "`rm\': cannot remove `".print;
          param.print;
          "\': Permission denied.\n".print;
        };
      };
    };
  );
  
  //
  // Directory manager
  //
  
  - cd <-
  ( + e:ENTRY;
    + param:STRING;
    
    (cmds.count > 2).if {
      "`cd\': Too many arguments.\n".print;
    }.elseif {cmds.count = 1} then {
      dir.close;
      dir := FILE_SYSTEM;
    } else {
      param := cmds.item 1;
      e := dir.get param;
      (e != NULL).if {
        (e.is_directory).if {
          e := e.open;
          (e != NULL).if {
            dir.close;
            dir ?= e;
          } else {
            "`cd ".print;
            param.print;
            "\': Permission denied.\n".print;
          };
        } else {
          '`'.print;
          param.print;
          "\': Not a directory.\n".print;
        };
      } else {
        '`'.print;
        param.print;
        "\': No such file or directory.\n".print;
      };
    };
  );
  
  - mkdir <-
  ( + e:ENTRY;
    + param:STRING;
       
    (cmds.count = 1).if {
      "`mkdir\': Too few arguments.\n".print;
    }.elseif {cmds.count != 2} then {
      "`mkdir\': Too many arguments.\n".print;
    } else {
      param := cmds.item 1;
      e := dir.make_directory param;
      (e = NULL).if {
        '`'.print;
        param.print;
        "\': File exists, cannot create directory.\n".print;
      };
    };
  );
  
  //
  // File manager.
  //
  
  - cat <-
  ( + e:ENTRY;
    + param:STRING;
    + file:STD_FILE;
    
    (cmds.count = 1).if {
      "`cat\': Too few arguments.\n".print;
    }.elseif {cmds.count != 2} then {
      "`cat\': Too many arguments.\n".print;
    } else {
      param := cmds.item 1;
      e := dir.get param;
      ((e = NULL) || {! e.is_file}).if {
        '`'.print;
        param.print;
        "\': No such file.\n".print;
      } else {
        e := e.open;
        (e = NULL).if {
          '`'.print;
          param.print;
          "\': Not open.\n".print;
        } else {
          file ?= e;
          string_tmp.clear;
          string_tmp.set_capacity (file.size.to_integer);
          file.read string_tmp size (file.size);
          string_tmp.print;
          '\n'.print;
          file.close;
        };
      };
    };
  );
    
  - mkfile <-
  ( + e:ENTRY;
    + f:STD_FILE;
    + param:STRING;
       
    (cmds.count = 1).if {
      "`mkfile\': Too few arguments.\n".print;
    } else {
      param := cmds.item 1;
      e := dir.make_file param;
      (e = NULL).if {
        '`'.print;
        param.print;
        "\': File exists, cannot create file.\n".print;
      }.elseif {cmds.count > 2} then {
        f ?= e.open;
        2.to (cmds.upper) do { j:INTEGER;
          string_tmp.copy (cmds.item j);
          string_tmp.add_last ' ';
          f.write string_tmp from 1 size (string_tmp.count);
        };
        f.close;
      };
    };
  );
    
Section Public
  
  - main <-
  ( + command:STRING;
    + exit:BOOLEAN;
        
    cmds := FAST_ARRAY[STRING].create_with_capacity 10;
    command := STRING.create 100;
    dir := FILE_SYSTEM;
    
    {
      dir.path.print;
      " > ".print;
      command.clear;
      IO.read_line_in command;
      
      (command.is_empty).if_false {       
        cmds.clear;
        command.split_in cmds;      
        exit := (cmds.first == "exit") || {cmds.first == "bye"};	
        (exit).if_false {
          execute;
        };
      };
    }.do_until {exit};    
    "Good bye.\n".print;
  );
