PLearn 0.1
HelpSystem.cc
Go to the documentation of this file.
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&nbsp;by&nbsp;" 
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 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines