CommandsExample.cpp

Go to the documentation of this file.
00001 
00006 //
00007 // Date:      27 December  2005
00008 //
00009 // Copyright (c) Sergey Satskiy 2005
00010 //               <sergesatsky@yahoo.com>
00011 //
00012 // Permission to copy, use, modify, sell and distribute this software 
00013 // is granted provided this copyright notice appears in all copies. 
00014 // This software is provided "as is" without express or implied
00015 // warranty, and with no claim as to its suitability for any purpose.
00016 //
00017 
00018 #include <sys/time.h>
00019 #include <sys/types.h>
00020 #include <sys/stat.h>
00021 #include <unistd.h>
00022 
00023 #include <iostream>
00024 #include <vector>
00025 #include <string>
00026 #include <map>
00027 #include <list>
00028 #include <algorithm>
00029 using namespace std;
00030 
00031 
00032 #include <boost/function.hpp>
00033 #include <boost/functional.hpp>
00034 using namespace boost;
00035 
00036     // The wrapper is in a single header file.
00037 #include "SReadline.h"
00038 using namespace swift;
00039 
00040 
00041     
00042     // The following typedefs and the struct are
00043     // for "advanced" completers
00044 typedef function< void ( const vector< string > & ) >   Func;
00045 typedef pair< string, Func >                            Element;
00046 
00047     
00048 struct MyElement : public Element
00049 {
00050     operator string () const { return first; }
00051     MyElement( const string & Arg1, Func  Arg2 ) : Element( Arg1, Arg2 ) {}
00052 };
00053 
00054 typedef list< MyElement >     MyContainer;
00055 
00056 
00057     // A functor to look for a command in the 
00058     // container of completers
00059 class LookupFunctor
00060 {
00061     public:
00062             // Creates a functor and memorises tokens
00063         LookupFunctor( const vector< string > &  tokens ) :
00064             Tokens( tokens )
00065         {}
00066 
00067             // Compares the first token only
00068         bool operator()( const MyElement &  Element ) const
00069         {
00070             return strncmp( Tokens.begin()->c_str(),
00071                             (static_cast< string >( Element )).c_str(),
00072                             Tokens.begin()->size() ) == 0;
00073         }
00074 
00075     private:
00076         const vector< string > &  Tokens;
00077 };
00078 
00079 
00080 
00081 
00082 
00083     // The 'help' command processor
00084 class SHelpExecutor
00085 {
00086     public:
00087             // Memorises the list of completers
00088         SHelpExecutor( const MyContainer &  completers ) :
00089             Completers( completers )
00090         {}
00091 
00092             // Prints all the completers on the std out
00093         void operator() ( const vector< string > &  Unused )
00094         {
00095             cout << "List of the command variations:" << endl;
00096             for ( MyContainer::const_iterator  k( Completers.begin() );
00097                   k != Completers.end(); ++k )
00098             {
00099                 cout << static_cast< string >( *k ) << endl;
00100             }
00101         }
00102     private:
00103         const MyContainer &   Completers;
00104 };
00105 
00106 
00107 
00108     // The 'timeofday' command executor
00109     // It prints the number of seconds and microsecond since the Epoch
00110 void TimeOfDay( const vector< string > &    Unused );
00111 void TimeOfDay( const vector< string > &    Unused )
00112 {
00113     struct timeval      tv;
00114     gettimeofday( &tv, 0 );
00115     cout << "gettimefday() reports: " << tv.tv_sec << '.' << tv.tv_usec << endl;
00116 }
00117 
00118 
00119     // The 'filesize' command executor
00120     // It prints the size of the given file in bytes
00121 void FileSize( const vector< string > &  Tokens );
00122 void FileSize( const vector< string > &  Tokens )
00123 {
00124     if ( Tokens.size() != 2 )
00125     {
00126         cout << "The filesize command supposes the file name" << endl;
00127         return;
00128     }
00129 
00130     struct stat     Stat;
00131     if ( stat( Tokens[1].c_str(), &Stat ) != 0 )
00132     {
00133         cout << "Cannot get info for the given '" 
00134              << Tokens[1] << "' file. Check the name." << endl;
00135         return;
00136     }
00137     
00138     cout << "File '" << Tokens[1] << "' size: " 
00139          << Stat.st_size << " bytes" << endl;
00140 }
00141 
00142 
00143 
00144 
00145 int  main( int  argc, char **  argv )
00146 { 
00147         // First parameter is a file name to save / load the
00148         // commands history. The second is a max number of stored commands
00149         // Both parameters could be ommited. In this case the history size
00150         // will be 64 and no save/restore operations will be performed.
00151     SReadline           Reader( "/tmp/.testhist", 32 );
00152 
00153         // Completers with functions to be called
00154     MyContainer         AdvancedCompleters;
00155 
00156         // Help executor functor
00157     SHelpExecutor       HelpExecutor( AdvancedCompleters );
00158 
00159 
00160         // The following is supported:
00161         // - "identifiers"
00162         // - special identifier %file - means to perform a file name completion
00163     AdvancedCompleters.push_back( MyElement( "help", 
00164                                              boost::bind1st( 
00165                                                  boost::mem_fun( &SHelpExecutor::operator() 
00166                                                                ), &HelpExecutor 
00167                                                            ) 
00168                                            ) 
00169                                 );
00170     AdvancedCompleters.push_back( MyElement( "exit", 0 ) );
00171     AdvancedCompleters.push_back( MyElement( "timeofday", TimeOfDay ) );
00172     AdvancedCompleters.push_back( MyElement( "filesize %file", FileSize ) );
00173 
00174 
00175         // Now register the completers.
00176         // Actually it is possible to re-register another set at any time
00177     Reader.RegisterCompletions( AdvancedCompleters );
00178         
00179     
00180         // true when we should exit
00181     bool                    EndOfInput( false );
00182         // List of the entered tokens
00183     vector< string >        Tokens;
00184         // Search iterator
00185     MyContainer::iterator   Found( AdvancedCompleters.end() );
00186 
00187 
00188     for ( ; ; )
00189     {
00190             // We get the list of tokens
00191         Reader.GetLine( "Please input your command> ", Tokens, EndOfInput );
00192         if ( EndOfInput )
00193         {
00194             cout << "End of the session. Exiting." << endl;
00195             break;
00196         }
00197 
00198         if ( !Tokens.empty() )
00199         {
00200             if ( *Tokens.begin() == "exit" )    break;
00201 
00202             Found = find_if( AdvancedCompleters.begin(), AdvancedCompleters.end(), 
00203                              LookupFunctor( Tokens ) );
00204 
00205                 // If found the first token in the list of completers -
00206                 // call the stored function
00207             if ( Found != AdvancedCompleters.end() )
00208             {
00209                 if ( Found->second != 0 ) Found->second( Tokens );
00210             }
00211             else
00212             {
00213                 cout << "Unknown command. Type 'help' for the list of acceptable commands" 
00214                      << endl;
00215             }
00216         }
00217         
00218         cout << "Press Ctrl+D for gracefull exit" << endl;
00219     }
00220         
00221     return 0;
00222 }
00223 

Generated on Mon May 8 21:57:51 2006 for Commands executor with SReadline wrapper by  doxygen 1.4.5