int main( int argc, char** argv ) { using namespace sam; sp::EMaskType researchMask = sp::eMaskTypeSequence; // by default show sequences sp::EMaskOptions descriptionMask = sp::eMaskOptionsColor; // by default show nothing bool recursiveListing = false; std::vector<std::string> paths; std::vector<std::string> filters; // Declare the supported options. bpo::options_description mainOptions; mainOptions.add_options() (kAllOptionString , kAllOptionMessage) (kDirectoriesOptionString , kDirectoriesOptionMessage) (kExpressionOptionString , bpo::value<std::string>(), kExpressionOptionMessage) (kFilesOptionString , kFilesOptionMessage) (kHelpOptionString , kHelpOptionMessage) (kIgnoreOptionString , kIgnoreOptionMessage) (kPathOptionString , kPathOptionMessage) (kRecursiveOptionString , kRecursiveOptionMessage ) (kVerboseOptionString , kVerboseOptionMessage) (kColorOptionString , kColorOptionMessage) (kFirstImageOptionString , bpo::value<std::ssize_t>(), kFirstImageOptionMessage) (kLastImageOptionString , bpo::value<std::ssize_t>(), kLastImageOptionMessage) (kFullRMPathOptionString , kFullRMPathOptionMessage ) (kBriefOptionString , kBriefOptionMessage ) ; // describe hidden options bpo::options_description hidden; hidden.add_options() (kInputDirOptionString, bpo::value< std::vector<std::string> >(), kInputDirOptionMessage) (kEnableColorOptionString, bpo::value<std::string>(), kEnableColorOptionMessage) ; // define default options bpo::positional_options_description pod; pod.add(kInputDirOptionString, -1); bpo::options_description cmdline_options; cmdline_options.add(mainOptions).add(hidden); bpo::positional_options_description pd; pd.add("", -1); //parse the command line, and put the result in vm bpo::variables_map vm; bpo::notify(vm); try { bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).positional(pod).run(), vm); // get environment options and parse them if( const char* env_rm_options = std::getenv("SAM_RM_OPTIONS") ) { const std::vector<std::string> vecOptions = bpo::split_unix( env_rm_options, " " ); bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm); } if( const char* env_rm_options = std::getenv("SAM_OPTIONS") ) { const std::vector<std::string> vecOptions = bpo::split_unix( env_rm_options, " " ); bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm); } } catch( const bpo::error& e) { TUTTLE_COUT( "sam-rm: command line error: " << e.what() ); exit( -2 ); } catch(...) { TUTTLE_COUT("sam-rm: unknown error in command line."); exit( -2 ); } if ( vm.count(kColorOptionLongName) ) { enableColor = true; } if ( vm.count(kEnableColorOptionLongName) ) { const std::string str = vm[kEnableColorOptionLongName].as<std::string>(); enableColor = string_to_boolean( str ); } if( enableColor ) { descriptionMask |= sp::eMaskOptionsColor; _color.enable(); } if ( vm.count(kHelpOptionLongName ) ) { TUTTLE_COUT( _color._blue << "TuttleOFX project [http://sites.google.com/site/tuttleofx]" << _color._std << std::endl ); TUTTLE_COUT( _color._blue << "NAME" << _color._std ); TUTTLE_COUT( _color._green << "\tsam-rm - remove file sequences" << _color._std << std::endl ); TUTTLE_COUT( _color._blue << "SYNOPSIS" << _color._std ); TUTTLE_COUT( _color._green << "\tsam-rm [options] [sequence_pattern]" << _color._std << std::endl ); TUTTLE_COUT( _color._blue << "DESCRIPTION" << _color._std << std::endl ); TUTTLE_COUT( "Remove sequence of files, and could remove trees (folder, files and sequences)." << std::endl ); TUTTLE_COUT( _color._blue << "OPTIONS" << _color._std << std::endl ); TUTTLE_COUT( mainOptions ); TUTTLE_COUT( _color._blue << "EXAMPLES" << _color._std << std::left); SAM_EXAMPLE_TITLE_COUT( "Sequence possible definitions: "); SAM_EXAMPLE_LINE_COUT("Auto-detect padding : ", "[email protected]"); SAM_EXAMPLE_LINE_COUT("Padding of 8 (usual style): ", "seq.########.jpg"); SAM_EXAMPLE_LINE_COUT("Padding of 8 (printf style): ", "seq.%08d.jpg"); SAM_EXAMPLE_TITLE_COUT( "Delete: "); SAM_EXAMPLE_LINE_COUT("A sequence:", "sam-rm /path/to/sequence/[email protected]"); SAM_EXAMPLE_LINE_COUT("Sequences in a directory:", "sam-rm /path/to/sequence/"); return 0; } if ( vm.count(kBriefOptionLongName) ) { TUTTLE_COUT( _color._green << "remove file sequences" << _color._std); return 0; } if (vm.count(kExpressionOptionLongName)) { bal::split( filters, vm["expression"].as<std::string>(), bal::is_any_of(",")); } if (vm.count(kDirectoriesOptionLongName)) { researchMask |= sp::eMaskTypeDirectory; } if (vm.count(kFilesOptionLongName)) { researchMask |= sp::eMaskTypeFile; } if (vm.count(kIgnoreOptionLongName)) { researchMask &= ~sp::eMaskTypeSequence; } if (vm.count(kVerboseOptionLongName)) { verbose = true; } if (vm.count(kFirstImageOptionLongName)) { selectRange = true; firstImage = vm[kFirstImageOptionLongName].as< std::ssize_t >(); } if (vm.count(kLastImageOptionLongName)) { selectRange = true; lastImage = vm[kLastImageOptionLongName].as< std::ssize_t >(); } if (vm.count(kFullRMPathOptionLongName)) { researchMask |= sp::eMaskTypeDirectory; researchMask |= sp::eMaskTypeFile; researchMask |= sp::eMaskTypeSequence; } if (vm.count(kAllOptionLongName)) { // add .* files descriptionMask |= sp::eMaskOptionsDotFile; } if (vm.count(kPathOptionLongName)) { descriptionMask |= sp::eMaskOptionsPath; } // defines paths, but if no directory specify in command line, we add the current path if (vm.count(kInputDirOptionLongName)) { paths = vm[kInputDirOptionLongName].as< std::vector<std::string> >(); } else { TUTTLE_COUT( _color._error << "No sequence and/or directory are specified." << _color._std ); return 1; } if (vm.count(kRecursiveOptionLongName)) { recursiveListing = true; } // for(unsigned int i=0; i<filters.size(); i++) // TUTTLE_COUT("filters = " << filters.at(i)); // TUTTLE_COUT("research mask = " << researchMask); // TUTTLE_COUT("options mask = " << descriptionMask); try { std::vector<boost::filesystem::path> pathsNoRemoved; sp::Detector detector; BOOST_FOREACH( bfs::path path, paths ) { // TUTTLE_TCOUT( "path: "<< path ); if( bfs::exists( path ) ) { if( bfs::is_directory( path ) ) { //TUTTLE_TCOUT( "is a directory" ); if(recursiveListing) { for ( bfs::recursive_directory_iterator end, dir(path); dir != end; ++dir ) { if( bfs::is_directory( *dir ) ) { //TUTTLE_TCOUT( *dir ); boost::ptr_vector<sp::FileObject> listing = detector.fileObjectInDirectory( ( (bfs::path) *dir ).string(), filters, researchMask, descriptionMask ); removeFileObject( listing, pathsNoRemoved ); } } } boost::ptr_vector<sp::FileObject> listing = detector.fileObjectInDirectory( path.string(), filters, researchMask, descriptionMask ); removeFileObject( listing, pathsNoRemoved ); } else { //TUTTLE_TCOUT( "is NOT a directory "<< path.branch_path() << " | "<< path.leaf() ); filters.push_back( path.leaf().string() ); boost::ptr_vector<sp::FileObject> listing = detector.fileObjectInDirectory( path.branch_path().string(), filters, researchMask, descriptionMask ); removeFileObject( listing, pathsNoRemoved ); } } else { // TUTTLE_TCOUT( "not exist ...." ); try { sp::Sequence s(path.branch_path(), descriptionMask ); s.initFromDetection( path.string(), sp::Sequence::ePatternDefault ); if( s.getNbFiles() ) { // TUTTLE_TCOUT( s ); removeSequence( s ); } } catch(... ) { TUTTLE_CERR ( _color._error << "Unrecognized pattern \"" << path << "\"" << _color._std ); } } } // delete not empty folder the first time removeFiles( pathsNoRemoved ); } catch (bfs::filesystem_error &ex) { TUTTLE_COUT( _color._error << ex.what() << _color._std ); } catch(... ) { TUTTLE_CERR ( _color._error << boost::current_exception_diagnostic_information() << _color._std ); } return 0; }
int sammvcp( int argc, char** argv ) { ttl::EMaskOptions descriptionMask = ttl::eMaskOptionsNone; // by default show nothing std::string availableExtensions; std::vector<std::string> paths; std::vector<std::string> filters; std::string outputPattern; bool verbose = false; bool dstIsSeq = false; std::ssize_t offset = 0; bool hasInputFirst = false; std::ssize_t inputFirst = 0; bool hasInputLast = false; std::ssize_t inputLast = 0; std::ssize_t outputFirst = 0; std::ssize_t outputLast = 0; typedef enum { eOffsetModeNotSet, eOffsetModeValue, eOffsetModeFirstTime, eOffsetModeLastTime, } EOffsetMode; EOffsetMode offsetMode = eOffsetModeNotSet; // Declare the supported options. bpo::options_description mainOptions; mainOptions.add_options( ) ( "help,h" , "show this help" ) ( "offset,o" , bpo::value<std::ssize_t>( ), "retime the sequence with the given offset. ex: -o 1, -o \"-10\"" ) // ( "force,f" , bpo::value<bool>( ) , "if a destination file exists, replace it" ) ( "verbose,v" , "explain what is being done" ) ( "input-first" , bpo::value<std::ssize_t>( ), "specify the first input image, in order to select a sub-range of the input sequence" ) ( "input-last" , bpo::value<std::ssize_t>( ), "specify the last input image, in order to select a sub-range of the input sequence" ) ( "output-first", bpo::value<std::ssize_t>( ), "specify the first output image, in order to retime the sequence. It's another way to create an offset of your sequence." ) ( "output-last" , bpo::value<std::ssize_t>( ), "specify the last output image, in order to retime the sequence" ) ( "color" , "display with colors" ) ( "brief" , "brief summary of the tool" ) ; // describe hidden options bpo::options_description hidden; hidden.add_options( ) ( "input", bpo::value< std::vector<std::string> >( ), "input sequences, files, directories" ) ( "enable-color", bpo::value<std::string>(), "enable/disable color") ; // define default options bpo::positional_options_description pod; pod.add( "input", -1 ); bpo::options_description cmdline_options; cmdline_options.add( mainOptions ).add( hidden ); //parse the command line, and put the result in vm bpo::variables_map vm; try { bpo::store( bpo::command_line_parser( argc, argv ).options( cmdline_options ).positional( pod ).run( ), vm ); // get environnement options and parse them if( const char* env_options = std::getenv( SAM_MV_OR_CP_OPTIONS ) ) { const std::vector<std::string> vecOptions = bpo::split_unix( env_options, " " ); bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm); } if( const char* env_options = std::getenv( "SAM_OPTIONS" ) ) { const std::vector<std::string> vecOptions = bpo::split_unix( env_options, " " ); bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm); } bpo::notify( vm ); } catch( const bpo::error& e) { TUTTLE_COUT( SAM_TOOL ": command line error: " << e.what() ); exit( -2 ); } catch(...) { TUTTLE_COUT( SAM_TOOL ": unknown error in command line."); exit( -2 ); } if ( vm.count("color") ) { enableColor = true; } if ( vm.count("enable-color") ) { const std::string str = vm["enable-color"].as<std::string>(); enableColor = string_to_boolean(str); } if( enableColor ) { using namespace tuttle::common; _color.enable(); } if( vm.count( "help" ) ) { TUTTLE_COUT( _color._blue << "TuttleOFX project [http://sites.google.com/site/tuttleofx]" << _color._std << std::endl ); #ifndef SAM_MOVEFILES TUTTLE_COUT( _color._blue <<"NAME" << _color._std ); TUTTLE_COUT( _color._green << "\tsam-cp - copy sequence(s) in a directory" << _color._std << std::endl ); TUTTLE_COUT( _color._blue << "SYNOPSIS" << _color._std ); TUTTLE_COUT( _color._green << "\tsam-cp [options] sequence[s] [outputDirectory][outputSequence]" << _color._std << std::endl ); #else TUTTLE_COUT( _color._blue << "NAME" << _color._std ); TUTTLE_COUT( _color._green << "\tsam-mv - move sequence(s) in a directory" << _color._std << std::endl ); TUTTLE_COUT( _color._blue << "SYNOPSIS" << _color._std ); TUTTLE_COUT( _color._green << "\tsam-mv [options] sequence[s] [outputDirectory][outputSequence]" << _color._std << std::endl ); #endif TUTTLE_COUT( _color._blue << "DESCRIPTION" << _color._std << std::endl ); #ifndef SAM_MOVEFILES TUTTLE_COUT( "Copy sequence of image files, and could remove trees (folder, files and sequences)." << std::endl ); #else TUTTLE_COUT( "Move sequence of image files, and could remove trees (folder, files and sequences)." << std::endl ); #endif TUTTLE_COUT( _color._blue << "OPTIONS" <<_color._std ); TUTTLE_COUT( mainOptions ); return 1; } if ( vm.count("brief") ) { #ifndef SAM_MOVEFILES TUTTLE_COUT( _color._green << "copy sequence(s) in a directory" << _color._std ); #else TUTTLE_COUT( _color._green << "move sequence(s) in a directory" << _color._std ); #endif return 0; } if( vm.count( "expression" ) ) { bal::split( filters, vm["expression"].as<std::string > ( ), bal::is_any_of( "," ) ); } if( vm.count( "all" ) ) { // add .* files descriptionMask |= ttl::eMaskOptionsDotFile; } // defines paths if( vm.count( "input" ) ) { paths = vm["input"].as< std::vector<std::string> >(); } if( paths.size( ) < 2 ) { TUTTLE_COUT( _color._error << "No sequence and/or directory are specified." << _color._std ); return 1; } if( vm.count( "offset" ) ) { offset = vm["offset"].as<std::ssize_t>( ); offsetMode = eOffsetModeValue; } if( vm.count( "input-first" ) ) { hasInputFirst = true; inputFirst = vm["input-first"].as<std::ssize_t>( ); } if( vm.count( "input-last" ) ) { hasInputLast = true; inputLast = vm["input-last"].as<std::ssize_t>( ); } if( vm.count( "output-first" ) ) { outputFirst = vm["output-first"].as<std::ssize_t>( ); if( offsetMode != eOffsetModeNotSet ) { TUTTLE_CERR( _color._error << "You can't cumulate multiple options to modify the time." << _color._std ); return -1; } offsetMode = eOffsetModeFirstTime; } if( vm.count( "output-last" ) ) { outputLast = vm["output-last"].as<std::ssize_t>( ); if( offsetMode != eOffsetModeNotSet ) { TUTTLE_CERR( _color._error << "You can't cumulate multiple options to modify the time." << _color._std ); return -1; } offsetMode = eOffsetModeLastTime; } if( vm.count( "verbose" ) ) { verbose = true; } bfs::path dstPath = paths.back( ); paths.pop_back( ); std::string sequencePattern; if( ! bfs::is_directory( dstPath ) ) { sequencePattern = dstPath.filename( ).string( ); dstPath = dstPath.parent_path( ); if( ! dstPath.empty() && ! bfs::is_directory( dstPath ) ) { TUTTLE_CERR( _color._error << "Your destination is not in a valid directory: " << tuttle::quotes(dstPath.string()) << "." << _color._std ); return -1; } } else { if( paths.size( ) > 1 ) { TUTTLE_CERR( _color._error << "To copy multiple sequences, your destination must be a directory: " << tuttle::quotes(dstPath.string()) << "." << _color._std ); return -1; } sequencePattern = ""; } ttl::Sequence dstSeq( dstPath, descriptionMask ); if( sequencePattern.size( ) > 0 ) { dstIsSeq = dstSeq.initFromPattern( dstPath, sequencePattern, 0, 0, 1, descriptionMask, ttl::Sequence::ePatternAll ); if( ! dstIsSeq ) // there is a pattern, but it's not valid. { TUTTLE_CERR( _color._error << "Your destination " << tuttle::quotes(sequencePattern) << " is not a valid pattern. Your destination can be a directory or a pattern." << _color._std ); return -1; } } try { BOOST_FOREACH( const bfs::path& srcPath, paths ) { ttl::Sequence srcSeq( srcPath.branch_path( ), descriptionMask ); const bool srcIsSeq = srcSeq.initFromDetection( srcPath.string( ), ttl::Sequence::ePatternDefault ); if( ! srcIsSeq ) { TUTTLE_CERR( _color._error << "Input is not a sequence: " << tuttle::quotes(srcPath.string()) << "." << _color._std ); return -1; } if( srcSeq.getNbFiles( ) == 0 ) { TUTTLE_CERR( _color._error << "No existing file for the input sequence: " << tuttle::quotes(srcPath.string()) << "." << _color._std ); return -1; } ttl::Sequence::Time first = hasInputFirst ? inputFirst : srcSeq.getFirstTime(); ttl::Sequence::Time last = hasInputLast ? inputLast : srcSeq.getLastTime(); switch( offsetMode ) { case eOffsetModeNotSet: { offset = 0; break; } case eOffsetModeValue: { // set by "offset" command line option break; } case eOffsetModeFirstTime: { // set by "input-first" command line option offset = outputFirst - first; break; } case eOffsetModeLastTime: { // set by "input-last" command line option offset = outputLast - last; break; } } if( dstIsSeq ) { if( verbose ) { TUTTLE_COUT( srcSeq.getAbsoluteStandardPattern( ) << " -> " << dstSeq.getAbsoluteStandardPattern( ) << " (" << srcSeq.getNbFiles( ) << ") " ); } copy_sequence( srcSeq, first, last, dstSeq, offset ); } else { if( verbose ) { TUTTLE_COUT( srcSeq.getAbsoluteStandardPattern( ) << " -> " << dstPath / srcSeq.getStandardPattern( ) << " (" << srcSeq.getNbFiles( ) << ")" ); } copy_sequence( srcSeq, first, last, dstPath, offset ); } } } catch( bfs::filesystem_error &ex ) { TUTTLE_COUT( _color._error << ex.what( ) << _color._std ); return -2; } catch( ... ) { TUTTLE_CERR( _color._error << boost::current_exception_diagnostic_information( ) << _color._std ); return -3; } return 0; }
int main( int argc, char** argv ) { std::vector<std::string> plugins; std::vector<std::string> foundPlugins; std::vector<std::string> filters; using namespace sam; // Declare the supported options. bpo::options_description mainOptions; mainOptions.add_options() (kHelpOptionString , kHelpOptionMessage) (kAllOptionString , kAllOptionMessage) (kFilterOptionString , bpo::value<std::string>(), kFilterOptionMessage) (kColorOptionString , kColorOptionMessage) (kPropertiesOptionString , kPropertiesOptionMessage) (kClipsOptionString , kClipsOptionMessage) (kParametersOptionString , kParametersOptionMessage) (kBriefOptionString , kBriefOptionMessage) ; // describe hidden options bpo::options_description hidden; hidden.add_options() (kInputDirOptionString, bpo::value< std::vector<std::string> >(), kInputDirOptionMessage) ; // define default options bpo::positional_options_description pod; pod.add(kInputDirOptionLongName, -1); bpo::options_description cmdline_options; cmdline_options.add(mainOptions).add(hidden); //parse the command line, and put the result in vm bpo::variables_map vm; try { bpo::store(bpo::command_line_parser(argc, argv).options(cmdline_options).positional(pod).run(), vm); // get environnement options and parse them if( const char* env_plugins_options = std::getenv("SAM_PLUGINS_OPTIONS") ) { const std::vector<std::string> vecOptions = bpo::split_unix( env_plugins_options, " " ); bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm); } if( const char* env_options = std::getenv("SAM_OPTIONS") ) { const std::vector<std::string> vecOptions = bpo::split_unix( env_options, " " ); bpo::store(bpo::command_line_parser(vecOptions).options(cmdline_options).positional(pod).run(), vm); } bpo::notify(vm); } catch( const bpo::error& e) { TUTTLE_COUT( "sam-plugins: command line error: " << e.what() ); exit( -2 ); } catch(...) { TUTTLE_COUT( "sam-plugins: unknown error in command line."); exit( -2 ); } if (vm.count(kColorOptionLongName)) { color = true; _color.enable(); } if( vm.count(kHelpOptionLongName) ) { TUTTLE_COUT( _color._blue << "TuttleOFX project [http://sites.google.com/site/tuttleofx]" << _color._std << std::endl ); TUTTLE_COUT( _color._blue << "NAME" << _color._std ); TUTTLE_COUT( _color._green << "\tsam-plugins - show informations about OpenFX plugins" << _color._std << std::endl ); TUTTLE_COUT( _color._blue << "SYNOPSIS" << _color._std ); TUTTLE_COUT( _color._green << "\tsam-plugins [options] [specific_OpenFX_plugin]" << _color._std << std::endl ); TUTTLE_COUT( _color._blue << "DESCRIPTION" << _color._std ); TUTTLE_COUT( "List OpenFX in OFX_PLUGIN_PATH by default."); TUTTLE_COUT( "And could print properties, parameters and clips for each plugins" << std::endl ); TUTTLE_COUT( _color._blue << "OPTIONS" << _color._std ); TUTTLE_COUT( mainOptions ); return 0; } if ( vm.count(kBriefOptionLongName) ) { TUTTLE_COUT( _color._green << "show informations about OpenFX plugins" << _color._std ); return 0; } // defines plugins if( vm.count(kInputDirOptionLongName) ) { plugins = vm[kInputDirOptionLongName].as< std::vector<std::string> >(); } if( vm.count(kFilterOptionLongName) ) { bal::split( filters, vm[kFilterOptionLongName].as<std::string>(), bal::is_any_of(",")); } if( vm.count(kAllOptionLongName) | (plugins.size() == 0) ) { tth::Core::instance().preload(); const std::vector<tth::ofx::imageEffect::OfxhImageEffectPlugin*> plugs = tth::Core::instance().getImageEffectPluginCache().getPlugins(); for( std::size_t i = 0; i < plugs.size(); ++i ) { const std::string plugName = plugs.at(i)->getRawIdentifier(); if( isNotFiltered( plugName, filters) ) { TUTTLE_COUT( plugName ); } } return 0; } if (vm.count(kPropertiesOptionLongName)) { properties = true; } if (vm.count(kClipsOptionLongName)) { clips = true; } if (vm.count(kParametersOptionLongName)) { parameters = true; } // for(unsigned int i=0; i< plugins.size(); i++) // TUTTLE_COUT( plugins.at(i) ); try { tth::Core::instance().preload(); // get the plugins names for research partials names (rawreader need to make reference to the plug tuttle.reader) const std::vector<tth::ofx::imageEffect::OfxhImageEffectPlugin*> plugs = tth::Core::instance().getImageEffectPluginCache().getPlugins(); unsigned int founded; BOOST_FOREACH( const std::string& plugin, plugins ) { std::vector< std::string > termsPlugin; bal::split( termsPlugin, plugin, bal::is_any_of(".")); for( std::size_t i=0; i<plugs.size(); i++ ) { founded = 0; for( std::size_t t=0; t<termsPlugin.size(); t++ ) { std::size_t found1 = plugs.at(i)->getRawIdentifier().find( "."+termsPlugin.at(t) ); std::size_t found2 = plugs.at(i)->getRawIdentifier().find( termsPlugin.at(t)+"." ); if( ( found1 == std::string::npos ) && ( found2 == std::string::npos ) ) { break; } ++founded; if( founded == termsPlugin.size() ) { /*TUTTLE_COUT("plug is " << plugs.at(i)->getRawIdentifier() );*/ foundPlugins.push_back( plugs.at(i)->getRawIdentifier() ); } } } } TUTTLE_COUT( _color._red << "################################################################################" << _color._std ); BOOST_FOREACH( const std::string& plugin, foundPlugins ) { TUTTLE_COUT(_color._blue << "PLUGIN DESCRIPTION" << _color._std ); getPluginProperties( plugin ); TUTTLE_COUT( _color._red << "################################################################################" << _color._std ); }