CmdInput

Files CCore/inc/CmdInput.h CCore/src/CmdInput.cpp

CmdInput

CmdInput is a simple character input processing class. It recognizes a given set of commands. It works with some target class. The target builds the command set and provides methods to execute them.


class CmdInput : NoCopy
 {
   ....

  public:
  
   struct Target 
    {
     virtual void buildCmdList(CmdInput &input)=0;
     
     template <class T>
     void addCommand(CmdInput &input,StrLen cmd,void (T::*method)(StrLen arg)); 
    };
   
   using TargetMethod = void (Target::*)(StrLen arg) ;
  
   // constructors
  
   explicit CmdInput(Target &target);
   
   ~CmdInput();
   
   // methods
   
   void start();
  
   bool put(char ch);
   
   void put(StrLen str);
   
   bool back();
   
   struct CompleteResult
    {
     ulen count;
     StrLen str;

     ....
    };
   
   CompleteResult complete() const;
   
   struct FinishResult
    {
     ....

     // methods
     
     bool operator + () const;
     
     bool operator ! () const;
     
     void operator () (StrLen arg);
     
     template <class Report>
     void operator () (StrLen arg,Report &report); 
    };
   
   FinishResult finish();
 };

CmdInput constructor takes a reference to the target. It calls the target virtual method buildCmdList() to prepare the command set. Target must use the method addCommand() to add a command to the set. An example:


class Target : public NoCopyBase<CmdInput::Target>
 {
  private:
  
   void empty(StrLen);

   void help(StrLen arg);

   void stat(StrLen arg);

   void exit(StrLen arg);
   
   virtual void buildCmdList(CmdInput &input)
    {
     addCommand(input,"",&Target::empty);
     addCommand(input,"help",&Target::help);
     addCommand(input,"stat",&Target::stat);
     addCommand(input,"exit",&Target::exit);
    }
 };

The strings cmd must be persistent (at least for the life-time of the CmdInput object), usually they are string literals. You should define an empty command to react on the empty command line.

The following methods are to process a character input:

start() starts an input command.

put(char) adds a character. The return value is true, if the input is valid, i.e. can be completed to a command.

put(StrLen) adds a string of characters.

back() backs one character. The return value is false, if the input is empty and cannot be backed.

Two last methods are to complete the input.

complete() checks if the input is valid. The return value is a structure with two fields: count is the number of commands, which can be received by completing the input, str is the completing string, if the count equals 1. This method can be used to implement the auto-completion.

finish() checks if the input is a command. The return value is non-null in this case and can be used to call the correspondent target method to execute the command. There are two variants of the call. The first operator () (StrLen arg) is to call the method with the argument. The second operator () (StrLen arg,Report &report) does the call inside a try-catch block, report is an ReportException class.

CmdInputCon

CmdInputCon is a complex class, it combines the CmdInput and some console reader class.


template <class ReadCon,ulen MaxArgLen=80>
class CmdInputCon : NoCopy
 {
   ....

  public: 
  
   template <class ... SS>
   CmdInputCon(CmdInput::Target &target,StrLen prompt_str,SS && ... ss); 
   
   ~CmdInputCon();
   
   void setBadChar(char bad_char);

   template <class ... SS>
   void command(SS && ... ss);
 };

The first argument of the constructor is a target, the second is a prompt string. This string must be persistent for the life-time of the object. Other arguments a forwarded to the inner console reader object.

"Bad character" is printed during command input, if the entered string is not correct. For example, if the command set is "start", "exit" and the string "s" is entered, then typing any character, other than 't' is echoed using the bad character. By default, the bad character is '?'. The method setBadChar() resets it to the given character.

The main method is the command(). It enters and executes a single command from the console. An additional ReportException argument may be provided to execute a command in a try-catch block.

A complete example of using this class.


class Target : public NoCopyBase<CmdInput::Target>
 {
   bool run_flag;
 
  private:
  
   void empty(StrLen) {}
  
   void help(StrLen arg) { Printf(Con,"help #.q;\n",arg); }
   
   void exit(StrLen arg) { Printf(Con,"exit #.q;\n",arg); run_flag=false; }
   
   virtual void buildCmdList(CmdInput &input)
    {
     addCommand(input,"",&Target::empty);
     addCommand(input,"help",&Target::help);
     addCommand(input,"exit",&Target::exit);
    }
 
  public:
  
   Target() : run_flag(true) {}
   
   ~Target() {}
   
   bool operator + () const { return run_flag; }
   
   bool operator ! () const { return !run_flag; }
 };

class Test : NoCopy
 {
   Target target;
   
   CmdInputCon<ReadCon> input;
   
  public: 
  
   Test()
    : input(target,"test> ")
    {
    }
    
   ~Test()
    {
    } 
    
   void run()
    {
     while( +target )
       {
        input.command();
       }
    }  
 };

int main()
 {
  Test test;
  
  test.run();

  return 0;
 }