00001 #ifndef NO_GPL
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #else
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #endif
00056
00057
00058 #include <rtt/Logger.hpp>
00059 #include <rtt/MultiVector.hpp>
00060 #include <rtt/TypeStream.hpp>
00061 #include "TaskBrowser.hpp"
00062
00063 #include "rtt/TryCommand.hpp"
00064 #include <rtt/TaskContext.hpp>
00065 #include <rtt/scripting/parser-debug.hpp>
00066 #include <rtt/scripting/Parser.hpp>
00067 #include <rtt/scripting/ProgramLoader.hpp>
00068 #include <rtt/scripting/parse_exception.hpp>
00069 #include <rtt/scripting/PeerParser.hpp>
00070
00071 #include <iostream>
00072 #include <fstream>
00073 #include <sstream>
00074 #include <iomanip>
00075 #include <deque>
00076 #include <stdio.h>
00077 #ifndef NO_GPL
00078 #include <readline/readline.h>
00079 #include <readline/history.h>
00080 #endif
00081 #include <boost/bind.hpp>
00082 #include <boost/lambda/lambda.hpp>
00083
00084 #include <signal.h>
00085
00086 namespace OCL
00087 {
00088 using namespace RTT;
00089 using namespace RTT::detail;
00090 #ifndef NO_GPL
00091 std::vector<std::string> TaskBrowser::candidates;
00092 std::vector<std::string> TaskBrowser::completes;
00093 std::vector<std::string>::iterator TaskBrowser::complete_iter;
00094 std::string TaskBrowser::component;
00095 std::string TaskBrowser::peerpath;
00096 std::string TaskBrowser::text;
00097 #endif
00098 TaskContext* TaskBrowser::taskcontext = 0;
00099 OperationInterface* TaskBrowser::taskobject = 0;
00100 TaskContext* TaskBrowser::peer = 0;
00101 TaskContext* TaskBrowser::tb = 0;
00102 TaskContext* TaskBrowser::context = 0;
00103
00104 using boost::bind;
00105 using namespace RTT;
00106 using namespace std;
00107
00108 string TaskBrowser::red("\e[m\e[1;31m");
00109 string TaskBrowser::green("\e[m\e[1;32m");
00110 string TaskBrowser::blue("\e[m\e[1;34m");
00111
00115 static std::ostream&
00116 nl(std::ostream& __os)
00117 { return __os.put(__os.widen('\n')); }
00118
00119
00120 void ctrl_c_catcher(int sig)
00121 {
00122 ::signal(sig, SIG_IGN);
00123 #ifndef NO_GPL
00124
00125
00126
00127 rl_free_line_state();
00128
00129 #endif
00130 ::signal(SIGINT, ctrl_c_catcher);
00131 }
00132
00133 #ifndef NO_GPL
00134 char *TaskBrowser::rl_gets ()
00135 {
00136
00137
00138 if (line_read)
00139 {
00140 free (line_read);
00141 line_read = 0;
00142 }
00143
00144
00145 std::string p;
00146 if ( !macrorecording ) {
00147 p = prompt;
00148 } else {
00149 p = "> ";
00150 }
00151
00152 if (rl_set_signals() != 0)
00153 cerr << "Error setting signals !" <<endl;
00154 line_read = readline ( p.c_str() );
00155
00156
00157
00158 if (line_read && *line_read) {
00159
00160 string s = line_read;
00161 if (s != "quit")
00162 add_history (line_read);
00163 }
00164 return (line_read);
00165 }
00166
00167 char* TaskBrowser::dupstr( const char *s )
00168 {
00169 char * rv;
00170
00171 rv = (char*) malloc( strlen( s ) + 1 );
00172 strcpy( rv, s );
00173 return rv;
00174 }
00175
00176 char *TaskBrowser::command_generator( const char *_text, int state )
00177 {
00178
00179 if ( !state )
00180 {
00181
00182 text = _text;
00183
00184 completes.clear();
00185 find_completes();
00186 complete_iter = completes.begin();
00187 }
00188 else
00189 ++complete_iter;
00190
00191
00192 if ( complete_iter == completes.end() )
00193 return 0;
00194
00195 return dupstr( complete_iter->c_str() );
00196 }
00197
00202 void TaskBrowser::find_completes() {
00203 std::string::size_type pos;
00204 std::string::size_type startpos;
00205 std::string line( rl_line_buffer );
00206
00207
00208 if ( line.find(std::string("cd ")) == 0 || line.find(std::string("ls ")) == 0) {
00209
00210
00211 pos = line.find(" ");
00212 startpos = line.find_last_of(". ");
00213
00214
00215 peer = taskcontext;
00216 if ( pos+1 != line.length() )
00217 peer = findPeer( line.substr(pos+1) );
00218
00219
00220 TaskContext::PeerList v = peer->getPeerList();
00221 for (TaskContext::PeerList::iterator i = v.begin(); i != v.end(); ++i) {
00222 std::string path;
00223 if ( !( pos+1 > startpos) )
00224 path = line.substr(pos+1, startpos - pos);
00225
00226 if ( *i == line.substr(startpos+1) )
00227 completes.push_back( path + *i + ".");
00228 else
00229 if ( startpos == std::string::npos || startpos+1 == line.length() || i->find( line.substr(startpos+1)) == 0 )
00230 completes.push_back( path + *i );
00231 }
00232
00233 if (line.find(std::string("cd ")) == 0)
00234 return;
00235
00236 v = peer->getObjectList();
00237 for (TaskContext::PeerList::iterator i = v.begin(); i != v.end(); ++i) {
00238 std::string path;
00239 if ( !( pos+1 > startpos) )
00240 path = line.substr(pos+1, startpos - pos);
00241
00242 if ( *i == line.substr(startpos+1) )
00243 completes.push_back( path + *i + ".");
00244 else
00245 if ( startpos == std::string::npos || startpos+1 == line.length() || i->find( line.substr(startpos+1)) == 0 )
00246 completes.push_back( path + *i );
00247 }
00248 return;
00249 }
00250
00251
00252 if ( line.find(std::string(".")) == 0 ) {
00253
00254 std::vector<std::string> tbcoms;
00255 tbcoms.push_back(".loadProgram ");
00256 tbcoms.push_back(".unloadProgram ");
00257 tbcoms.push_back(".loadStateMachine ");
00258 tbcoms.push_back(".unloadStateMachine ");
00259 tbcoms.push_back(".light");
00260 tbcoms.push_back(".dark");
00261 tbcoms.push_back(".nocolors");
00262 tbcoms.push_back(".connect");
00263 tbcoms.push_back(".record");
00264 tbcoms.push_back(".end");
00265 tbcoms.push_back(".cancel");
00266
00267
00268 for( std::vector<std::string>::iterator it = tbcoms.begin();
00269 it != tbcoms.end();
00270 ++it)
00271 if ( it->find(line) == 0 )
00272 completes.push_back( *it );
00273 return;
00274 }
00275
00276 if ( line.find(std::string("list ")) == 0
00277 || line.find(std::string("trace ")) == 0
00278 || line.find(std::string("untrace ")) == 0) {
00279 stringstream ss( line.c_str() );
00280 string lcommand;
00281 ss >> lcommand;
00282 lcommand += ' ';
00283 std::vector<std::string> progs;
00284
00285
00286 progs = context->scripting()->getPrograms();
00287
00288 for( std::vector<std::string>::iterator it = progs.begin();
00289 it != progs.end();
00290 ++it) {
00291 string res = lcommand + *it;
00292 if ( res.find(line) == 0 )
00293 completes.push_back( *it );
00294 }
00295 progs = context->scripting()->getStateMachines();
00296 for( std::vector<std::string>::iterator it = progs.begin();
00297 it != progs.end();
00298 ++it) {
00299 string res = lcommand + *it;
00300 if ( res.find(line) == 0 )
00301 completes.push_back( *it );
00302 }
00303
00304 return;
00305 }
00306
00307 startpos = text.find_last_of(",( ");
00308 if ( startpos == std::string::npos )
00309 startpos = 0;
00310
00311
00312 find_peers(startpos);
00313
00314
00315
00316
00317
00318
00319 std::string comp = component;
00320
00321
00322
00323
00324
00325 find_ops();
00326
00327
00328
00329 if ( line.empty() ) {
00330 completes.push_back("cd ");
00331 completes.push_back("cd ..");
00332 completes.push_back("ls");
00333 completes.push_back("help");
00334 completes.push_back("quit");
00335 completes.push_back("list");
00336 completes.push_back("trace");
00337 completes.push_back("untrace");
00338 if (taskcontext == context)
00339 completes.push_back("leave");
00340 else
00341 completes.push_back("enter");
00342
00343 }
00344
00345
00346 if ( !text.empty() ) {
00347 if ( std::string( "cd " ).find(text) == 0 )
00348 completes.push_back("cd ");
00349 if ( std::string( "ls" ).find(text) == 0 )
00350 completes.push_back("ls");
00351 if ( std::string( "cd .." ).find(text) == 0 )
00352 completes.push_back("cd ..");
00353 if ( std::string( "help" ).find(text) == 0 )
00354 completes.push_back("help");
00355 if ( std::string( "quit" ).find(text) == 0 )
00356 completes.push_back("quit");
00357 if ( std::string( "list " ).find(text) == 0 )
00358 completes.push_back("list ");
00359 if ( std::string( "trace " ).find(text) == 0 )
00360 completes.push_back("trace ");
00361 if ( std::string( "untrace " ).find(text) == 0 )
00362 completes.push_back("untrace ");
00363
00364 if (taskcontext == context && string("leave").find(text) == 0)
00365 completes.push_back("leave");
00366
00367 if (context == tb && string("enter").find(text) == 0)
00368 completes.push_back("enter");
00369 }
00370 }
00371
00372 void TaskBrowser::find_ops()
00373 {
00374
00375
00376 std::vector<std::string> attrs;
00377 attrs = taskobject->attributes()->names();
00378 for (std::vector<std::string>::iterator i = attrs.begin(); i!= attrs.end(); ++i ) {
00379 if ( i->find( component ) == 0 && !component.empty() )
00380 completes.push_back( peerpath + *i );
00381 }
00382
00383 if (taskobject == peer && peer->properties() != 0 ) {
00384 std::vector<std::string> props;
00385 peer->properties()->list(props);
00386 for (std::vector<std::string>::iterator i = props.begin(); i!= props.end(); ++i ) {
00387 if ( i->find( component ) == 0 && !component.empty() ) {
00388 completes.push_back( peerpath + *i );
00389 }
00390 }
00391 }
00392
00393
00394 std::vector<std::string> comps;
00395 comps = taskobject->commands()->getNames();
00396 for (std::vector<std::string>::iterator i = comps.begin(); i!= comps.end(); ++i ) {
00397 if ( i->find( component ) == 0 )
00398 completes.push_back( peerpath + *i );
00399 }
00400
00401 comps = taskobject->methods()->getNames();
00402 for (std::vector<std::string>::iterator i = comps.begin(); i!= comps.end(); ++i ) {
00403 if ( i->find( component ) == 0 )
00404 completes.push_back( peerpath + *i );
00405 }
00406
00407 comps = taskobject->events()->getNames();
00408 for (std::vector<std::string>::iterator i = comps.begin(); i!= comps.end(); ++i ) {
00409 if ( i->find( component ) == 0 )
00410 completes.push_back( peerpath + *i );
00411 }
00412 }
00413
00414 void TaskBrowser::find_peers( std::string::size_type startpos )
00415 {
00416 peerpath.clear();
00417 peer = context;
00418 taskobject = context;
00419
00420 std::string to_parse = text.substr(startpos);
00421 startpos = 0;
00422 std::string::size_type endpos = 0;
00423
00424 component.clear();
00425 peerpath.clear();
00426 while (endpos != std::string::npos )
00427 {
00428 bool itemfound = false;
00429 endpos = to_parse.find(".");
00430 if ( endpos == startpos ) {
00431 component.clear();
00432 break;
00433 }
00434 std::string item = to_parse.substr(startpos, endpos);
00435
00436 if ( taskobject->getObject( item ) ) {
00437 taskobject = peer->getObject(item);
00438 itemfound = true;
00439 } else
00440 if ( peer->hasPeer( item ) ) {
00441 peer = peer->getPeer( item );
00442 taskobject = peer;
00443 itemfound = true;
00444 }
00445 if ( itemfound ) {
00446 peerpath += to_parse.substr(startpos, endpos) + ".";
00447 if ( endpos != std::string::npos )
00448 to_parse = to_parse.substr(endpos + 1);
00449 else
00450 to_parse.clear();
00451 startpos = 0;
00452 }
00453 else {
00454
00455
00456 component = item;
00457 break;
00458 }
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469 TaskContext::PeerList v;
00470 if ( taskobject == peer ) {
00471
00472 v = peer->getPeerList();
00473 for (TaskContext::PeerList::iterator i = v.begin(); i != v.end(); ++i) {
00474 if ( i->find( component ) == 0 ) {
00475 completes.push_back( peerpath + *i );
00476 completes.push_back( peerpath + *i + "." );
00477
00478 }
00479 }
00480 }
00481
00482 v = taskobject->getObjectList();
00483 for (TaskContext::PeerList::iterator i = v.begin(); i != v.end(); ++i) {
00484 if ( i->find( component ) == 0 ) {
00485 completes.push_back( peerpath + *i );
00486 if ( *i != "this" )
00487 completes.push_back( peerpath + *i + "." );
00488
00489 }
00490 }
00491 return;
00492 }
00493
00494 char ** TaskBrowser::orocos_hmi_completion ( const char *text, int start, int end )
00495 {
00496 char **matches;
00497 matches = ( char ** ) 0;
00498
00499 matches = rl_completion_matches ( text, &TaskBrowser::command_generator );
00500
00501 return ( matches );
00502 }
00503 #endif // !NO_GPL
00504
00505 TaskBrowser::TaskBrowser( TaskContext* _c )
00506 : TaskContext("TaskBrowser"),
00507 command(0),
00508 debug(0),
00509 line_read(0),
00510 lastc(0), storedname(""), storedline(-1),
00511 macrorecording(false)
00512 {
00513 tb = this;
00514 context = tb;
00515 this->switchTaskContext(_c);
00516 #ifndef NO_GPL
00517 rl_completion_append_character = '\0';
00518 rl_attempted_completion_function = &TaskBrowser::orocos_hmi_completion;
00519
00520 if ( read_history(".tb_history") != 0 ) {
00521 read_history("~/.tb_history");
00522 }
00523 #endif
00524
00525 this->setColorTheme( darkbg );
00526 this->enterTask();
00527 }
00528
00529 TaskBrowser::~TaskBrowser() {
00530 #ifndef NO_GPL
00531 if (line_read)
00532 {
00533 free (line_read);
00534 }
00535 if ( write_history(".tb_history") != 0 ) {
00536 write_history("~/.tb_history");
00537 }
00538 #endif
00539 }
00540
00544 char getTaskStatusChar(TaskContext* t)
00545 {
00546 if (t->isRunning() )
00547 return 'R';
00548 if (t->isConfigured() )
00549 return 'S';
00550 return 'U';
00551 }
00552
00553 char getStateMachineStatusChar(TaskContext* t, string progname)
00554 {
00555 string ps = t->scripting()->getStateMachineStatus(progname);
00556 return toupper(ps[0]);
00557 }
00558
00559 char getProgramStatusChar(TaskContext* t, string progname)
00560 {
00561 string ps = t->scripting()->getProgramStatus(progname);
00562 return toupper(ps[0]);
00563 }
00564
00565 void str_trim(string& str, char to_trim)
00566 {
00567 string::size_type pos1 = str.find_first_not_of(to_trim);
00568 string::size_type pos2 = str.find_last_not_of(to_trim);
00569 str = str.substr(pos1 == string::npos ? 0 : pos1,
00570 pos2 == string::npos ? str.length() - 1 : pos2 - pos1 + 1);
00571 }
00572
00573
00578 void TaskBrowser::loop()
00579 {
00580 using boost::lambda::_1;
00581
00582
00583 ::signal( SIGINT, ctrl_c_catcher );
00584 #ifndef NO_GPL
00585
00586 if(rl_catch_signals == 0)
00587 cerr << "Error: not catching signals !"<<endl;
00588 if (rl_set_signals() != 0)
00589 cerr << "Error setting signals !" <<endl;
00590 #endif
00591 cout << nl<<
00592 coloron <<
00593 " This console reader allows you to browse and manipulate TaskContexts."<<nl<<
00594 " You can type in a command, event, method, expression or change variables."<<nl;
00595 cout <<" (type '"<<underline<<"help"<<coloroff<<coloron<<"' for instructions)"<<nl;
00596 #ifndef NO_GPL
00597 cout << " TAB completion and HISTORY is available ('bash' like)" <<coloroff<<nl<<nl;
00598 #else
00599 cout << " TAB completion and history is NOT available (LGPL-version)" <<coloroff<<nl<<nl;
00600 #endif
00601 while (1)
00602 {
00603 if (!macrorecording) {
00604 if ( context == tb )
00605 cout << green << " Watching " <<coloroff;
00606 else
00607 cout << red << " In " << coloroff;
00608
00609 char state = getTaskStatusChar(taskcontext);
00610
00611 cout << "Task "<<green<< taskcontext->getName() <<coloroff<< "["<< state <<"]. (Status of last Command : ";
00612 if ( command == 0 )
00613 cout << "none";
00614 else if ( command->done() )
00615 cout <<green + "done";
00616 else if ( command->valid() )
00617 cout << blue+"busy";
00618 else if ( command->executed() )
00619 cout << red+"fail";
00620 else if ( command->accepted() )
00621 cout << blue+"queued";
00622 cout << coloroff << " )";
00623
00624
00625 cout << endl;
00626
00627
00628 for (PTrace::iterator it = ptraces.begin(); it != ptraces.end(); ++it) {
00629 TaskContext* progpeer = it->first.first;
00630 int line = progpeer->scripting()->getProgramLine(it->first.second);
00631 if ( line != it->second ) {
00632 it->second = line;
00633 printProgram( it->first.second, -1, progpeer );
00634 }
00635 }
00636
00637 for (PTrace::iterator it = straces.begin(); it != straces.end(); ++it) {
00638 TaskContext* progpeer = it->first.first;
00639 int line = progpeer->scripting()->getStateMachineLine(it->first.second);
00640 if ( line != it->second ) {
00641 it->second = line;
00642 printProgram( it->first.second, -1, progpeer );
00643 }
00644 }
00645 }
00646
00647 checkPorts();
00648
00649 ::signal( SIGINT, ctrl_c_catcher );
00650 #ifndef NO_GPL
00651 const char* const commandStr = rl_gets();
00652
00653 std::string command( commandStr ? commandStr : "quit" );
00654 #else
00655 std::string command;
00656 cout << prompt;
00657 getline(cin,command);
00658 if (!cin)
00659 command = "quit";
00660 #endif
00661 str_trim( command, ' ');
00662 ::signal( SIGINT, SIG_DFL );
00663 cout << coloroff;
00664 if ( command == "quit" ) {
00665
00666 cout << endl;
00667 return;
00668 } else if ( command == "help") {
00669 printHelp();
00670 } else if ( command == "#debug") {
00671 debug = !debug;
00672 } else if ( command.find("list ") == 0 || command == "list" ) {
00673 browserAction(command);
00674 } else if ( command.find("trace ") == 0 || command == "trace" ) {
00675 browserAction(command);
00676 } else if ( command.find("untrace ") == 0 || command == "untrace" ) {
00677 browserAction(command);
00678 } else if ( command.find("ls") == 0 ) {
00679 std::string::size_type pos = command.find("ls")+2;
00680 command = std::string(command, pos, command.length());
00681 printInfo( command );
00682 } else if ( command == "" ) {
00683 } else if ( command.find("cd ..") == 0 ) {
00684 this->switchBack( );
00685 } else if ( command.find("enter") == 0 ) {
00686 this->enterTask();
00687 } else if ( command.find("leave") == 0 ) {
00688 this->leaveTask();
00689 } else if ( command.find("cd ") == 0 ) {
00690 std::string::size_type pos = command.find("cd")+2;
00691 command = std::string(command, pos, command.length());
00692 this->switchTaskContext( command );
00693 } else if ( command.find(".") == 0 ) {
00694 command = std::string(command, 1, command.length());
00695 this->browserAction( command );
00696 } else if ( macrorecording) {
00697 macrotext += command +'\n';
00698 } else {
00699 try {
00700 this->evalCommand( command );
00701 } catch(...){
00702 cerr << "The command '"<<command<<"' caused an unknown exception and could not be completed."<<endl;
00703 }
00704
00705
00706 storedline = -1;
00707 }
00708 cout <<endl;
00709 }
00710 }
00711
00712 std::deque<TaskContext*> taskHistory;
00713 std::string TaskBrowser::prompt(" (type 'ls' for context info) :");
00714 std::string TaskBrowser::coloron("\e[m\e[1;31m");
00715 std::string TaskBrowser::underline("\e[4m");
00716 std::string TaskBrowser::coloroff("\e[m");
00717
00718 void TaskBrowser::enterTask()
00719 {
00720 if ( context == taskcontext ) {
00721 log(Info) <<"Already in Task "<< taskcontext->getName()<<endlog();
00722 return;
00723 }
00724 context = taskcontext;
00725 log(Info) <<"Entering Task "<< taskcontext->getName()<<endlog();
00726 }
00727
00728 void TaskBrowser::leaveTask()
00729 {
00730 if ( context == tb ) {
00731 log(Info) <<"Already watching Task "<< taskcontext->getName()<<endlog();
00732 return;
00733 }
00734 context = tb;
00735 log(Info) <<"Watching Task "<< taskcontext->getName()<<endlog();
00736 }
00737
00738 void TaskBrowser::recordMacro(std::string name)
00739 {
00740 if ( name.empty() ) {
00741 cerr << "Please specify a macro name." <<endl;
00742 return;
00743 } else {
00744 cout << "Recording macro "<< name <<endl;
00745 cout << "Use program scripting syntax (do, set,...) !" << endl <<endl;
00746 cout << "export function "<< name<<" {"<<endl;
00747 }
00748 macrorecording = true;
00749 macroname = name;
00750 }
00751
00752 void TaskBrowser::cancelMacro() {
00753 cout << "Canceling macro "<< macroname <<endl;
00754 macrorecording = false;
00755 }
00756
00757 void TaskBrowser::endMacro() {
00758 string fname = macroname + ".ops";
00759 macrorecording = false;
00760 cout << "}" <<endl;
00761 cout << "Saving file "<< fname <<endl;
00762 ofstream macrofile( fname.c_str() );
00763 macrofile << "/* TaskBrowser macro '"<<macroname<<"' */" <<endl<<endl;
00764 macrofile << "export function "<<macroname<<" {"<<endl;
00765 macrofile << macrotext.c_str();
00766 macrofile << "}"<<endl;
00767
00768 cout << "Loading file "<< fname <<endl;
00769 ProgramLoader loader;
00770 if ( loader.loadProgram( fname, context ) ) {
00771 cout << "Done."<<endl;
00772 } else
00773 cout << "Failed."<<endl;
00774 }
00775
00776 void TaskBrowser::switchBack()
00777 {
00778 if ( taskHistory.size() == 0)
00779 return;
00780 if ( !taskcontext->engine()->commands()->isProcessed( lastc ) ) {
00781 Logger::log()<<Logger::Warning
00782 << "Previous command was not yet processed by previous Processor." <<Logger::nl
00783 << " Can not track command status across tasks."<< endlog();
00784
00785 command = 0;
00786 } else {
00787 delete command;
00788 command = 0;
00789 }
00790
00791 this->switchTaskContext( taskHistory.front(), false );
00792 lastc = 0;
00793 taskHistory.pop_front();
00794 }
00795
00796 void TaskBrowser::checkPorts()
00797 {
00798
00799
00800 DataFlowInterface::Ports ports;
00801 ports = this->ports()->getPorts();
00802 for( DataFlowInterface::Ports::iterator i=ports.begin(); i != ports.end(); ++i) {
00803
00804 PortInterface* p = *i;
00805 PortInterface* tcp = taskcontext->ports()->getPort( p->getName() );
00806 if ( p->ready() == false || tcp == 0 || tcp->ready() == false) {
00807 this->ports()->removePort( p->getName() );
00808 delete p;
00809 }
00810 }
00811 }
00812
00813 void TaskBrowser::setColorTheme(ColorTheme t)
00814 {
00815
00816 const char* dbg = "\033[01;";
00817 const char* wbg = "\033[02;";
00818
00819 const char* r = "31m";
00820 const char* g = "32m";
00821 const char* b = "34m";
00822 const char* con = "31m";
00823 const char* coff = "\e[m";
00824 const char* und = "\e[4m";
00825
00826 switch (t)
00827 {
00828 case nocolors:
00829 green.clear();
00830 red.clear();
00831 blue.clear();
00832 coloron.clear();
00833 coloroff.clear();
00834 underline.clear();
00835 return;
00836 break;
00837 case darkbg:
00838 green = dbg;
00839 red = dbg;
00840 blue = dbg;
00841 coloron = dbg;
00842 break;
00843 case whitebg:
00844 green = wbg;
00845 red = wbg;
00846 blue = wbg;
00847 coloron = wbg;
00848 break;
00849 }
00850 green += g;
00851 red += r;
00852 blue += b;
00853 coloron += con;
00854 coloroff = coff;
00855 underline = und;
00856 }
00857
00858 void TaskBrowser::switchTaskContext(std::string& c) {
00859
00860 peer = taskcontext;
00861 if ( this->findPeer( c + "." ) == 0 ) {
00862 cerr << "No such peer: "<< c <<nl;
00863 return;
00864 }
00865
00866 if ( peer == taskcontext ) {
00867 cerr << "Already in "<< c <<nl;
00868 return;
00869 }
00870
00871 if ( peer == tb ) {
00872 cerr << "Can not switch to TaskBrowser." <<nl;
00873 return;
00874 }
00875
00876
00877 this->switchTaskContext( peer );
00878 }
00879
00880 void TaskBrowser::switchTaskContext(TaskContext* tc, bool store) {
00881
00882 if (taskHistory.size() == 20 )
00883 taskHistory.pop_back();
00884 if ( taskcontext && store)
00885 taskHistory.push_front( taskcontext );
00886
00887
00888
00889 if ( taskcontext && !taskcontext->engine()->commands()->isProcessed( lastc ) ) {
00890 Logger::log()<<Logger::Warning
00891 << "Previous command was not yet processed by previous Processor." <<Logger::nl
00892 << " Can not track command status across tasks."<< endlog();
00893
00894 command = 0;
00895 } else {
00896 delete command;
00897 command = 0;
00898 }
00899
00900
00901 this->disconnect();
00902
00903
00904 DataFlowInterface::Ports ports = this->ports()->getPorts();
00905 for( DataFlowInterface::Ports::iterator i=ports.begin(); i != ports.end(); ++i) {
00906 this->ports()->removePort( (*i)->getName() );
00907 delete *i;
00908 }
00909
00910
00911 if ( context == taskcontext )
00912 context = tc;
00913 taskcontext = tc;
00914 lastc = 0;
00915
00916
00917 this->addPeer( taskcontext );
00918
00919 cerr << " Switched to : " << taskcontext->getName() <<endl;
00920
00921 }
00922
00923 TaskContext* TaskBrowser::findPeer(std::string c) {
00924
00925 std::string s( c );
00926
00927 our_pos_iter_t parsebegin( s.begin(), s.end(), "teststring" );
00928 our_pos_iter_t parseend;
00929
00930 PeerParser pp( peer, true );
00931 try {
00932 parse( parsebegin, parseend, pp.parser(), SKIP_PARSER );
00933 }
00934 catch( ... )
00935 {
00936 log(Debug) <<"No such peer : "<< c <<endlog();
00937 return 0;
00938 }
00939 taskobject = pp.taskObject();
00940 assert(taskobject);
00941 peer = pp.peer();
00942 return pp.peer();
00943 }
00944
00945 void TaskBrowser::browserAction(std::string& act)
00946 {
00947 std::stringstream ss(act);
00948 std::string instr;
00949 ss >> instr;
00950
00951 if ( instr == "list" ) {
00952 int line;
00953 ss >> line;
00954 if (ss) {
00955 this->printProgram(line);
00956 return;
00957 }
00958 ss.clear();
00959 string arg;
00960 ss >> arg;
00961 if (ss) {
00962 ss.clear();
00963 ss >> line;
00964 if (ss) {
00965
00966 this->printProgram(arg, line);
00967 return;
00968 }
00969
00970 this->printProgram( arg );
00971 return;
00972 }
00973
00974 this->printProgram();
00975 return;
00976 }
00977
00978
00979
00980
00981 if ( instr == "trace") {
00982 string arg;
00983 ss >> arg;
00984 if (ss) {
00985 bool pi = context->scripting()->hasProgram(arg);
00986 if (pi) {
00987 ptraces[make_pair(context, arg)] = context->scripting()->getProgramLine(arg);
00988 this->printProgram( arg );
00989 return;
00990 }
00991 pi = context->scripting()->hasStateMachine(arg);
00992 if (pi) {
00993 straces[make_pair(context, arg)] = context->scripting()->getStateMachineLine(arg);
00994 this->printProgram( arg );
00995 return;
00996 }
00997 cerr <<"No such program or state machine: "<< arg <<endl;
00998 return;
00999 }
01000
01001
01002 std::vector<std::string> names;
01003 names = context->scripting()->getPrograms();
01004 for (std::vector<std::string>::iterator it = names.begin(); it != names.end(); ++it) {
01005 bool pi = context->scripting()->hasProgram(arg);
01006 if (pi)
01007 ptraces[make_pair(context, arg)] = context->scripting()->getProgramLine(arg);
01008 }
01009
01010 names = context->scripting()->getStateMachines();
01011 for (std::vector<std::string>::iterator it = names.begin(); it != names.end(); ++it) {
01012 bool pi = context->scripting()->hasStateMachine(arg);
01013 if (pi)
01014 straces[make_pair(context, arg)] = context->scripting()->getStateMachineLine(arg);
01015 }
01016
01017 cerr << "Tracing all programs and state machines in "<< context->getName() << endl;
01018 return;
01019 }
01020
01021 if ( instr == "untrace") {
01022 string arg;
01023 ss >> arg;
01024 if (ss) {
01025 ptraces.erase( make_pair(context, arg) );
01026 straces.erase( make_pair(context, arg) );
01027 cerr <<"Untracing "<< arg <<" of "<< context->getName()<<endl;
01028 return;
01029 }
01030
01031 std::vector<std::string> names;
01032 names = context->scripting()->getPrograms();
01033 for (std::vector<std::string>::iterator it = names.begin(); it != names.end(); ++it) {
01034 bool pi = context->scripting()->hasProgram(arg);
01035 if (pi)
01036 ptraces.erase(make_pair(context, arg));
01037 }
01038
01039 names = context->scripting()->getStateMachines();
01040 for (std::vector<std::string>::iterator it = names.begin(); it != names.end(); ++it) {
01041 bool pi = context->scripting()->hasStateMachine(arg);
01042 if (pi)
01043 straces.erase(make_pair(context, arg));
01044 }
01045
01046 cerr << "Untracing all programs and state machines of "<< context->getName() << endl;
01047 return;
01048 }
01049
01050 std::string arg;
01051 ss >> arg;
01052 ProgramLoader loader;
01053 if ( instr == "loadProgram") {
01054 if ( loader.loadProgram( arg, context ) )
01055 cout << "Done."<<endl;
01056 else
01057 cout << "Failed."<<endl;
01058 return;
01059 }
01060 if ( instr == "unloadProgram") {
01061 if ( loader.unloadProgram( arg, context ) )
01062 cout << "Done."<<endl;
01063 else
01064 cout << "Failed."<<endl;
01065 return;
01066 }
01067
01068 if ( instr == "loadStateMachine") {
01069 if ( loader.loadStateMachine( arg, context ) )
01070 cout << "Done."<<endl;
01071 else
01072 cout << "Failed."<<endl;
01073 return;
01074 }
01075 if ( instr == "unloadStateMachine") {
01076 if ( loader.unloadStateMachine( arg, context ) )
01077 cout << "Done."<<endl;
01078 else
01079 cout << "Failed."<<endl;
01080 return;
01081 }
01082 if ( instr == "dark") {
01083 this->setColorTheme(darkbg);
01084 cout << nl << "Setting Color Theme for "+green+"dark"+coloroff+" backgrounds."<<endl;
01085 return;
01086 }
01087 if ( instr == "light") {
01088 this->setColorTheme(whitebg);
01089 cout << nl << "Setting Color Theme for "+green+"light"+coloroff+" backgrounds."<<endl;
01090 return;
01091 }
01092 if ( instr == "nocolors") {
01093 this->setColorTheme(nocolors);
01094 cout <<nl << "Disabling all colors"<<endl;
01095 return;
01096 }
01097 if ( instr == "connect") {
01098 if (arg.empty() ) {
01099 cout <<nl << "TaskBrowser connects to all ports of "<<taskcontext->getName()<<endl;
01100
01101 DataFlowInterface::Ports ports = taskcontext->ports()->getPorts();
01102 for( DataFlowInterface::Ports::iterator i=ports.begin(); i != ports.end(); ++i) {
01103 if (this->ports()->getPort( (*i)->getName() ) == 0 )
01104 this->ports()->addPort( (*i)->antiClone() );
01105 }
01106 RTT::connectPorts(this,taskcontext);
01107 }
01108 else {
01109 cout <<nl << "TaskBrowser connects to port '"<<arg <<"' of "<<taskcontext->getName()<<endl;
01110
01111 DataFlowInterface::Ports ports = taskcontext->ports()->getPorts();
01112 for( DataFlowInterface::Ports::iterator i=ports.begin(); i != ports.end(); ++i) {
01113 if ( (*i)->getName() == arg && this->ports()->getPort( (*i)->getName() ) == 0 ) {
01114 this->ports()->addPort( (*i)->antiClone() );
01115 this->ports()->getPort( arg )->connectTo( *i );
01116 assert( this->ports()->getPort( arg )->connected() );
01117 return;
01118 }
01119 }
01120 }
01121 return;
01122 }
01123 if ( instr == "record") {
01124 recordMacro( arg );
01125 return;
01126 }
01127 if ( instr == "cancel") {
01128 cancelMacro();
01129 return;
01130 }
01131 if ( instr == "end") {
01132 endMacro();
01133 return;
01134 }
01135 cerr << "Unknown Browser Action : "<< act <<endl;
01136 cerr << "See 'help' for valid syntax."<<endl;
01137 }
01138
01139 void TaskBrowser::evaluate(std::string& comm) {
01140 this->evalCommand(comm);
01141 }
01142
01143 void TaskBrowser::evalCommand(std::string& comm )
01144 {
01145 cout << " Got :"<< comm <<nl;
01146
01147 OperationInterface* ops = context->getObject( comm );
01148 if ( ops )
01149 {
01150 sresult << nl << "Printing Interface of '"<< coloron << ops->getName() <<coloroff <<"' :"<<nl<<nl;
01151 std::vector<std::string> methods = ops->commands()->getNames();
01152 std::for_each( methods.begin(), methods.end(), boost::bind(&TaskBrowser::printCommand, this, _1, ops) );
01153 methods = ops->methods()->getNames();
01154 std::for_each( methods.begin(), methods.end(), boost::bind(&TaskBrowser::printMethod, this, _1, ops) );
01155 if (comm == "this") {
01156 methods = taskcontext->events()->getNames();
01157 std::for_each( methods.begin(), methods.end(), boost::bind(&TaskBrowser::printEvent, this, _1, taskcontext->events()) );
01158 }
01159 cout << sresult.str();
01160 sresult.str("");
01161
01162 }
01163
01164
01165
01166
01167 if ( context->attributes()->getValue( comm ) ) {
01168 this->printResult( context->attributes()->getValue( comm )->getDataSource().get(), true );
01169 cout << sresult.str();
01170 sresult.str("");
01171 return;
01172 }
01173
01174 if ( ops ) {
01175 return;
01176 }
01177
01178 Parser _parser;
01179
01180 if (debug)
01181 cerr << "Trying ValueChange..."<<nl;
01182 try {
01183
01184 DataSourceBase::shared_ptr ds = _parser.parseValueChange( comm, context );
01185
01186 if ( ds.get() != 0 ) {
01187 this->printResult( ds.get(), false );
01188 cout << sresult.str() << nl;
01189 sresult.str("");
01190 return;
01191 } else if (debug)
01192 cerr << "returned zero !"<<nl;
01193 } catch ( fatal_semantic_parse_exception& pe ) {
01194
01195 if (debug)
01196 cerr << "fatal_semantic_parse_exception: ";
01197 cerr << pe.what() <<nl;
01198 return;
01199 } catch ( syntactic_parse_exception& pe ) {
01200
01201 if (debug)
01202 cerr << "syntactic_parse_exception: ";
01203 cerr << pe.what() <<nl;
01204 return;
01205 } catch ( parse_exception_parser_fail &pe )
01206 {
01207
01208 if (debug) {
01209 cerr << "Ignoring ValueChange exception :"<<nl;
01210 cerr << pe.what() <<nl;
01211 }
01212 } catch ( parse_exception& pe ) {
01213
01214 if (debug)
01215 cerr << "parse_exception :";
01216 cerr << pe.what() <<nl;
01217 return;
01218 }
01219 if (debug)
01220 cerr << "Trying Expression..."<<nl;
01221 try {
01222
01223 DataSourceBase::shared_ptr ds = _parser.parseExpression( comm, context );
01224
01225 if ( ds.get() != 0 ) {
01226 this->printResult( ds.get(), true );
01227 cout << sresult.str() << nl;
01228 sresult.str("");
01229 return;
01230 } else if (debug)
01231 cerr << "returned zero !"<<nl;
01232 } catch ( syntactic_parse_exception& pe ) {
01233
01234 if (debug)
01235 cerr << "syntactic_parse_exception :";
01236 cerr << pe.what() <<nl;
01237 return;
01238 } catch ( fatal_semantic_parse_exception& pe ) {
01239
01240 if (debug)
01241 cerr << "fatal_semantic_parse_exception :";
01242 cerr << pe.what() <<nl;
01243 return;
01244 } catch ( parse_exception_parser_fail &pe )
01245 {
01246
01247 if (debug) {
01248 cerr << "Ignoring Expression exception :"<<nl;
01249 cerr << pe.what() <<nl;
01250 }
01251 } catch ( parse_exception& pe ) {
01252
01253 if (debug) {
01254 cerr << "Ignoring Expression parse_exception :"<<nl;
01255 cerr << pe.what() <<nl;
01256 }
01257 }
01258 if (debug)
01259 cerr << "Trying Command..."<<nl;
01260 try {
01261 CommandInterface* com = _parser.parseCommand( comm, context, true ).first;
01262
01263 if ( com && dynamic_cast<DispatchInterface*>(com) == 0 ) {
01264 string prompt =" = ";
01265 sresult <<prompt<< setw(20)<<left;
01266 sresult << com->execute() << right;
01267 cout << sresult.str();
01268 sresult.str("");
01269 delete com;
01270 return;
01271 }
01272 if ( command && !command->executed() ) {
01273 cerr << "Warning : previous command is not yet processed by Processor." <<nl;
01274 } else {
01275 delete command;
01276 }
01277 command = dynamic_cast<DispatchInterface*>(com);
01278 } catch ( parse_exception& pe ) {
01279 if (debug)
01280 cerr << "CommandParser parse_exception :"<<nl;
01281 cerr << pe.what() <<nl;
01282 return;
01283 } catch (...) {
01284 cerr << "Illegal Input."<<nl;
01285 return;
01286 }
01287
01288 if ( command == 0 ) {
01289 cerr << "Uncaught : Illegal command."<<nl;
01290 return;
01291 }
01292
01293 command->readArguments();
01294 if ( command->dispatch() == false ) {
01295 cerr << "Command not accepted by "<<context->getName()<<"'s Processor !" << nl;
01296 delete command;
01297 command = 0;
01298 accepted = 0;
01299 }
01300 }
01301
01302 void TaskBrowser::printResult( DataSourceBase* ds, bool recurse) {
01303 std::string prompt(" = ");
01304
01305 sresult <<prompt<< setw(20)<<left;
01306 if ( ds )
01307 doPrint( ds, recurse );
01308 else
01309 sresult << "(null)";
01310 sresult << right;
01311 }
01312
01313 void TaskBrowser::doPrint( DataSourceBase* ds, bool recurse) {
01314
01315
01316
01317 ds->reset();
01318
01319 DataSource<PropertyBag>* dspbag = DataSource<PropertyBag>::narrow(ds);
01320 if (dspbag) {
01321 PropertyBag bag( dspbag->get() );
01322 if (!recurse) {
01323 int siz = bag.getProperties().size();
01324 int wdth = siz ? (20 - (siz / 10 + 1)) : 20;
01325 sresult <<setw(0)<< siz <<setw( wdth )<< " Properties";
01326 } else {
01327 if ( ! bag.empty() ) {
01328 sresult <<setw(0)<<nl;
01329 for( PropertyBag::iterator it= bag.getProperties().begin(); it!=bag.getProperties().end(); ++it) {
01330 sresult <<setw(14)<<right<<(*it)->getType()<<" "<<coloron<<setw(14)<< (*it)->getName()<<coloroff;
01331 DataSourceBase::shared_ptr propds = (*it)->getDataSource();
01332 this->printResult( propds.get(), false );
01333 sresult <<" ("<<(*it)->getDescription()<<')' << nl;
01334 }
01335 } else {
01336 sresult <<prompt<<"(empty PropertyBag)";
01337 }
01338 }
01339 return;
01340 }
01341
01342 DataSourceBase::shared_ptr dsb(ds);
01343 dsb->evaluate();
01344 sresult << dsb;
01345 }
01346
01347 struct comcol
01348 {
01349 const char* command;
01350 comcol(const char* c) :command(c) {}
01351 std::ostream& operator()( std::ostream& os ) const {
01352 os<<"'"<< TaskBrowser::coloron<< TaskBrowser::underline << command << TaskBrowser::coloroff<<"'";
01353 return os;
01354 }
01355 };
01356
01357 struct keycol
01358 {
01359 const char* command;
01360 keycol(const char* c) :command(c) {}
01361 std::ostream& operator()( std::ostream& os )const {
01362 os<<"<"<< TaskBrowser::coloron<< TaskBrowser::underline << command << TaskBrowser::coloroff<<">";
01363 return os;
01364 }
01365 };
01366
01367 struct titlecol
01368 {
01369 const char* command;
01370 titlecol(const char* c) :command(c) {}
01371 std::ostream& operator()( std::ostream& os ) const {
01372 os<<endl<<"["<< TaskBrowser::coloron<< TaskBrowser::underline << command << TaskBrowser::coloroff<<"]";
01373 return os;
01374 }
01375 };
01376
01377 std::ostream& operator<<(std::ostream& os, comcol f ){
01378 return f(os);
01379 }
01380
01381 std::ostream& operator<<(std::ostream& os, keycol f ){
01382 return f(os);
01383 }
01384
01385 std::ostream& operator<<(std::ostream& os, titlecol f ){
01386 return f(os);
01387 }
01388
01389 void TaskBrowser::printHelp()
01390 {
01391 cout << coloroff;
01392 cout <<titlecol("Task Browsing")<<nl;
01393 cout << " To switch to another task, type "<<comcol("cd <path-to-taskname>")<<nl;
01394 cout << " and type "<<comcol("cd ..")<<" to go back to the previous task (History size is 20)."<<nl;
01395 cout << " Pressing "<<keycol("tab")<<" multiple times helps you to complete your command."<<nl;
01396 cout << " It is not mandatory to switch to a task to interact with it, you can type the"<<nl;
01397 cout << " peer-path to the task (dot-separated) and then type command or expression :"<<nl;
01398 cout << " PeerTask.OtherTask.FinalTask.countTo(3) [enter] "<<nl;
01399 cout << " Where 'countTo' is a method of 'FinalTask'."<<nl;
01400 cout << " The TaskBrowser starts by default 'In' the current component. In order to watch"<<nl;
01401 cout << " the TaskBrowser itself, type "<<comcol("leave")<<" You will notice that it"<<nl;
01402 cout << " has connected to the data ports of the visited component. Use "<<comcol("enter")<<" to enter"<<nl;
01403 cout << " the visited component again. The "<<comcol("cd")<<" command works transparantly in both"<<nl;
01404 cout << " modi."<<nl;
01405
01406 cout << " "<<titlecol("Task Context Info")<<nl;
01407 cout << " To see the contents of a task, type "<<comcol("ls")<<nl;
01408 cout << " For a detailed argument list (and helpful info) of the object's methods, "<<nl;
01409 cout <<" type the name of one of the listed task objects : " <<nl;
01410 cout <<" this [enter]" <<nl<<nl;
01411 cout <<" Command : bool factor( int number )" <<nl;
01412 cout <<" Factor a value into its primes." <<nl;
01413 cout <<" number : The number to factor in primes." <<nl;
01414 cout <<" Method : bool isRunning( )" <<nl;
01415 cout <<" Is this TaskContext started ?" <<nl;
01416 cout <<" Method : bool loadProgram( const& std::string Filename )" <<nl;
01417 cout <<" Load an Orocos Program Script from a file." <<nl;
01418 cout <<" Filename : An ops file." <<nl;
01419 cout <<" ..."<<nl;
01420
01421 cout <<titlecol("Expressions")<<nl;
01422 cout << " You can evaluate any script expression by merely typing it :"<<nl;
01423 cout << " 1+1 [enter]" <<nl;
01424 cout << " = 2" <<nl;
01425 cout << " or inspect the status of a program :"<<nl;
01426 cout << " programs.myProgram.isRunning [enter]" <<nl;
01427 cout << " = false" <<nl;
01428 cout << " and display the contents of complex data types (vector, array,...) :"<<nl;
01429 cout << " array(6)" <<nl;
01430 cout << " = {0, 0, 0, 0, 0, 0}" <<nl;
01431
01432 cout <<titlecol("Changing Attributes and Properties")<<nl;
01433 cout << " To change the value of a Task's attribute, type "<<comcol("varname = <newvalue>")<<nl;
01434 cout << " If you provided a correct assignment, the browser will inform you of the success"<<nl;
01435 cout <<" with '= true'." <<nl;
01436
01437 cout <<titlecol("Commands")<<nl;
01438 cout << " A Command is 'sent' to a task, which will process it in its own context (thread)."<<nl;
01439 cout << " A command consists of an object, followed by a dot ('.'), the command "<<nl;
01440 cout << " name, followed by the parameters. An example could be :"<<nl;
01441 cout << " otherTask.bar.orderBeers(\"Palm\", 5) [enter] "<<nl;
01442 cout << " The prompt will inform you about the status of the last command you entered. "<<nl;
01443 cout << " It is allowed to enter a new command while the previous is still busy. "<<nl;
01444
01445 cout <<titlecol("Methods")<<nl;
01446 cout << " Methods 'look' the same as commands, but they are evaluated"<<nl;
01447 cout << " immediately and print the result. An example could be :"<<nl;
01448 cout << " someTask.bar.getNumberOfBeers(\"Palm\") [enter] "<<nl;
01449 cout << " = 99" <<nl;
01450
01451 cout <<titlecol("Events")<<nl;
01452 cout << " Events behave as methods, they are emitted immediately."<<nl;
01453 cout << " An example emitting an event :"<<nl;
01454 cout << " someTask.notifyUserState(\"Drunk\") [enter] "<<nl;
01455 cout << " = (void)" <<nl;
01456
01457 cout <<titlecol("Program and StateMachine Scripts")<<nl;
01458 cout << " To load a program script from local disc, type "<<comcol(".loadProgram <filename>")<<nl;
01459 cout << " To load a state machine script from local disc, type "<<comcol(".loadStateMachine <filename>")<<nl;
01460 cout << " ( notice the starting dot '.' )"<<nl;
01461 cout << " Likewise, "<<comcol(".loadProgram <ProgramName>")<<" and "<<comcol(".unloadStateMachine <StateMachineName>")<<nl;
01462 cout << " are available (notice it is the program's name, not the filename)."<<nl;
01463 cout << " You can use "<<comcol("ls progname")<<nl;
01464 cout << " to see the programs commands, methods and variables. You can manipulate each one of these,."<<nl;
01465 cout << " as if the program is a Task itself (see all items above)."<<nl;
01466
01467 cout << " To print a program or state machine listing, use "<<comcol("list progname [linenumber]")<<nl;
01468 cout << " to list the contents of the current program lines being executed,"<<nl;
01469 cout << " or 10 lines before or after <linenumber>. When only "<<comcol("list [n]")<<nl;
01470 cout << " is typed, 20 lines of the last listed program are printed from line <n> on "<<nl;
01471 cout << " ( default : list next 20 lines after previous list )."<<nl;
01472
01473 cout << " To trace a program or state machine listing, use "<<comcol("trace [progname]")<<" this will"<<nl;
01474 cout << " cause the TaskBrowser to list the contents of a traced program,"<<nl;
01475 cout << " each time the line number of the traced program changes."<<nl;
01476 cout << " Disable tracing with "<<comcol("untrace [progname]")<<""<<nl;
01477 cout << " If no arguments are given to "<<comcol("trace")<<" and "<<comcol("untrace")<<", it applies to all programs."<<nl;
01478
01479 cout << " A status character shows which line is being executed."<<nl;
01480 cout << " For programs : 'E':Error, 'S':Stopped, 'R':Running, 'P':Paused"<<nl;
01481 cout << " For state machines : <the same as programs> + 'A':Active, 'I':Inactive"<<nl;
01482
01483 cout <<titlecol("Changing Colors")<<nl;
01484 cout << " You can inform the TaskBrowser of your background color by typing "<<comcol(".dark")<<nl;
01485 cout << " "<<comcol(".light")<<", or "<<comcol(".nocolors")<<" to increase readability."<<nl;
01486
01487 cout <<titlecol("Macro Recording / Command line history")<<nl;
01488 cout << " You can browse the commandline history by using the up-arrow key or press "<<comcol("Ctrl r")<<nl;
01489 cout << " and a search term. Hit enter to execute the current searched command."<<nl;
01490 cout << " Macros can be recorded using the "<<comcol(".record 'macro-name'")<<" command."<<nl;
01491 cout << " You can cancel the recording by typing "<<comcol(".cancel")<<" ."<<nl;
01492 cout << " You can save and load the macro by typing "<<comcol(".end")<<" . The macro becomes"<<nl;
01493 cout << " available as a command with name 'macro-name' in the current TaskContext." << nl;
01494 cout << " While you enter the macro, it is not executed, as you must use scripting syntax which"<<nl;
01495 cout << " may use loop or conditional statements, variables etc."<<nl;
01496
01497 cout <<titlecol("Connecting Ports")<<nl;
01498 cout << " You can instruct the TaskBrowser to connect to the ports of the current Peer by"<<nl;
01499 cout << " typing "<<comcol(".connect [port-name]")<<", which will temporarily create connections"<<nl;
01500 cout << " to all ports if [port-name] is omitted or to the specified port otherwise."<<nl;
01501 cout << " The TaskBrowser disconnects these ports when it visits another component, but the"<<nl;
01502 cout << " created connection objects remain in place (this is more or less a bug)!"<<nl;
01503 }
01504
01505 void TaskBrowser::printProgram(const std::string& progname, int cl , TaskContext* progpeer ) {
01506 string ps;
01507 char s;
01508 stringstream txtss;
01509 int ln;
01510 int start;
01511 int end;
01512 bool found(false);
01513
01514 if (progpeer == 0 )
01515 progpeer = context;
01516
01517
01518 if ( progpeer->scripting()->hasProgram( progname ) ) {
01519 s = getProgramStatusChar(progpeer, progname);
01520 txtss.str( progpeer->scripting()->getProgramText(progname) );
01521 ln = progpeer->scripting()->getProgramLine(progname);
01522 if ( cl < 0 ) cl = ln;
01523 start = cl < 10 ? 1 : cl - 10;
01524 end = cl + 10;
01525 this->listText( txtss, start, end, ln, s);
01526 found = true;
01527 }
01528
01529
01530 if ( progpeer->scripting()->hasStateMachine( progname ) ) {
01531 s = getStateMachineStatusChar(progpeer, progname);
01532 txtss.str( progpeer->scripting()->getStateMachineText(progname) );
01533 ln = progpeer->scripting()->getStateMachineLine(progname);
01534 if ( cl < 0 ) cl = ln;
01535 start = cl <= 10 ? 1 : cl - 10;
01536 end = cl + 10;
01537 this->listText( txtss, start, end, ln, s);
01538 found = true;
01539 }
01540 if ( !found ) {
01541 cerr << "Error : No such program or state machine found : "<<progname;
01542 cerr << " in "<< progpeer->getName() <<"."<<endl;
01543 return;
01544 }
01545 storedname = progname;
01546 }
01547
01548 void TaskBrowser::printProgram(int cl ) {
01549 string ps;
01550 char s;
01551 stringstream txtss;
01552 int ln;
01553 int start;
01554 int end;
01555 bool found(false);
01556 if ( context->scripting()->hasProgram( storedname ) ) {
01557 s = getProgramStatusChar(context, storedname);
01558 txtss.str( context->scripting()->getProgramText(storedname) );
01559 ln = context->scripting()->getProgramLine(storedname);
01560 if ( cl < 0 ) cl = storedline;
01561 if (storedline < 0 ) cl = ln -10;
01562 start = cl;
01563 end = cl + 20;
01564 this->listText( txtss, start, end, ln, s);
01565 found = true;
01566 }
01567 if ( context->scripting()->hasStateMachine(storedname) ) {
01568 s = getStateMachineStatusChar(context, storedname);
01569 txtss.str( context->scripting()->getStateMachineText(storedname) );
01570 ln = context->scripting()->getStateMachineLine(storedname);
01571 if ( cl < 0 ) cl = storedline;
01572 if (storedline < 0 ) cl = ln -10;
01573 start = cl;
01574 end = cl+20;
01575 this->listText( txtss, start, end, ln, s);
01576 found = true;
01577 }
01578 if ( !found )
01579 cerr << "Error : No such program or state machine found : "<<storedname<<endl;
01580 }
01581
01582 void TaskBrowser::listText(stringstream& txtss,int start, int end, int ln, char s) {
01583 int curln = 1;
01584 string line;
01585 while ( start > 1 && curln != start ) {
01586 getline( txtss, line, '\n' );
01587 if ( ! txtss )
01588 break;
01589 ++curln;
01590 }
01591 while ( end > start && curln != end ) {
01592 getline( txtss, line, '\n' );
01593 if ( ! txtss )
01594 break;
01595 if ( curln == ln ) {
01596 cout << s<<'>';
01597 }
01598 else
01599 cout << " ";
01600 cout<< setw(int(log(double(end)))) <<right << curln<< left;
01601 cout << ' ' << line <<endl;
01602 ++curln;
01603 }
01604 storedline = curln;
01605 // done !
01606 }
01607
01608 void TaskBrowser::printInfo(const std::string& peerp)
01609 {
01610 // this sets this->peer to the peer given
01611 peer = context;
01612 if ( this->findPeer( peerp+"." ) == 0 ) {
01613 cerr << "No such peer or object: " << peerp << endl;
01614 return;
01615 }
01616
01617 if ( !peer || !peer->ready()) {
01618 cout << nl << " Connection to peer "+peerp+" lost (peer->ready() == false)." <<endlog();
01619 return;
01620 }
01621
01622 if ( peer == taskobject )
01623 sresult <<nl<<" Listing TaskContext "<< green << peer->getName()<<coloroff<< " :"<<nl;
01624 else
01625 sresult <<nl<<" Listing TaskObject "<< green << taskobject->getName()<<coloroff<< " :"<<nl;
01626
01627 // Only print Properties for TaskContexts
01628 if ( peer == taskobject ) {
01629 sresult <<nl<<" Configuration Properties: ";
01630 PropertyBag* bag = peer->properties();
01631 if ( bag && bag->size() != 0 ) {
01632 // Print Properties:
01633 for( PropertyBag::iterator it = bag->begin(); it != bag->end(); ++it) {
01634 DataSourceBase::shared_ptr pds = (*it)->getDataSource();
01635 sresult << nl << setw(11)<< right << (*it)->getType()<< " "
01636 << coloron <<setw(14)<<left<< (*it)->getName() << coloroff;
01637 this->printResult( pds.get(), false ); // do not recurse
01638 sresult<<" ("<< (*it)->getDescription() <<')';
01639 }
01640 } else {
01641 sresult << "(none)";
01642 }
01643 sresult <<nl;
01644 }
01645
01646 // Print "this" interface (without detail) and then list objects...
01647 sresult <<nl<< " Execution Interface:";
01648
01649 sresult <<nl<< " Attributes : ";
01650 std::vector<std::string> objlist = taskobject->attributes()->names();
01651 if ( !objlist.empty() ) {
01652 sresult << nl;
01653 // Print Attributes:
01654 for( std::vector<std::string>::iterator it = objlist.begin(); it != objlist.end(); ++it) {
01655 DataSourceBase::shared_ptr pds = taskobject->attributes()->getValue(*it)->getDataSource();
01656 sresult << setw(11)<< right << pds->getType()<< " "
01657 << coloron <<setw( 14 )<<left<< *it << coloroff;
01658 this->printResult( pds.get(), false ); // do not recurse
01659 sresult <<nl;
01660 }
01661 } else {
01662 sresult << coloron << "(none)";
01663 }
01664
01665 sresult <<coloroff<<nl<< " Methods : "<<coloron;
01666 objlist = taskobject->methods()->getNames();
01667 if ( !objlist.empty() ) {
01668 copy(objlist.begin(), objlist.end(), std::ostream_iterator<std::string>(sresult, " "));
01669 } else {
01670 sresult << "(none)";
01671 }
01672 sresult <<coloroff<<nl<< " Commands : "<<coloron;
01673 objlist = taskobject->commands()->getNames();
01674 if ( !objlist.empty() ) {
01675 copy(objlist.begin(), objlist.end(), std::ostream_iterator<std::string>(sresult, " "));
01676 } else {
01677 sresult << "(none)";
01678 }
01679 sresult <<coloroff<<nl<< " Events : "<<coloron;
01680 objlist = taskobject->events()->getEvents();
01681 if ( !objlist.empty() ) {
01682 copy(objlist.begin(), objlist.end(), std::ostream_iterator<std::string>(sresult, " "));
01683 } else {
01684 sresult << "(none)";
01685 }
01686 sresult << coloroff << nl;
01687
01688 if ( peer == taskobject ) {
01689 sresult <<nl<< " Data Flow Ports: ";
01690 objlist = peer->ports()->getPortNames();
01691 if ( !objlist.empty() ) {
01692 for(vector<string>::iterator it = objlist.begin(); it != objlist.end(); ++it) {
01693 PortInterface* port = peer->ports()->getPort(*it);
01694 PortInterface::PortType pt = port->getPortType();
01695 // Port type R/W
01696 sresult << nl << " " << (pt == PortInterface::ReadPort ?
01697 " R" : pt == PortInterface::WritePort ? " W" : "RW");
01698 // Port data type + name
01699 if ( !port->ready() || !port->connection() )
01700 sresult << "(U) " << setw(11)<<right<< port->getTypeInfo()->getTypeName();
01701 else
01702 sresult << "(C) " << setw(11)<<right<< port->getTypeInfo()->getTypeName();
01703 sresult << " "
01704 << coloron <<setw( 14 )<<left<< *it << coloroff;
01705 if ( port->ready() )
01706 sresult << " = " <<port->connection()->getDataSource();
01707 else {
01708 ConnectionInterface::shared_ptr c = port->createConnection();
01709 if ( c )
01710 sresult << " = " << c->getDataSource();
01711 }
01712 // Port description
01713 // if ( peer->getObject(*it) )
01714 // sresult << " ( "<< taskobject->getObject(*it)->getDescription() << " ) ";
01715 }
01716 } else {
01717 sresult << "(none)";
01718 }
01719 sresult << coloroff << nl;
01720 }
01721
01722 objlist = taskobject->getObjectList();
01723 sresult <<nl<< " Task Objects: "<<nl;
01724 if ( !objlist.empty() ) {
01725 for(vector<string>::iterator it = objlist.begin(); it != objlist.end(); ++it)
01726 sresult <<coloron<< " " << setw(14) << *it <<coloroff<< " ( "<< taskobject->getObject(*it)->getDescription() << " ) "<<nl;
01727 } else {
01728 sresult <<coloron<< "(none)" <<coloroff <<nl;
01729 }
01730
01731 // TaskContext specific:
01732 if ( peer == taskobject ) {
01733
01734 objlist = peer->scripting()->getPrograms();
01735 if ( !objlist.empty() ) {
01736 sresult << " Programs : "<<coloron;
01737 for(vector<string>::iterator it = objlist.begin(); it != objlist.end(); ++it)
01738 sresult << *it << "["<<getProgramStatusChar(peer,*it)<<"] ";
01739 sresult << coloroff << nl;
01740 }
01741
01742 objlist = peer->scripting()->getStateMachines();
01743 if ( !objlist.empty() ) {
01744 sresult << " StateMachines: "<<coloron;
01745 for(vector<string>::iterator it = objlist.begin(); it != objlist.end(); ++it)
01746 sresult << *it << "["<<getStateMachineStatusChar(peer,*it)<<"] ";
01747 sresult << coloroff << nl;
01748 }
01749
01750 // if we are in the TB, display the peers of our connected task:
01751 if ( context == tb )
01752 sresult <<nl<< " "<<peer->getName()<<" Peers : "<<coloron;
01753 else
01754 sresult << nl <<" Peers : "<<coloron;
01755
01756 objlist = peer->getPeerList();
01757 if ( !objlist.empty() )
01758 for(vector<string>::iterator it = objlist.begin(); it != objlist.end(); ++it) {
01759 assert( peer->getPeer(*it) );
01760 sresult << *it << "["<<getTaskStatusChar(peer->getPeer(*it))<<"] ";
01761 }
01762 else
01763 sresult << "(none)";
01764 }
01765 sresult <<coloroff<<nl;
01766 cout << sresult.str();
01767 sresult.str("");
01768 }
01769
01770 void TaskBrowser::printCommand( const std::string m, OperationInterface* ops )
01771 {
01772 using boost::lambda::_1;
01773 std::vector<ArgumentDescription> args;
01774 args = ops->commands()->getArgumentList( m );
01775 sresult << " Command : bool " << coloron << m << coloroff<< "( ";
01776 for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); ++it) {
01777 sresult << it->type <<" ";
01778 sresult << coloron << it->name << coloroff;
01779 if ( it+1 != args.end() )
01780 sresult << ", ";
01781 else
01782 sresult << " ";
01783 }
01784 sresult << ")"<<nl;
01785 sresult << " " << ops->commands()->getDescription( m )<<nl;
01786 for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); ++it)
01787 sresult <<" "<< it->name <<" : " << it->description << nl;
01788 }
01789
01790 void TaskBrowser::printMethod( const std::string m, OperationInterface* ops )
01791 {
01792 std::vector<ArgumentDescription> args;
01793 args = ops->methods()->getArgumentList( m );
01794 sresult << " Method : "<< ops->methods()->getResultType(m)<<" " << coloron << m << coloroff<< "( ";
01795 for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); ++it) {
01796 sresult << it->type <<" ";
01797 sresult << coloron << it->name << coloroff;
01798 if ( it+1 != args.end() )
01799 sresult << ", ";
01800 else
01801 sresult << " ";
01802 }
01803 sresult << ")"<<nl;
01804 sresult << " " << ops->methods()->getDescription( m )<<nl;
01805 for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); ++it)
01806 sresult <<" "<< it->name <<" : " << it->description << nl;
01807 }
01808
01809 void TaskBrowser::printEvent( const std::string m, EventService* ops )
01810 {
01811 std::vector<ArgumentDescription> args;
01812 args = ops->getArgumentList( m );
01813 sresult << " Event : "<< ops->getResultType(m)<<" " << coloron << m << coloroff<< "( ";
01814 for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); ++it) {
01815 sresult << it->type <<" ";
01816 sresult << coloron << it->name << coloroff;
01817 if ( it+1 != args.end() )
01818 sresult << ", ";
01819 else
01820 sresult << " ";
01821 }
01822 sresult << ")"<<nl;
01823 sresult << " " << ops->getDescription( m )<<nl;
01824 for (std::vector<ArgumentDescription>::iterator it = args.begin(); it != args.end(); ++it)
01825 sresult <<" "<< it->name <<" : " << it->description << nl;
01826 }
01827
01828 }