PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // HelpSystem.cc 00004 // Copyright (c) 2006 Pascal Vincent 00005 // Copyright (C) 2007 Xavier Saint-Mleux, ApSTAT Technologies, inc. 00006 00007 // Redistribution and use in source and binary forms, with or without 00008 // modification, are permitted provided that the following conditions are met: 00009 // 00010 // 1. Redistributions of source code must retain the above copyright 00011 // notice, this list of conditions and the following disclaimer. 00012 // 00013 // 2. Redistributions in binary form must reproduce the above copyright 00014 // notice, this list of conditions and the following disclaimer in the 00015 // documentation and/or other materials provided with the distribution. 00016 // 00017 // 3. The name of the authors may not be used to endorse or promote 00018 // products derived from this software without specific prior written 00019 // permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00031 // 00032 // This file is part of the PLearn library. For more information on the PLearn 00033 // library, go to the PLearn Web site at www.plearn.org 00034 00035 #include <plearn/base/Object.h> 00036 #include "HelpSystem.h" 00037 00038 #include <algorithm> 00039 00040 #include "stringutils.h" 00041 #include "tostring.h" 00042 #include <plearn/misc/HTMLUtils.h> 00043 00044 #include <plearn/io/openFile.h> 00045 #include <plearn/io/fileutils.h> 00046 #include <plearn/io/openString.h> 00047 00048 #include <plearn/base/TypeFactory.h> 00049 #include <plearn/base/RemoteTrampoline.h> 00050 #include <plearn/base/RemoteDeclareMethod.h> 00051 #include <plearn/base/RemoteMethodDoc.h> 00052 #include <plearn/base/RemoteMethodMap.h> 00053 #include <commands/PLearnCommands/PLearnCommandRegistry.h> 00054 //#include <plearn/base/Object.h> 00055 00056 00057 namespace PLearn { 00058 using namespace std; 00059 00060 00061 /***** 00062 * Commands 00063 */ 00064 00065 vector<string> HelpSystem::listCommands() 00066 { 00067 vector<string> commands; 00068 for(PLearnCommandRegistry::command_map::const_iterator 00069 it = PLearnCommandRegistry::allCommands().begin(); 00070 it != PLearnCommandRegistry::allCommands().end(); ++it) 00071 commands.push_back(it->first); 00072 return commands; 00073 } 00074 00075 string HelpSystem::helpCommands() 00076 { 00077 vector<string> commands= listCommands(); 00078 string s= ""; 00079 for(vector<string>::iterator it= commands.begin(); 00080 it != commands.end(); ++it) 00081 { 00082 PLearnCommand* cmd= PLearnCommandRegistry::getCommand(*it); 00083 s+= *it + "\t: " + cmd->description + '\n'; 00084 } 00085 return s+'\n'; 00086 } 00087 00088 string HelpSystem::helpOnCommand(const string& commandname) 00089 { 00090 PLearnCommand* cmd= PLearnCommandRegistry::getCommand(commandname); 00091 string help= "*** Help for command '" + commandname + "' ***\n"; 00092 help+= cmd->description + '\n'; 00093 help+= cmd->helpmsg + '\n'; 00094 return help; 00095 } 00096 00097 string HelpSystem::helpCommandsHTML() 00098 { 00099 string s; 00100 s.reserve(16384); 00101 s+= "<div class=\"generaltable\">\n" 00102 "<h2>Index of Available Commands</h2>\n" 00103 "<table cellspacing=\"0\" cellpadding=\"0\">\n"; 00104 00105 int i=0; 00106 vector<string> commands= listCommands(); 00107 for(vector<string>::iterator it= commands.begin(); 00108 it != commands.end(); ++it, ++i) 00109 { 00110 PLearnCommand* cmd= PLearnCommandRegistry::getCommand(*it); 00111 string helpurl= "command_" + *it + ".html"; 00112 string helphtml= "<a href=\"" + helpurl + "\">" + *it + "</a>"; 00113 s+= string(" <tr class=\"") + (i%2 == 0? "even" : "odd") + "\">\n" 00114 " <td>" + helphtml + "</td>" 00115 "<td>" + cmd->description + "</td></tr>\n"; 00116 } 00117 s+="</table>\n</div>\n"; 00118 return helpPrologueHTML("Command Index") + s + helpEpilogueHTML(); 00119 } 00120 00121 string HelpSystem::helpOnCommandHTML(const string& commandname) 00122 { 00123 PLearnCommand* cmd= PLearnCommandRegistry::getCommand(commandname); 00124 string s= string("<div class=\"cmdname\">") 00125 + HTMLUtils::quote(commandname) + "</div>\n" 00126 "<div class=\"cmddescr\">" 00127 + HTMLUtils::quote_format_and_highlight(cmd->description) + "</div>\n" 00128 "<div class=\"cmdhelp\">" 00129 + HTMLUtils::quote_format_and_highlight(cmd->helpmsg) 00130 + "</div>\n"; 00131 return helpPrologueHTML(commandname) + s + helpEpilogueHTML(); 00132 } 00133 00134 00135 /***** 00136 * Functions 00137 */ 00138 00139 vector<pair<string, int> > HelpSystem::listFunctions() 00140 { 00141 return getGlobalFunctionMap().getMethodList(); 00142 } 00143 00144 vector<string> HelpSystem::listFunctionPrototypes() 00145 { 00146 return getGlobalFunctionMap().getMethodPrototypes(); 00147 } 00148 00149 string HelpSystem::helpFunctions() 00150 { 00151 vector<pair<string, int> > funcs= listFunctions(); 00152 string s; 00153 for(vector<pair<string, int> >::iterator it= funcs.begin(); 00154 it != funcs.end(); ++it) 00155 s+= it->first +'('+tostring(it->second)+")\t:" 00156 + helpOnFunction(it->first, it->second) +'\n'; 00157 return s; 00158 } 00159 00160 string HelpSystem::helpOnFunction(const string& functionname, int arity) 00161 { 00162 return getGlobalFunctionMap().getMethodHelpText(functionname, arity); 00163 } 00164 00165 string HelpSystem::helpFunctionsHTML() 00166 { 00167 string s= "<div class=\"rmitable\">\n" 00168 "<h2>List of Functions</h2>\n" 00169 "<table cellspacing=\"0\" cellpadding=\"0\">\n"; 00170 s.reserve(32768); 00171 00172 vector<pair<string, int> > functions= listFunctions(); 00173 00174 int i= 0; 00175 for(vector<pair<string, int> >::iterator it= functions.begin(); 00176 it != functions.end(); ++it) 00177 s+= string("<tr class=\"") + (i++ == 0? "first" : "others") + "\">\n" 00178 + helpOnFunctionHTML(it->first, it->second) 00179 + "</tr>\n"; 00180 00181 PLERROR("In HelpSystem::helpFunctionsHTML - Error thrown because of " 00182 "commented code (see code for details)"); 00183 /* TODO The code below was commented because the 'index' variable was not 00184 * defined. It should probably be fixed and uncommented. 00185 if(index == 0) 00186 s+= "<tr><td>No Remote-Callable Functions.</td></tr>\n"; 00187 */ 00188 00189 s+= "</table></div>\n"; 00190 00191 return helpPrologueHTML("Function Index") + s + helpEpilogueHTML(); 00192 } 00193 00194 namespace 00195 { 00196 string formatMethodDocHTML(const RemoteMethodDoc& doc, const string& classname= "") 00197 { 00198 // Generate the function signature and argument-list table in HTML form 00199 string return_type = HTMLUtils::quote_format_and_highlight(doc.returnType()); 00200 string args = ""; 00201 string arg_table = ""; 00202 list<ArgDoc>::const_iterator adit= doc.argListDoc().begin(), 00203 adend= doc.argListDoc().end(); 00204 list<string>::const_iterator tyit= doc.argListType().begin(), 00205 tyend= doc.argListType().end(); 00206 int j=0; 00207 for( ; tyit != tyend ; ++tyit) 00208 { 00209 string arg_type= HTMLUtils::quote_format_and_highlight(*tyit); 00210 string arg_name= ""; 00211 string arg_doc= "(no documentation)"; 00212 00213 if(adit != adend) 00214 { 00215 arg_name= HTMLUtils::quote(adit->m_argument_name); 00216 arg_doc= HTMLUtils::quote_format_and_highlight(adit->m_doc); 00217 ++adit; 00218 } 00219 00220 if(!args.empty()) args += ", "; 00221 00222 args+= arg_type + ' ' + arg_name; 00223 00224 if(!arg_table.empty()) arg_table += "</tr><tr><td></td>"; 00225 00226 string td1_class = (++j % 2 == 0? "argnameeven" : "argnameodd"); 00227 string td2_class = ( j % 2 == 0? "argdoceven" : "argdocodd"); 00228 00229 arg_table+= 00230 " <td class=\"" + td1_class + "\">" + arg_type + ' ' + arg_name + "</td>" 00231 + " <td class=\"" + td2_class + "\">" + arg_doc + "</td>"; 00232 } 00233 00234 // Header 00235 string s= "<td colspan=\"3\"><div class=\"rmiprototype\">"; 00236 s+= return_type 00237 + " <span class=\"rmifuncname\">" + doc.name() + "</span>" 00238 + '(' + args + ')' + "</div>\n" 00239 "</tr><tr><td></td><td colspan=\"2\">" 00240 + HTMLUtils::quote_format_and_highlight(doc.bodyDoc()) 00241 + (classname == "" ? "" 00242 : " (defined by " + HTMLUtils::quote_format_and_highlight(classname) + ")") 00243 + "</td>"; 00244 00245 // Args table 00246 if(!arg_table.empty()) 00247 s+= "</tr>\n<tr>\n" 00248 "<td class=\"rmititle\">Arguments</td>\n" + arg_table; 00249 00250 // Ret. val 00251 string td1_class = (++j % 2 == 0? "argnameeven" : "argnameodd"); 00252 string td2_class = ( j % 2 == 0? "argdoceven" : "argdocodd"); 00253 00254 if(!doc.returnType().empty() || !doc.returnDoc().empty()) 00255 s+= "</tr>\n<tr>\n" 00256 "<td class=\"rmititle\">Returns</td>\n" 00257 "<td class=\"" + td1_class + "\">" + return_type + "</td>" 00258 "<td class=\"" + td2_class + "\">" 00259 + HTMLUtils::quote_format_and_highlight(doc.returnDoc()) + "</td>\n"; 00260 00261 //last <tr> s/b closed by calling fn. 00262 return s; 00263 } 00264 } 00265 00266 string HelpSystem::helpOnFunctionHTML(const string& functionname, int arity) 00267 { 00268 // the result is a list of table fields (<td>...</td>) 00269 // should be enclosed in a table row (<table><tr>...</tr></table>) 00270 const RemoteTrampoline* t= 00271 getGlobalFunctionMap().lookup(functionname, arity); 00272 PLASSERT(t); 00273 return formatMethodDocHTML(t->documentation()); 00274 } 00275 00276 /***** 00277 * Classes 00278 */ 00279 00280 vector<string> HelpSystem::listClasses() 00281 { 00282 const TypeMap& type_map = TypeFactory::instance().getTypeMap(); 00283 int nclasses = type_map.size(); 00284 vector<string> class_list(type_map.size()); 00285 TypeMap::const_iterator it = type_map.begin(); 00286 for(int k=0; k<nclasses; ++k, ++it) 00287 class_list[k] = it->first; 00288 return class_list; 00289 } 00290 00291 map<string, string> HelpSystem::getClassTree() 00292 { 00293 const TypeMap& type_map = TypeFactory::instance().getTypeMap(); 00294 map<string, string> class_tree; 00295 TypeMap::const_iterator it = type_map.begin(); 00296 TypeMap::const_iterator itend = type_map.end(); 00297 for(; it!=itend; ++it) 00298 class_tree[it->first] = it->second.parent_class; 00299 return class_tree; 00300 } 00301 00302 string HelpSystem::helpClasses() 00303 { 00304 vector<string> classes= listClasses(); 00305 string s= ""; 00306 for(vector<string>::iterator it= classes.begin(); 00307 it != classes.end(); ++it) 00308 { 00309 const TypeMapEntry& e= 00310 TypeFactory::instance().getTypeMapEntry(*it); 00311 s+= "- " + *it + "\t("+ e.parent_class +")\t: " 00312 + e.one_line_descr + '\n'; 00313 } 00314 return s+'\n'; 00315 } 00316 00317 string HelpSystem::helpOnClass(const string& classname) 00318 { 00319 00320 const TypeMap& type_map = TypeFactory::instance().getTypeMap(); 00321 TypeMap::const_iterator it = type_map.find(classname); 00322 TypeMap::const_iterator itend = type_map.end(); 00323 00324 if(it==itend) 00325 PLERROR("Object type %s unknown.\n" 00326 "Did you #include it, does it call the IMPLEMENT_NAME_AND_DEEPCOPY macro?\n" 00327 "and has it indeed been linked with your program?", classname.c_str()); 00328 00329 const TypeMapEntry& entry = it->second; 00330 Object* obj = 0; 00331 00332 string s= "################################################################## \n"; 00333 s+= "## " + classname + "\n"; 00334 s+= "## " + helpClassParents(classname) + '\n'; 00335 s+= "## declared in file '" + entry.declaring_file.canonical() + "'\n"; 00336 s+= "################################################################## \n\n"; 00337 00338 // Display basic help 00339 s+= addprefix("# ", entry.one_line_descr) + "\n\n"; 00340 s+= addprefix("# ", entry.multi_line_help) + "\n\n"; 00341 00342 if(entry.constructor) // it's an instantiable class 00343 obj = (*entry.constructor)(); 00344 else { 00345 string virtual_help = 00346 "Note: " + classname 00347 + " is a base-class with pure virtual methods that\n" 00348 "cannot be instantiated directly (default values for build options\n" 00349 "can only be displayed for instantiable classes, so you will only\n" 00350 "see question marks here).\n\n"; 00351 s += addprefix("# ", virtual_help); 00352 } 00353 00354 s+= "################################################################## \n" 00355 "## Build Options ## \n" 00356 "## (including those inherited from parent and ancestor classes) ## \n" 00357 "################################################################## \n\n"; 00358 s+= classname + "( \n"; 00359 s+= helpClassOptions(classname); 00360 s+= ");\n\n"; 00361 00362 if(obj) delete obj; 00363 00364 s+= "################################################################## \n"; 00365 s+= "## Subclasses of " + classname + " \n" 00366 "# (only those that can be instantiated) \n" 00367 "################################################################## \n\n"; 00368 s+= addprefix("# ", helpDerivedClasses(classname)); 00369 /* 00370 s+= "\n\n################################################################## \n"; 00371 s+= "## Remote-callable methods of " + classname + " \n" 00372 "################################################################## \n\n"; 00373 s+= addprefix("# ", helpMethods(classname)); 00374 */ 00375 s+= "\n\n################################################################## \n\n"; 00376 00377 return s; 00378 } 00379 00380 string HelpSystem::helpClassesHTML() 00381 { 00382 string s= "<div class=\"generaltable\">\n" 00383 "<h2>Index of Available Classes</h2>\n" 00384 "<table cellspacing=\"0\" cellpadding=\"0\">\n"; 00385 s.reserve(131072); 00386 int i=0; 00387 vector<string> classes= listClasses(); 00388 for(vector<string>::iterator it= classes.begin(); 00389 it != classes.end(); ++it) 00390 { 00391 const TypeMapEntry& e= TypeFactory::instance().getTypeMapEntry(*it); 00392 s+= string(" <tr class=\"") + (i++%2 == 0? "even" : "odd") + "\">\n" 00393 " <td>" 00394 + HTMLUtils::quote_format_and_highlight(*it) 00395 + "</td>\n" 00396 " <td>" 00397 + HTMLUtils::quote_format_and_highlight(e.one_line_descr) 00398 + '(' + HTMLUtils::quote_format_and_highlight(e.parent_class) + ')' 00399 + "</td></tr>\n"; 00400 } 00401 s+= "</table></div>\n"; 00402 return helpPrologueHTML("Class Index") + s + helpEpilogueHTML(); 00403 } 00404 00405 string HelpSystem::helpOnClassHTML(const string& classname) 00406 { 00407 string s= ""; 00408 s.reserve(65536); 00409 00410 // Output parents heading 00411 s+= helpClassParentsHTML(classname); 00412 00413 // Output general information 00414 const TypeMapEntry& entry= TypeFactory::instance().getTypeMapEntry(classname); 00415 s+= "<div class=\"classname\">" + HTMLUtils::quote(classname) + "</div>\n" 00416 "<div class=\"classdescr\">" 00417 + HTMLUtils::quote(entry.one_line_descr) 00418 + " (declared in '" + HTMLUtils::quote(entry.declaring_file.canonical()) 00419 + "')</div>\n" 00420 "<div class=\"classhelp\">" 00421 + HTMLUtils::quote_format_and_highlight(entry.multi_line_help) 00422 + "</div>\n"; 00423 00424 if(!entry.constructor) // it's not an instantiable class 00425 s+= "<div class=\"classhelp\"><b>Note:</b>" + HTMLUtils::quote(classname) 00426 + " is a base-class with pure virtual methods " 00427 "that cannot be instantiated directly.\n" 00428 "(default values for build options can only be " 00429 "displayed for instantiable classes, \n" 00430 " so you'll only see question marks here.)</div>\n"; 00431 00432 // Output list of options 00433 s+= helpClassOptionsHTML(classname); 00434 00435 // Output instantiable derived classes 00436 s+= helpDerivedClassesHTML(classname); 00437 00438 // Output remote-callable methods 00439 s+= helpMethodsHTML(classname); 00440 00441 return helpPrologueHTML(classname) + s + helpEpilogueHTML(); 00442 } 00443 00444 00445 vector<string> HelpSystem::listClassParents(const string& classname) 00446 { 00447 string cl= classname; 00448 vector<string> parents; 00449 const TypeMapEntry* e= 00450 &TypeFactory::instance().getTypeMapEntry(cl); 00451 bool known_parent= true; 00452 while(known_parent && e->parent_class != cl) 00453 { 00454 cl= e->parent_class; 00455 parents.push_back(cl); 00456 if(TypeFactory::instance().isRegistered(cl)) 00457 e= &TypeFactory::instance().getTypeMapEntry(cl); 00458 else 00459 { 00460 known_parent= false; 00461 parents.push_back("!?!UNKNOWN_PARENT_CLASS!?!"); 00462 } 00463 } 00464 return parents; 00465 } 00466 00467 string HelpSystem::helpClassParents(const string& classname) 00468 { 00469 vector<string> parents= listClassParents(classname); 00470 string s= ""; 00471 for(vector<string>::reverse_iterator it= parents.rbegin(); 00472 it != parents.rend(); ++it) 00473 s+= *it + " > "; 00474 return s + classname; 00475 } 00476 00477 string HelpSystem::helpClassParentsHTML(const string& classname) 00478 { 00479 return string("<div class=\"crumbtrail\">") 00480 + HTMLUtils::quote_format_and_highlight(helpClassParents(classname)) 00481 + "</div>"; 00482 } 00483 00484 vector<string> HelpSystem::listDerivedClasses(const string& classname) 00485 { 00486 const TypeMapEntry& entry= 00487 TypeFactory::instance().getTypeMapEntry(classname); 00488 const TypeMap& the_map= TypeFactory::instance().getTypeMap(); 00489 vector<string> classes; 00490 for(TypeMap::const_iterator it= the_map.begin(); 00491 it != the_map.end(); ++it) 00492 { 00493 const TypeMapEntry& e= it->second; 00494 if(e.constructor && it->first!=classname) 00495 { 00496 Object* o= (*e.constructor)(); 00497 if((*entry.isa_method)(o)) 00498 classes.push_back(it->first); 00499 if(o) delete o; 00500 } 00501 } 00502 return classes; 00503 } 00504 00505 string HelpSystem::helpDerivedClasses(const string& classname) 00506 { 00507 vector<string> classes= listDerivedClasses(classname); 00508 string s= ""; 00509 for(vector<string>::iterator it= classes.begin(); 00510 it != classes.end(); ++it) 00511 s+= right(*it, 30) + " - " 00512 + TypeFactory::instance().getTypeMapEntry(*it).one_line_descr 00513 + '\n'; 00514 return s; 00515 } 00516 00517 string HelpSystem::helpDerivedClassesHTML(const string& classname) 00518 { 00519 // Output instantiable derived classes 00520 vector<string> classes= listDerivedClasses(classname); 00521 00522 string s= "<div class=\"generaltable\">\n" 00523 "<h2>List of Instantiable Derived Classes</h2>\n" 00524 "<table cellspacing=\"0\" cellpadding=\"0\">\n"; 00525 00526 int i= 0; 00527 for(vector<string>::iterator it= classes.begin(); 00528 it != classes.end(); ++it) 00529 s+= string(" <tr class=\"") + (i++%2 == 0? "even" : "odd") + "\">\n" 00530 " <td>" 00531 + HTMLUtils::quote_format_and_highlight(*it) + "</td><td>" 00532 + HTMLUtils::quote_format_and_highlight( 00533 TypeFactory::instance().getTypeMapEntry(*it).one_line_descr) 00534 + " </td> </tr>\n"; 00535 00536 if(i==0) 00537 s+= "<tr><td>This class does not have instantiable " 00538 "derived classes.</td></tr>\n"; 00539 00540 return s+"</table></div>\n"; 00541 } 00542 00543 pair<string, vector<string> > HelpSystem::precisOnClass(const string& classname) 00544 { 00545 const TypeMapEntry& tme = TypeFactory::instance().getTypeMapEntry(classname); 00546 return make_pair(tme.one_line_descr, listBuildOptions(classname)); 00547 } 00548 00549 00550 /***** 00551 * Options 00552 */ 00553 00554 vector<string> HelpSystem::listClassOptions(const string& classname) 00555 { 00556 vector<pair<OptionBase::OptionLevel, string> > optswl= 00557 listClassOptionsWithLevels(classname); 00558 int nopts= optswl.size(); 00559 vector<string> opts(nopts); 00560 for(int i= 0; i < nopts; ++i) 00561 opts[i]= optswl[i].second; 00562 return opts; 00563 } 00564 00565 vector<string> HelpSystem::listBuildOptions(const string& classname) 00566 { 00567 vector<pair<OptionBase::OptionLevel, string> > optswl= 00568 listBuildOptionsWithLevels(classname); 00569 int nopts= optswl.size(); 00570 vector<string> opts(nopts); 00571 for(int i= 0; i < nopts; ++i) 00572 opts[i]= optswl[i].second; 00573 return opts; 00574 } 00575 00576 vector<pair<OptionBase::OptionLevel, string> > 00577 HelpSystem::listClassOptionsWithLevels(const string& classname, 00578 const OptionBase::flag_t& flags) 00579 { 00580 const TypeMapEntry& e= TypeFactory::instance().getTypeMapEntry(classname); 00581 OptionList& optlist= (*e.getoptionlist_method)(); 00582 int nopts= optlist.size(); 00583 vector<pair<OptionBase::OptionLevel, string> > options; 00584 for(int i= 0; i < nopts; ++i) 00585 if(optlist[i]->flags() & flags) 00586 options.push_back(make_pair(optlist[i]->level(), 00587 optlist[i]->optionname())); 00588 return options; 00589 } 00590 00591 vector<pair<OptionBase::OptionLevel, string> > 00592 HelpSystem::listBuildOptionsWithLevels(const string& classname) 00593 { return listClassOptionsWithLevels(classname, OptionBase::buildoption); } 00594 00595 string HelpSystem::helpClassOptions(const string& classname) 00596 { 00597 string s= ""; 00598 vector<pair<OptionBase::OptionLevel, string> > options= 00599 listClassOptionsWithLevels(classname); 00600 sort(options.begin(), options.end()); 00601 OptionBase::OptionLevel lvl= 0; 00602 OptionBase::OptionLevel curlvl= OptionBase::getCurrentOptionLevel(); 00603 int nbeyond= 0; 00604 for(vector<pair<OptionBase::OptionLevel, string> >::iterator 00605 it= options.begin(); it != options.end(); ++it) 00606 { 00607 if(lvl != it->first) 00608 { 00609 lvl= it->first; 00610 if(lvl <= curlvl) 00611 s+= "##############################\n" 00612 "# Options for level " 00613 + OptionBase::optionLevelToString(lvl) 00614 + "\n\n"; 00615 } 00616 if(lvl <= curlvl) 00617 s+= helpOnOption(classname, it->second) + '\n'; 00618 else 00619 ++nbeyond; 00620 } 00621 if(nbeyond > 0) 00622 s+= "##############################\n" 00623 "# " + tostring(nbeyond) 00624 + " hidden options beyond level " 00625 + OptionBase::optionLevelToString(curlvl) 00626 + "\n\n"; 00627 return s; 00628 } 00629 00630 string HelpSystem::helpOnOption(const string& classname, const string& optionname) 00631 { 00632 string s= ""; 00633 PP<OptionBase> opt= getOptionByName(classname, optionname); 00634 OptionBase::flag_t flags = opt->flags(); 00635 if(flags & OptionBase::buildoption 00636 && opt->level() <= OptionBase::getCurrentOptionLevel()) 00637 s+= addprefix("# ", opt->optiontype() + ": " + opt->description()) 00638 //+ addprefix("# ", "*OptionLevel: " + opt->levelString()) 00639 + "\n" + opt->optionname() + " = " 00640 + getOptionDefaultVal(classname, optionname) + " ;\n\n"; 00641 00642 return s; 00643 } 00644 00645 string HelpSystem::helpClassOptionsHTML(const string& classname) 00646 { 00647 string s= "<div class=\"generaltable\">\n" 00648 "<h2>List of All Options</h2>\n" 00649 "<table cellspacing=\"0\" cellpadding=\"0\">\n"; 00650 s.reserve(32768); 00651 00652 vector<string> options= listClassOptions(classname); 00653 int i= 0; 00654 for(vector<string>::iterator it= options.begin(); 00655 it != options.end(); ++it) 00656 { 00657 PP<OptionBase> opt= getOptionByName(classname, *it); 00658 if(opt->flags() & OptionBase::buildoption 00659 && opt->level() <= OptionBase::getCurrentOptionLevel()) 00660 { 00661 s+= string(" <tr class=\"") + (i % 2 == 0? "even" : "odd") + "\">\n" 00662 + helpOnOptionHTML(classname, *it) + "</tr>\n"; 00663 ++i; 00664 } 00665 } 00666 00667 if (i==0) 00668 s+= "<tr><td>This class does not specify any build options.</td></tr>\n"; 00669 00670 s+= "</table></div>\n"; 00671 return s; 00672 } 00673 00674 string HelpSystem::helpOnOptionHTML(const string& classname, const string& optionname) 00675 { 00676 // the result is a list of table fields (<td>...</td>) 00677 // should be enclosed in a table row (<table><tr>...</tr></table>) 00678 string s= ""; 00679 PP<OptionBase> opt= getOptionByName(classname, optionname); 00680 s+= " <td><div class=\"opttype\">" 00681 + HTMLUtils::quote_format_and_highlight(opt->optiontype()) + "</div>\n" 00682 " <div class=\"optname\">" 00683 + HTMLUtils::quote(opt->optionname()) + "</div>\n"; 00684 00685 string defaultval= getOptionDefaultVal(classname, optionname); 00686 if (defaultval != "?") 00687 s+= " <div class=\"optvalue\">= " 00688 + HTMLUtils::quote(defaultval) + "</div>\n"; 00689 00690 string flag_string = join(opt->flagStrings(), " | "); 00691 s+= string(" <div class=\"opttype\"><i>(") 00692 + join(opt->flagStrings(), " | ") + ")</i></div>\n" 00693 + " <div class=\"optlevel\"><i>(OptionLevel: " 00694 + opt->levelString() + ")</i></div>\n" 00695 " </td>\n"; 00696 00697 string descr= opt->description(); 00698 if (removeblanks(descr) == "") descr = "(no description)"; 00699 s+= string(" <td>")+HTMLUtils::quote_format_and_highlight(descr); 00700 00701 string defclass= getOptionDefiningClass(classname, optionname); 00702 if (defclass != "") 00703 s+= string(" <span class=\"fromclass\">") 00704 + "(defined by " 00705 + HTMLUtils::highlight_known_classes(defclass) + ")" 00706 "</span>\n"; 00707 s+= " </td>\n"; 00708 return s; 00709 } 00710 00711 string HelpSystem::getOptionDefaultVal(const string& classname, 00712 const string& optionname) 00713 { 00714 PP<OptionBase> opt= getOptionByName(classname, optionname); 00715 const TypeMapEntry& entry= TypeFactory::instance().getTypeMapEntry(classname); 00716 Object* obj= 0; 00717 if(entry.constructor) obj= (*entry.constructor)(); 00718 00719 string defaultval= "?"; 00720 if(obj) // it's an instantiable class 00721 { 00722 defaultval= opt->defaultval(); 00723 if(defaultval=="") defaultval= opt->writeIntoString(obj); 00724 delete obj; 00725 } 00726 return defaultval; 00727 } 00728 00729 string HelpSystem::getOptionDefiningClass(const string& classname, 00730 const string& optionname) 00731 { 00732 PP<OptionBase> opt= getOptionByName(classname, optionname); 00733 const TypeMapEntry& entry= TypeFactory::instance().getTypeMapEntry(classname); 00734 string defclass= ""; 00735 if(entry.constructor) 00736 { 00737 Object* obj= (*entry.constructor)(); 00738 defclass= opt->optionHolderClassName(obj); 00739 delete obj; 00740 } 00741 return defclass; 00742 } 00743 00744 /***** 00745 * Methods 00746 */ 00747 00748 vector<pair<string, int> > HelpSystem::listMethods(const string& classname) 00749 { 00750 return TypeFactory::instance().getTypeMapEntry(classname). 00751 get_remote_methods().getMethodList(); 00752 } 00753 00754 vector<string> HelpSystem::listMethodPrototypes(const string& classname) 00755 { 00756 return TypeFactory::instance().getTypeMapEntry(classname). 00757 get_remote_methods().getMethodPrototypes(); 00758 } 00759 00760 string HelpSystem::helpMethods(const string& classname) 00761 { 00762 vector<pair<string, int> > methods= listMethods(classname); 00763 string s= ""; 00764 for(vector<pair<string, int> >::iterator it= methods.begin(); 00765 it != methods.end(); ++it) 00766 s+= string("\n##########\n") 00767 + helpOnMethod(classname, it->first, it->second) + '\n'; 00768 return s; 00769 } 00770 00771 string HelpSystem::helpOnMethod(const string& classname, 00772 const string& methodname, int arity) 00773 { 00774 return TypeFactory::instance().getTypeMapEntry(classname) 00775 .get_remote_methods().getMethodHelpText(methodname, arity); 00776 } 00777 00778 string HelpSystem::helpMethodsHTML(const string& classname) 00779 { 00780 string s= "<div class=\"rmitable\">\n" 00781 "<h2>List of Remote-Callable Methods</h2>\n" 00782 "<table cellspacing=\"0\" cellpadding=\"0\">\n"; 00783 00784 vector<string> parents= listClassParents(classname); 00785 parents.insert(parents.begin(), classname); 00786 vector<pair<string, int> > methods; 00787 map<pair<string, int>, string> definingclass; 00788 for(vector<string>::iterator it= parents.begin(); 00789 it != parents.end(); ++it) 00790 { 00791 vector<pair<string, int> > ms= listMethods(*it); 00792 for(vector<pair<string, int> >::iterator jt= ms.begin(); 00793 jt != ms.end(); ++jt) 00794 { 00795 if(definingclass.find(*jt) == definingclass.end()) 00796 methods.push_back(*jt); 00797 definingclass[*jt]= *it; 00798 } 00799 } 00800 00801 int i= 0; 00802 for(vector<pair<string, int> >::iterator it= methods.begin(); 00803 it != methods.end(); ++it) 00804 s+= string("<tr class=\"") + (i++ == 0? "first" : "others") + "\">\n" 00805 + helpOnMethodHTML(definingclass[*it], it->first, it->second) 00806 + "</tr>\n"; 00807 00808 PLERROR("In HelpSystem::helpMethodsHTML - Error thrown because of " 00809 "commented code (see code for details)"); 00810 /* TODO The code below was commented because the 'index' variable was not 00811 * defined. It should probably be fixed and uncommented. 00812 if(index == 0) 00813 s+= "<tr><td>This class does not define any remote-callable methods.</td></tr>\n"; 00814 00815 */ 00816 s+= "</table></div>\n"; 00817 00818 return s; 00819 } 00820 00821 string HelpSystem::helpOnMethodHTML(const string& classname, 00822 const string& methodname, int arity) 00823 { 00824 // the result is a list of table fields (<td>...</td>) 00825 // should be enclosed in a table row (<table><tr>...</tr></table>) 00826 const RemoteTrampoline* t= TypeFactory::instance().getTypeMapEntry(classname) 00827 .get_remote_methods().lookup(methodname, arity); 00828 PLASSERT(t); 00829 return formatMethodDocHTML(t->documentation(), classname); 00830 } 00831 00832 00833 /*** 00834 * General Stuff 00835 */ 00836 00837 string HelpSystem::html_resources_path; // init. 00838 00839 string HelpSystem::helpIndexHTML() 00840 { 00841 static PPath from_dir= ""; 00842 static string the_index= string("<div class=\"cmdname\">\n") 00843 + "Welcome to PLearn User-Level Class and Commands Help\n" 00844 "</div>" 00845 "<div class=\"cmdhelp\">\n" 00846 "<ul>\n" 00847 " <li> <a href=\"classes_index.html\">Class Index</a>\n" 00848 " <li> <a href=\"commands_index.html\">Command Index</a>\n" 00849 " <li> <a href=\"functions_index.html\">Function Index</a>\n" 00850 "</ul></div>\n"; 00851 00852 if(from_dir != html_resources_path) 00853 { 00854 from_dir= html_resources_path; 00855 PPath indexfile= from_dir/"index.html"; 00856 if(pathexists(indexfile)) 00857 { 00858 PStream f= openFile(indexfile, 00859 PStream::raw_ascii); 00860 the_index= f.readAll(); 00861 } 00862 } 00863 00864 return helpPrologueHTML() + the_index + helpEpilogueHTML(); 00865 } 00866 00867 string HelpSystem::helpPrologueHTML(const string& title) 00868 { 00869 static PPath from_dir= ""; 00870 static string the_prologue= "<html><body>"; 00871 00872 if(from_dir != html_resources_path) 00873 { 00874 from_dir= html_resources_path; 00875 PStream f= openFile(from_dir/"help_prolog.html", 00876 PStream::raw_ascii); 00877 the_prologue= f.readAll(); 00878 } 00879 00880 map<string, string> dic; 00881 dic["PAGE_TITLE"]= title; 00882 PStream stm= openString(the_prologue, PStream::raw_ascii); 00883 time_t latest = 0; 00884 return readAndMacroProcess(stm, dic, latest, false); 00885 } 00886 00887 string HelpSystem::helpEpilogueHTML() 00888 { 00889 static PPath from_dir= ""; 00890 static string the_epilogue= "</body></html>"; 00891 00892 if(from_dir != html_resources_path) 00893 { 00894 from_dir= html_resources_path; 00895 PStream f= openFile(from_dir/"help_epilog.html", 00896 PStream::raw_ascii); 00897 the_epilogue= f.readAll(); 00898 } 00899 00900 return HTMLUtils::generated_by() + the_epilogue; 00901 } 00902 00903 00904 00905 BEGIN_DECLARE_REMOTE_FUNCTIONS 00906 00907 // Commands 00908 00909 declareFunction("listCommands", &HelpSystem::listCommands, 00910 (BodyDoc("Returns a list of all registered " 00911 "commands as strings."), 00912 RetDoc ("vector of command names"))); 00913 00914 declareFunction("helpCommands", &HelpSystem::helpCommands, 00915 (BodyDoc("Returns a plain text list of all " 00916 "registered commands."), 00917 RetDoc ("plain text list of commands"))); 00918 00919 declareFunction("helpOnCommand", &HelpSystem::helpOnCommand, 00920 (BodyDoc("Will return full help for the " 00921 "command with the given name "), 00922 ArgDoc ("commandname", 00923 "The name of the command on which to get help"), 00924 RetDoc ("help text for the command"))); 00925 00926 // HTML 00927 declareFunction("helpCommandsHTML", &HelpSystem::helpCommandsHTML, 00928 (BodyDoc("Returns an HTML list of all " 00929 "registered commands."), 00930 RetDoc ("HTML list of commands"))); 00931 00932 declareFunction("helpOnCommandHTML", &HelpSystem::helpOnCommandHTML, 00933 (BodyDoc("Will return full help for the " 00934 "command with the given name, in HTML"), 00935 ArgDoc ("commandname", 00936 "The name of the command on which to get help"), 00937 RetDoc ("help text for the command, in HTML"))); 00938 00939 // Functions 00940 00941 declareFunction("listFunctions", &HelpSystem::listFunctions, 00942 (BodyDoc("Returns a list of all registered global " 00943 "functions as pairs of (funtionname, nargs)"), 00944 RetDoc ("vector of function names, arity"))); 00945 00946 declareFunction("listFunctionPrototypes", 00947 &HelpSystem::listFunctionPrototypes, 00948 (BodyDoc("Returns a list of the prototypes " 00949 "of all registered global functions"), 00950 RetDoc ("vector of function prototypes as strings"))); 00951 00952 declareFunction("helpFunctions", &HelpSystem::helpFunctions, 00953 (BodyDoc("Returns a list of all registered global " 00954 "functions as plain text"), 00955 RetDoc ("plain text list of functions"))); 00956 00957 declareFunction("helpOnFunction", &HelpSystem::helpOnFunction, 00958 (BodyDoc("Will return full help on all registered " 00959 "global functions with the given name "), 00960 ArgDoc ("functionname", 00961 "The name of the function on which to get help"), 00962 ArgDoc ("arity", "The number of params"), 00963 RetDoc ("help text for the function"))); 00964 00965 // HTML 00966 declareFunction("helpFunctionsHTML", &HelpSystem::helpFunctionsHTML, 00967 (BodyDoc("Returns a list of all registered global " 00968 "functions as an HTML page."), 00969 RetDoc ("HTML list of functions"))); 00970 00971 declareFunction("helpOnFunctionHTML", &HelpSystem::helpOnFunctionHTML, 00972 (BodyDoc("Will return full HTML help on all registered " 00973 "global functions with the given name "), 00974 ArgDoc ("functionname", 00975 "The name of the function on which to get help"), 00976 ArgDoc ("arity", "The number of params"), 00977 RetDoc ("HTML help text for the function"))); 00978 00979 // Classes 00980 00981 declareFunction("listClasses", &HelpSystem::listClasses, 00982 (BodyDoc("Returns a list of all registered Object classes"), 00983 RetDoc ("vector of class names"))); 00984 00985 declareFunction("getClassTree", &HelpSystem::getClassTree, 00986 (BodyDoc("Returns a map, mapping all registered " 00987 "Object classnames to their parentclassname"), 00988 RetDoc ("map of class names to class names"))); 00989 00990 declareFunction("helpClasses", &HelpSystem::helpClasses, 00991 (BodyDoc("Returns a plain text list of all registered Object classes"), 00992 RetDoc ("plain text list of class names"))); 00993 00994 declareFunction("helpOnClass", &HelpSystem::helpOnClass, 00995 (BodyDoc("Will return full help for " 00996 "the class with the given name"), 00997 ArgDoc ("classname", 00998 "The name of the class on which to get help"), 00999 RetDoc ("help text for the class"))); 01000 01001 declareFunction("precisOnClass", &HelpSystem::precisOnClass, 01002 (BodyDoc("Will return short class descr. and list of build options"), 01003 ArgDoc ("classname", 01004 "The name of the class on which to get help"), 01005 RetDoc ("pair of classname and list of options"))); 01006 01007 // HTML 01008 declareFunction("helpClassesHTML", &HelpSystem::helpClassesHTML, 01009 (BodyDoc("Returns a list of all registered Object " 01010 "classes as an HTML page."), 01011 RetDoc ("HTML list of class names"))); 01012 01013 declareFunction("helpOnClassHTML", &HelpSystem::helpOnClassHTML, 01014 (BodyDoc("Will return full HTML help for " 01015 "the class with the given name"), 01016 ArgDoc ("classname", 01017 "The name of the class on which to get help"), 01018 RetDoc ("HTML help text for the class"))); 01019 // Parents 01020 declareFunction("listClassParents", &HelpSystem::listClassParents, 01021 (BodyDoc("List of parent classes."), 01022 ArgDoc ("classname", 01023 "The name of the class on which to get parents"), 01024 RetDoc ("vector of parent class names"))); 01025 01026 declareFunction("helpClassParents", &HelpSystem::helpClassParents, 01027 (BodyDoc("Text list of parent classes."), 01028 ArgDoc ("classname", 01029 "The name of the class on which to get parents"), 01030 RetDoc ("text list of parent class names"))); 01031 01032 declareFunction("helpClassParentsHTML", &HelpSystem::helpClassParentsHTML, 01033 (BodyDoc("HTML list of parent classes."), 01034 ArgDoc ("classname", 01035 "The name of the class on which to get parents"), 01036 RetDoc ("HTML list of parent class names"))); 01037 // Children 01038 declareFunction("listDerivedClasses", &HelpSystem::listDerivedClasses, 01039 (BodyDoc("List of derived classes."), 01040 ArgDoc ("classname", 01041 "The name of the class on which to get children"), 01042 RetDoc ("List of derived class names"))); 01043 01044 declareFunction("helpDerivedClasses", &HelpSystem::helpDerivedClasses, 01045 (BodyDoc("Text list of derived classes."), 01046 ArgDoc ("classname", 01047 "The name of the class on which to get children"), 01048 RetDoc ("Text list of derived class names"))); 01049 01050 declareFunction("helpDerivedClassesHTML", &HelpSystem::helpDerivedClassesHTML, 01051 (BodyDoc("HTML list of derived classes."), 01052 ArgDoc ("classname", 01053 "The name of the class on which to get children"), 01054 RetDoc ("HTML list of derived class names"))); 01055 01056 // Options 01057 01058 declareFunction("listClassOptions", &HelpSystem::listClassOptions, 01059 (BodyDoc("Returns a list of all options " 01060 "for the given class."), 01061 ArgDoc ("classname", "The name of the class " 01062 "on which to get option help"), 01063 RetDoc ("vector of option names"))); 01064 01065 declareFunction("listBuildOptions", &HelpSystem::listBuildOptions, 01066 (BodyDoc("Returns a list of build options " 01067 "for the given class."), 01068 ArgDoc ("classname", "The name of the class " 01069 "on which to get option help"), 01070 RetDoc ("vector of option names"))); 01071 01072 declareFunction("helpOnOption", &HelpSystem::helpOnOption, 01073 (BodyDoc("Will return full help for the option with " 01074 "the given name within the given class"), 01075 ArgDoc ("classname", "The name of the class " 01076 "on which to get option help"), 01077 ArgDoc ("optionname", 01078 "The name of the option on which to get help"), 01079 RetDoc ("help text for the option"))); 01080 // HTML 01081 declareFunction("helpClassOptionsHTML", &HelpSystem::helpClassOptionsHTML, 01082 (BodyDoc("Returns a list of all options " 01083 "for the given class as an HTML page."), 01084 ArgDoc ("classname", "The name of the class " 01085 "on which to get option help"), 01086 RetDoc ("HTML list of option names"))); 01087 01088 declareFunction("helpOnOptionHTML", &HelpSystem::helpOnOptionHTML, 01089 (BodyDoc("Will return full HTML help for the option " 01090 "with the given name within the given class"), 01091 ArgDoc ("classname", "The name of the class " 01092 "on which to get option help"), 01093 ArgDoc ("optionname", 01094 "The name of the option on which to get help"), 01095 RetDoc ("HTML help text for the option"))); 01096 01097 // Methods 01098 01099 declareFunction("listMethods", &HelpSystem::listMethods, 01100 (BodyDoc("Returns a list of all registered methods " 01101 "for the given class as pairs of (methodname, nargs)"), 01102 ArgDoc ("classname", 01103 "The name of the class whose methods you want to list."), 01104 RetDoc ("vector of method names"))); 01105 01106 declareFunction("listMethodPrototypes", 01107 &HelpSystem::listMethodPrototypes, 01108 (BodyDoc("Returns a list of the prototypes of " 01109 "all registered methods for the given class"), 01110 ArgDoc ("classname", "The name of the class " 01111 "whose method prototypes you want to list."), 01112 RetDoc ("vector of prototypes as strings"))); 01113 01114 declareFunction("helpMethods", &HelpSystem::helpMethods, 01115 (BodyDoc("Returns a list of all registered methods " 01116 "for the given class as text."), 01117 ArgDoc ("classname", 01118 "The name of the class whose methods you want to list."), 01119 RetDoc ("Text list of method names"))); 01120 01121 declareFunction("helpOnMethod", &HelpSystem::helpOnMethod, 01122 (BodyDoc("Will return full help on all registered " 01123 "methods of the class with the given name"), 01124 ArgDoc ("classname", "The name of the class"), 01125 ArgDoc ("methodname", "The name of the method"), 01126 ArgDoc ("arity", "The number of params"), 01127 RetDoc ("help text"))); 01128 01129 // HTML 01130 declareFunction("helpMethodsHTML", &HelpSystem::helpMethodsHTML, 01131 (BodyDoc("Returns a list of all registered methods " 01132 "for the given class as an HTML page."), 01133 ArgDoc ("classname", 01134 "The name of the class whose methods you want to list."), 01135 RetDoc ("HTML list of method names"))); 01136 01137 declareFunction("helpOnMethodHTML", &HelpSystem::helpOnMethodHTML, 01138 (BodyDoc("Will return full help on all registered " 01139 "methods of the class with the given name"), 01140 ArgDoc ("classname", "The name of the class"), 01141 ArgDoc ("methodname", "The name of the method"), 01142 ArgDoc ("arity", "The number of params"), 01143 RetDoc ("help text in HTML"))); 01144 01145 // HTML-only 01146 01147 declareFunction("helpIndexHTML", &HelpSystem::helpIndexHTML, 01148 (BodyDoc("Returns the global help index in HTML."), 01149 RetDoc ("HTML global help index"))); 01150 01151 declareFunction("setResourcesPathHTML", 01152 &HelpSystem::setResourcesPathHTML, 01153 (BodyDoc("Sets the help resource path " 01154 "for HTML resources."), 01155 ArgDoc ("path","HTML help resource path"))); 01156 01157 declareFunction("getResourcesPathHTML", 01158 &HelpSystem::getResourcesPathHTML, 01159 (BodyDoc("Gets the help resource path " 01160 "for HTML resources."), 01161 RetDoc ("path of HTML resources"))); 01162 01163 END_DECLARE_REMOTE_FUNCTIONS 01164 01165 01166 PP<OptionBase> HelpSystem::getOptionByName(const string& classname, 01167 const string& optionname) 01168 { 01169 const TypeMapEntry& e= TypeFactory::instance().getTypeMapEntry(classname); 01170 OptionList& optlist= (*e.getoptionlist_method)(); 01171 for(OptionList::iterator it= optlist.begin(); 01172 it != optlist.end(); ++it) 01173 if((*it)->optionname() == optionname) 01174 return *it; 01175 return 0;//not found... 01176 } 01177 01178 01179 } // end of namespace PLearn 01180 01181 01182 /* 01183 Local Variables: 01184 mode:c++ 01185 c-basic-offset:4 01186 c-file-style:"stroustrup" 01187 c-file-offsets:((innamespace . 0)(inline-open . 0)) 01188 indent-tabs-mode:nil 01189 fill-column:79 01190 End: 01191 */ 01192 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :