TuttleOFX  1
main.cpp
Go to the documentation of this file.
00001 #include <sam/common/utility.hpp>
00002 #include <sam/common/options.hpp>
00003 
00004 #include <boost/filesystem/operations.hpp>
00005 #include <boost/filesystem/exception.hpp>
00006 #include <boost/exception/diagnostic_information.hpp>
00007 #include <boost/foreach.hpp>
00008 #include <boost/algorithm/string.hpp>
00009 #include <boost/algorithm/string/split.hpp>
00010 #include <boost/program_options.hpp>
00011 #include <boost/shared_ptr.hpp>
00012 
00013 #include <detector.hpp>
00014 
00015 #include <algorithm>
00016 #include <iterator>
00017 
00018 namespace bpo = boost::program_options;
00019 namespace bfs = boost::filesystem;
00020 namespace bal = boost::algorithm;
00021 
00022 
00023 namespace sam
00024 {
00025         bool wasSthgDumped = false;
00026 }
00027 
00028 // A helper function to simplify the main part.
00029 template<class T>
00030 std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
00031 {
00032         copy(v.begin(), v.end(), std::ostream_iterator<T>(std::cout, " "));
00033         return os;
00034 }
00035 
00036 template<class T>
00037 void coutVec( const boost::ptr_vector<T>& v )
00038 {
00039         BOOST_FOREACH( const T& f, v )
00040         {
00041                 TUTTLE_LOG_INFO( f );
00042                 sam::wasSthgDumped = true;
00043         }
00044 }
00045 
00046 
00047 int main( int argc, char** argv )
00048 {
00049         signal(SIGINT, signal_callback_handler);
00050 
00051         using namespace tuttle::common;
00052         using namespace sam;
00053 
00054         boost::shared_ptr<formatters::Formatter> formatter( formatters::Formatter::get() );
00055         boost::shared_ptr<Color>                 color( Color::get() );
00056         
00057         sequenceParser::EMaskType    researchMask        = sequenceParser::eMaskTypeDirectory | sequenceParser::eMaskTypeFile | sequenceParser::eMaskTypeSequence ; // by default show directories, files and sequences
00058         sequenceParser::EMaskOptions descriptionMask     = sequenceParser::eMaskOptionsNone;   // by default show nothing
00059         bool             recursiveListing    = false;
00060         bool             script              = false;
00061         std::string      availableExtensions;
00062         std::vector<std::string> paths;
00063         std::vector<std::string> filters;
00064 
00065         formatter->init_logging();
00066         
00067         // Declare the supported options.
00068         bpo::options_description mainOptions;
00069         mainOptions.add_options()
00070                 (kAllOptionString            , kAllOptionMessage)
00071                 (kDirectoriesOptionString    , kDirectoriesOptionMessage)
00072                 (kExpressionOptionString     , bpo::value<std::string>(), kExpressionOptionMessage)
00073                 (kFilesOptionString          , kFilesOptionMessage )
00074                 (kHelpOptionString           , kHelpOptionMessage)
00075                 (kLongListingOptionString   , kLongListingOptionMessage)
00076                 (kRelativePathOptionString  , kRelativePathOptionMessage)
00077                 (kRecursiveOptionString      , kRecursiveOptionMessage)
00078                 (kPathOptionString    , kPathOptionMessage)
00079                 (kSequencesOptionString           , kSequencesOptionMessage)
00080                 (kColorOptionString            , kColorOptionMessage)
00081                 (kFullDisplayOptionString     , kFullDisplayOptionMessage )
00082                 (kScriptOptionString           , kScriptOptionMessage)
00083                 (kBriefOptionString            , kBriefOptionMessage)
00084         ;
00085         
00086         // describe hidden options
00087         bpo::options_description hidden;
00088         hidden.add_options()
00089                 (kInputDirOptionString, bpo::value< std::vector<std::string> >(), kInputDirOptionMessage)
00090                 (kEnableColorOptionString, bpo::value<std::string>(), kEnableColorOptionMessage)
00091         ;
00092         
00093         // define default options 
00094         bpo::positional_options_description pod;
00095         pod.add(kInputDirOptionLongName, -1);
00096         
00097         bpo::options_description cmdline_options;
00098         cmdline_options.add(mainOptions).add(hidden);
00099 
00100         bpo::positional_options_description pd;
00101         pd.add("", -1);
00102         
00103         bpo::variables_map vm;
00104 
00105         try
00106         {
00107                 //parse the command line, and put the result in vm
00108                 bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).positional(pod).run(), vm);
00109 
00110                 // get environment options and parse them
00111                 if( const char* env_ls_options = std::getenv("SAM_LS_OPTIONS") )
00112                 {
00113                         const std::vector<std::string> vecOptions = bpo::split_unix( env_ls_options, " " );
00114                         bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm);
00115                 }
00116                 if( const char* env_ls_options = std::getenv("SAM_OPTIONS") )
00117                 {
00118                         const std::vector<std::string> vecOptions = bpo::split_unix( env_ls_options, " " );
00119                         bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm);
00120                 }
00121                 bpo::notify(vm);
00122         }
00123         catch( const bpo::error& e)
00124         {
00125                 TUTTLE_LOG_ERROR("sam-ls: command line error: " << e.what() );
00126                 exit( 254 );
00127         }
00128         catch(...)
00129         {
00130                 TUTTLE_LOG_ERROR("sam-ls: unknown error in command line.");
00131                 exit( 254 );
00132         }
00133 
00134         if ( vm.count(kScriptOptionLongName) )
00135         {
00136                 // disable color, disable directory printing and set relative path by default
00137                 script = true;
00138                 descriptionMask |= sequenceParser::eMaskOptionsAbsolutePath;
00139         }
00140 
00141         if ( vm.count(kColorOptionLongName) && !script )
00142         {
00143                 color->enable();
00144                 descriptionMask |= sequenceParser::eMaskOptionsColor;
00145         }
00146         if ( vm.count(kEnableColorOptionLongName) && !script )
00147         {
00148                 const std::string str = vm[kEnableColorOptionLongName].as<std::string>();
00149                 if( string_to_boolean( str ) )
00150                 {
00151                         color->enable();
00152                         descriptionMask |= sequenceParser::eMaskOptionsColor;
00153                 }
00154                 else
00155                 {
00156                         color->disable();
00157                         remove( descriptionMask, sequenceParser::eMaskOptionsColor );
00158                 }
00159         }
00160         
00161         if (vm.count(kHelpOptionLongName))
00162         {
00163                 TUTTLE_LOG_INFO( color->_blue  << "TuttleOFX project [" << kUrlTuttleofxProject << "]" << color->_std );
00164                 TUTTLE_LOG_INFO( "" );
00165                 TUTTLE_LOG_INFO( color->_blue  << "NAME" << color->_std );
00166                 TUTTLE_LOG_INFO( color->_green << "\tsam-ls - list directory contents" << color->_std );
00167                 TUTTLE_LOG_INFO( "" );
00168                 TUTTLE_LOG_INFO( color->_blue  << "SYNOPSIS" << color->_std );
00169                 TUTTLE_LOG_INFO( color->_green << "\tsam-ls [options] [directories]" << color->_std );
00170                 TUTTLE_LOG_INFO( "" );
00171                 TUTTLE_LOG_INFO( color->_blue  << "DESCRIPTION" << color->_std );
00172                 TUTTLE_LOG_INFO( "" );
00173                 TUTTLE_LOG_INFO( "List information about the sequences, files and folders." );
00174                 TUTTLE_LOG_INFO( "List the current directory by default, and only sequences." );
00175                 TUTTLE_LOG_INFO( "The script option disable color, disable directory printing (in multi-directory case or recursive) and set relative path by default." );
00176                 TUTTLE_LOG_INFO( "" );
00177                 TUTTLE_LOG_INFO( color->_blue  << "OPTIONS" << color->_std );
00178                 TUTTLE_LOG_INFO( "" );
00179                 TUTTLE_LOG_INFO( mainOptions );
00180                 return 0;
00181         }
00182 
00183         if ( vm.count(kBriefOptionLongName) )
00184         {
00185                 TUTTLE_LOG_INFO( color->_green << "list directory contents" << color->_std );
00186                 return 0;
00187         }
00188 
00189         if (vm.count(kExpressionOptionLongName))
00190         {
00191                 TUTTLE_LOG_WARNING( "Expression: " << vm["expression"].as<std::string>() );
00192                 bal::split( filters, vm["expression"].as<std::string>(), bal::is_any_of(","));
00193         }
00194 
00195         if( vm.count(kDirectoriesOptionLongName ) | vm.count(kFilesOptionLongName) | vm.count(kSequencesOptionLongName) )
00196         {
00197                 researchMask &= ~sequenceParser::eMaskTypeDirectory;
00198                 researchMask &= ~sequenceParser::eMaskTypeFile;
00199                 researchMask &= ~sequenceParser::eMaskTypeSequence;
00200         }
00201                 
00202         if( vm.count(kDirectoriesOptionLongName ) )
00203         {
00204                 researchMask |= sequenceParser::eMaskTypeDirectory;
00205         }
00206         if (vm.count(kFilesOptionLongName))
00207         {
00208                 researchMask |= sequenceParser::eMaskTypeFile;
00209         }
00210         if (vm.count(kSequencesOptionLongName))
00211         {
00212                 researchMask |= sequenceParser::eMaskTypeSequence;
00213         }
00214         
00215         if (vm.count(kFullDisplayOptionLongName))
00216         {
00217                 researchMask |= sequenceParser::eMaskTypeDirectory;
00218                 researchMask |= sequenceParser::eMaskTypeFile;
00219                 researchMask |= sequenceParser::eMaskTypeSequence;
00220         }
00221         
00222         if (vm.count(kAllOptionLongName))
00223         {
00224                 // add .* files
00225                 descriptionMask |= sequenceParser::eMaskOptionsDotFile;
00226         }
00227         
00228         if (vm.count(kLongListingOptionLongName))
00229         {
00230                 descriptionMask |= sequenceParser::eMaskOptionsProperties;
00231         }
00232         
00233         if (vm.count(kRelativePathOptionLongName) )
00234         {
00235                 descriptionMask |= sequenceParser::eMaskOptionsPath;
00236         }
00237 
00238         if(vm.count(kPathOptionLongName))
00239         {
00240                 descriptionMask |= sequenceParser::eMaskOptionsAbsolutePath;
00241         }
00242         
00243         // defines paths, but if no directory specify in command line, we add the current path
00244         if (vm.count(kInputDirOptionLongName))
00245         {
00246                 paths = vm[kInputDirOptionLongName].as< std::vector<std::string> >();
00247         }
00248         else
00249         {
00250                 paths.push_back( "./" );
00251         }
00252         
00253         if (vm.count(kRecursiveOptionLongName))
00254         {
00255                 recursiveListing = true;
00256         }
00257 
00258 
00259 //      for(uint i=0; i<filters.size(); i++)
00260 //      TUTTLE_LOG_TRACE( "filters = " << filters.at(i) );
00261 //      TUTTLE_LOG_TRACE( "research mask = " << researchMask );
00262 //      TUTTLE_LOG_TRACE( "options  mask = " << descriptionMask );
00263 
00264         std::list<boost::shared_ptr<sequenceParser::FileObject> > listing;
00265         try
00266         {
00267                 std::size_t index = 0;
00268                 BOOST_FOREACH( bfs::path path, paths )
00269                 {
00270                         if( path == bfs::path(".") )
00271                         {
00272                                 path = bfs::path("./");
00273                         }
00274                         if( ( paths.size() > 1 || recursiveListing ) && !script )
00275                         {
00276                                 if( index > 0 )
00277                                 {
00278                                         TUTTLE_LOG_INFO( "" );
00279                                 }
00280                                 TUTTLE_LOG_INFO( path.string() << ":");
00281                                 wasSthgDumped = true;
00282                         }
00283 
00284                         coutVec( sequenceParser::fileObjectInDirectory( path.string(), filters, researchMask, descriptionMask ) );
00285 
00286                         if(recursiveListing)
00287                         {
00288                                 for ( bfs::recursive_directory_iterator end, dir( path ); dir != end; ++dir )
00289                                 {
00290                                         if( bfs::is_directory( *dir ) )
00291                                         {
00292                                                 bfs::path currentPath = (bfs::path)*dir;
00293                                                 if( !script )
00294                                                         TUTTLE_LOG_INFO( "\n" << currentPath.string() << ":" );
00295 
00296                                                 coutVec( sequenceParser::fileObjectInDirectory( currentPath.string(), filters, researchMask, descriptionMask ) );
00297 
00298                                         }
00299                                 }
00300                         }
00301                         ++index;
00302                 }
00303         }
00304         catch ( const bfs::filesystem_error& ex)
00305         {
00306                 TUTTLE_LOG_ERROR( ex.what() );
00307         }
00308         catch( ... )
00309         {
00310                 TUTTLE_LOG_ERROR( boost::current_exception_diagnostic_information() );
00311         }
00312         
00313         if(!wasSthgDumped)
00314         {
00315                 TUTTLE_LOG_ERROR( "No sequence found here." );
00316         }
00317         
00318         return 0;
00319 }