From 58bf0dbac1ab2d394b1e0c9a47520ec37a7aaf8a Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 1 Feb 2007 10:38:42 -0500 Subject: [PATCH] ENH: Patch from Alex to improve implementation and prepare for splitting the man page into more sections. --- Source/cmDocumentation.cxx | 299 ++++++++++++++++++------------------- Source/cmDocumentation.h | 78 ++++++++-- 2 files changed, 215 insertions(+), 162 deletions(-) diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index a03d267c0..65946658a 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -158,6 +158,19 @@ const cmDocumentationEntry cmDocumentationCopyright[] = //---------------------------------------------------------------------------- cmDocumentation::cmDocumentation() +:NameSection ("Name", "NAME") +,UsageSection ("Usage", "SYNOPSIS") +,DescriptionSection ("", "DESCRIPTION") +,OptionsSection ("Command-Line Options", "OPTIONS") +,CommandsSection ("Listfile Commands", "COMMANDS") +,CompatCommandsSection("Compatibility Listfile Commands", + "COMPATIBILITY COMMANDS") +,ModulesSection ("Standard CMake Modules", "MODULES") +,PropertiesSection ("Standard Properties", "PROPERTIES") +,GeneratorsSection ("Generators", "GENERATORS") +,SeeAlsoSection ("See Also", "SEE ALSO") +,CopyrightSection ("Copyright", "COPYRIGHT") +,AuthorSection ("Author", "AUTHOR") { this->CurrentForm = TextForm; this->TextIndent = ""; @@ -212,6 +225,16 @@ void cmDocumentation::AddSection(const char* name, this->Sections.push_back(d); } +//---------------------------------------------------------------------------- +void cmDocumentation::AddSection(const cmSection& section) +{ + if (!section.IsEmpty()) + { + this->Names.push_back(section.GetName(this->CurrentForm)); + this->Sections.push_back(section.GetEntries()); + } +} + //---------------------------------------------------------------------------- void cmDocumentation::ClearSections() { @@ -222,26 +245,49 @@ void cmDocumentation::ClearSections() //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os) { - if ( ht != cmDocumentation::HTML && - ht != cmDocumentation::Man ) + if(ht != cmDocumentation::HTML && ht != cmDocumentation::Man) { this->PrintVersion(os); } + switch (ht) { - case cmDocumentation::Usage: return this->PrintDocumentationUsage(os); - case cmDocumentation::Single: + case cmDocumentation::Full: this->CurrentForm = TextForm; break; + case cmDocumentation::HTML: this->CurrentForm = HTMLForm; break; + case cmDocumentation::Man: this->CurrentForm = ManForm; break; + case cmDocumentation::Usage: + case cmDocumentation::Single: + case cmDocumentation::SingleModule: + case cmDocumentation::SingleProperty: + case cmDocumentation::List: + case cmDocumentation::ModuleList: + case cmDocumentation::PropertyList: + case cmDocumentation::Copyright: + case cmDocumentation::Version: + this->CurrentForm = UsageForm; + break; + case cmDocumentation::None: + break; + } + + switch (ht) + { + case cmDocumentation::Usage: + return this->PrintDocumentationUsage(os); + case cmDocumentation::Single: return this->PrintDocumentationSingle(os); - case cmDocumentation::SingleModule: + case cmDocumentation::SingleModule: return this->PrintDocumentationSingleModule(os); - case cmDocumentation::SingleProperty: + case cmDocumentation::SingleProperty: return this->PrintDocumentationSingleProperty(os); case cmDocumentation::List: return this->PrintDocumentationList(os); case cmDocumentation::ModuleList: return this->PrintModuleList(os); case cmDocumentation::PropertyList: return this->PrintPropertyList(os); - case cmDocumentation::Full: return this->PrintDocumentationFull(os); - case cmDocumentation::HTML: return this->PrintDocumentationHTML(os); - case cmDocumentation::Man: return this->PrintDocumentationMan(os); + + case cmDocumentation::Full: + case cmDocumentation::HTML: + case cmDocumentation::Man: return this->PrintDocumentationFull(os); + case cmDocumentation::Copyright: return this->PrintCopyright(os); case cmDocumentation::Version: return true; default: return false; @@ -251,7 +297,7 @@ bool cmDocumentation::PrintDocumentation(Type ht, std::ostream& os) //---------------------------------------------------------------------------- bool cmDocumentation::CreateModulesSection() { - this->ModulesSection.push_back(cmDocumentationModulesHeader[0]); + this->ModulesSection.Append(cmDocumentationModulesHeader[0]); std::string cmakeModules = this->CMakeRoot; cmakeModules += "/Modules"; cmsys::Directory dir; @@ -272,7 +318,7 @@ bool cmDocumentation::CreateModulesSection() } } cmDocumentationEntry e = { 0, 0, 0 }; - this->ModulesSection.push_back(e); + this->ModulesSection.Append(e); return true; } @@ -354,7 +400,7 @@ bool cmDocumentation::CreateSingleModule(const char* fname, char* pbrief = strcpy(new char[brief.length()+1], brief.c_str()); this->ModuleStrings.push_back(pbrief); cmDocumentationEntry e = { pname, pbrief, ptext }; - this->ModulesSection.push_back(e); + this->ModulesSection.Append(e); return true; } } @@ -373,10 +419,10 @@ bool cmDocumentation::PrintRequestedDocumentation(std::ostream& os) { // Special case for printing help for a single command. if(i->first == cmDocumentation::Usage && i->second.length() > 0 && - !this->CommandsSection.empty()) + !this->CommandsSection.IsEmpty()) { // Check if the argument to the usage request was a command. - for(cmDocumentationEntry* entry = &this->CommandsSection[0]; + for(cmDocumentationEntry* entry = this->CommandsSection.GetEntries(); entry->brief; ++entry) { if(entry->name && (strcmp(entry->name, i->second.c_str()) == 0)) @@ -534,6 +580,12 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv) void cmDocumentation::Print(Form f, std::ostream& os) { this->CurrentForm = f; + Print(os); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::Print(std::ostream& os) +{ for(unsigned int i=0; i < this->Sections.size(); ++i) { this->PrintSection(os, this->Sections[i], this->Names[i]); @@ -549,56 +601,52 @@ void cmDocumentation::SetName(const char* name) //---------------------------------------------------------------------------- void cmDocumentation::SetNameSection(const cmDocumentationEntry* section) { - this->SetSection(0, section, 0, this->NameSection); + this->NameSection.Set(0, section, 0); } //---------------------------------------------------------------------------- void cmDocumentation::SetUsageSection(const cmDocumentationEntry* section) { - this->SetSection(0, section, 0, this->UsageSection); + this->UsageSection.Set(0, section, 0); } //---------------------------------------------------------------------------- void cmDocumentation ::SetDescriptionSection(const cmDocumentationEntry* section) { - this->SetSection(0, section, 0, this->DescriptionSection); + this->DescriptionSection.Set(0, section, 0); } //---------------------------------------------------------------------------- void cmDocumentation::SetOptionsSection(const cmDocumentationEntry* section) { - this->SetSection(0, section, cmDocumentationStandardOptions, - this->OptionsSection); + this->OptionsSection.Set(0, section, cmDocumentationStandardOptions); } //---------------------------------------------------------------------------- void cmDocumentation::SetCommandsSection(const cmDocumentationEntry* section) { - this->SetSection(cmDocumentationCommandsHeader, section, 0, - this->CommandsSection); + this->CommandsSection.Set(cmDocumentationCommandsHeader, section, 0); } //---------------------------------------------------------------------------- void cmDocumentation ::SetPropertiesSection(const cmDocumentationEntry* section) { - this->SetSection(cmDocumentationPropertiesHeader, section, 0, - this->PropertiesSection); + this->PropertiesSection.Set(cmDocumentationPropertiesHeader, section, 0); } //---------------------------------------------------------------------------- void cmDocumentation ::SetGeneratorsSection(const cmDocumentationEntry* section) { - this->SetSection(cmDocumentationGeneratorsHeader, section, 0, - this->GeneratorsSection); + this->GeneratorsSection.Set(cmDocumentationGeneratorsHeader, section, 0); } //---------------------------------------------------------------------------- void cmDocumentation::SetSeeAlsoList(const cmDocumentationEntry* also) { - this->SeeAlsoSection.clear(); + this->SeeAlsoSection.Clear(); this->SeeAlsoString = ".B "; for(const cmDocumentationEntry* i = also; i->brief; ++i) { @@ -607,14 +655,14 @@ void cmDocumentation::SetSeeAlsoList(const cmDocumentationEntry* also) } cmDocumentationEntry e = {0, 0, 0}; e.brief = this->SeeAlsoString.c_str(); - this->SeeAlsoSection.push_back(e); + this->SeeAlsoSection.Append(e); for(const cmDocumentationEntry* i = cmDocumentationStandardSeeAlso; i->brief; ++i) { - this->SeeAlsoSection.push_back(*i); + this->SeeAlsoSection.Append(*i); } e.brief = 0; - this->SeeAlsoSection.push_back(e); + this->SeeAlsoSection.Append(e); } //---------------------------------------------------------------------------- @@ -1097,7 +1145,7 @@ void cmDocumentation::PrintHTMLEscapes(std::ostream& os, const char* text) //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationSingle(std::ostream& os) { - if(this->CommandsSection.empty()) + if(this->CommandsSection.IsEmpty()) { os << "Internal error: commands list is empty." << std::endl; return false; @@ -1107,7 +1155,7 @@ bool cmDocumentation::PrintDocumentationSingle(std::ostream& os) os << "Argument --help-command needs a command name.\n"; return false; } - for(cmDocumentationEntry* entry = &this->CommandsSection[0]; + for(cmDocumentationEntry* entry = this->CommandsSection.GetEntries(); entry->brief; ++entry) { if(entry->name && this->SingleCommand == entry->name) @@ -1139,7 +1187,7 @@ bool cmDocumentation::PrintDocumentationSingleModule(std::ostream& os) && this->CreateSingleModule(cmakeModules.c_str(), this->SingleModuleName.c_str())) { - this->PrintDocumentationCommand(os, &this->ModulesSection[0]); + this->PrintDocumentationCommand(os, this->ModulesSection.GetEntries()); os << "\n Defined in: "; os << cmakeModules << "\n"; return true; @@ -1153,7 +1201,7 @@ bool cmDocumentation::PrintDocumentationSingleModule(std::ostream& os) //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationSingleProperty(std::ostream& os) { - if(this->PropertiesSection.empty()) + if(this->PropertiesSection.IsEmpty()) { os << "Internal error: properties list is empty." << std::endl; return false; @@ -1163,7 +1211,7 @@ bool cmDocumentation::PrintDocumentationSingleProperty(std::ostream& os) os << "Argument --help-property needs a property name.\n"; return false; } - for(cmDocumentationEntry* entry = &this->PropertiesSection[0]; + for(cmDocumentationEntry* entry = this->PropertiesSection.GetEntries(); entry->brief; ++entry) { if(entry->name && this->SinglePropertyName == entry->name) @@ -1182,12 +1230,12 @@ bool cmDocumentation::PrintDocumentationSingleProperty(std::ostream& os) //---------------------------------------------------------------------------- bool cmDocumentation::PrintDocumentationList(std::ostream& os) { - if(this->CommandsSection.empty()) + if(this->CommandsSection.IsEmpty()) { os << "Internal error: commands list is empty." << std::endl; return false; } - for(cmDocumentationEntry* entry = &this->CommandsSection[0]; + for(cmDocumentationEntry* entry = this->CommandsSection.GetEntries(); entry->brief; ++entry) { if(entry->name) @@ -1201,12 +1249,12 @@ bool cmDocumentation::PrintDocumentationList(std::ostream& os) //---------------------------------------------------------------------------- bool cmDocumentation::PrintPropertyList(std::ostream& os) { - if(this->PropertiesSection.empty()) + if(this->PropertiesSection.IsEmpty()) { os << "Internal error: properties list is empty." << std::endl; return false; } - for(cmDocumentationEntry* entry = &this->PropertiesSection[0]; + for(cmDocumentationEntry* entry = this->PropertiesSection.GetEntries(); entry->brief; ++entry) { if(entry->name) @@ -1221,12 +1269,12 @@ bool cmDocumentation::PrintPropertyList(std::ostream& os) bool cmDocumentation::PrintModuleList(std::ostream& os) { this->CreateModulesSection(); - if(this->ModulesSection.empty()) + if(this->ModulesSection.IsEmpty()) { os << "Internal error: modules list is empty." << std::endl; return false; } - for(cmDocumentationEntry* entry = &this->ModulesSection[0]; + for(cmDocumentationEntry* entry = this->ModulesSection.GetEntries(); entry->brief; ++entry) { if(entry->name) @@ -1241,7 +1289,7 @@ bool cmDocumentation::PrintModuleList(std::ostream& os) bool cmDocumentation::PrintDocumentationUsage(std::ostream& os) { this->CreateUsageDocumentation(); - this->Print(UsageForm, os); + this->Print(os); return true; } @@ -1249,31 +1297,46 @@ bool cmDocumentation::PrintDocumentationUsage(std::ostream& os) bool cmDocumentation::PrintDocumentationFull(std::ostream& os) { this->CreateFullDocumentation(); - this->Print(TextForm, os); + this->PrintHeader(GetNameString(), os); + this->Print(os); + this->PrintFooter(os); return true; } //---------------------------------------------------------------------------- -bool cmDocumentation::PrintDocumentationHTML(std::ostream& os) +void cmDocumentation::PrintHeader(const char* name, std::ostream& os) { - this->CreateFullDocumentation(); + switch(this->CurrentForm) + { + case HTMLForm: os << "\n"; - this->Print(HTMLForm, os); - os << "\n"; - return true; -} - -//---------------------------------------------------------------------------- -bool cmDocumentation::PrintDocumentationMan(std::ostream& os) -{ - this->CreateManDocumentation(); - os << ".TH " << this->GetNameString() << " 1 \"" + break; + case ManForm: + os << ".TH " << name << " 1 \"" << cmSystemTools::GetCurrentDateTime("%B %d, %Y").c_str() << "\" \"" << this->GetNameString() << " " << cmVersion::GetCMakeVersion() << "\"\n"; - this->Print(ManForm, os); - return true; + break; + case TextForm: + case UsageForm: + break; + } +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintFooter(std::ostream& os) +{ + switch(this->CurrentForm) + { + case HTMLForm: + os << "\n"; + break; + case ManForm: + case TextForm: + case UsageForm: + break; + } } //---------------------------------------------------------------------------- @@ -1287,140 +1350,76 @@ void cmDocumentation::PrintDocumentationCommand(std::ostream& os, }; this->ClearSections(); this->AddSection(0, &singleCommandSection[0]); - this->Print(TextForm, os); + this->Print(os); } //---------------------------------------------------------------------------- void cmDocumentation::CreateUsageDocumentation() { this->ClearSections(); - if(!this->UsageSection.empty()) - { - this->AddSection("Usage", &this->UsageSection[0]); - } - if(!this->OptionsSection.empty()) - { - this->AddSection("Command-Line Options", &this->OptionsSection[0]); - } - if(!this->GeneratorsSection.empty()) - { - this->AddSection("Generators", &this->GeneratorsSection[0]); - } + this->AddSection(this->UsageSection); + this->AddSection(this->OptionsSection); + this->AddSection(this->GeneratorsSection); } //---------------------------------------------------------------------------- void cmDocumentation::CreateFullDocumentation() { this->ClearSections(); - if(!this->NameSection.empty()) - { - this->AddSection("Name", &this->NameSection[0]); - } - if(!this->UsageSection.empty()) - { - this->AddSection("Usage", &this->UsageSection[0]); - } - if(!this->DescriptionSection.empty()) - { - this->AddSection(0, &this->DescriptionSection[0]); - } - if(!this->OptionsSection.empty()) - { - this->AddSection("Command-Line Options", &this->OptionsSection[0]); - } - if(!this->GeneratorsSection.empty()) - { - this->AddSection("Generators", &this->GeneratorsSection[0]); - } - if(!this->CommandsSection.empty()) - { - this->AddSection("Listfile Commands", &this->CommandsSection[0]); - } this->CreateModulesSection(); - if(!this->ModulesSection.empty()) + this->AddSection(this->NameSection); + this->AddSection(this->UsageSection); + this->AddSection(this->DescriptionSection); + this->AddSection(this->OptionsSection); + this->AddSection(this->GeneratorsSection); + this->AddSection(this->CommandsSection); + this->AddSection(this->ModulesSection); + this->AddSection(this->PropertiesSection); + this->AddSection(this->CopyrightSection.GetName(this->CurrentForm), + cmDocumentationCopyright); + + if(this->CurrentForm == ManForm) { - this->AddSection("Standard CMake Modules", &this->ModulesSection[0]); + this->AddSection(this->SeeAlsoSection); + this->AddSection(this->AuthorSection.GetName(ManForm), + cmDocumentationAuthor); } - if(!this->PropertiesSection.empty()) + else { - this->AddSection("Standard Properties", &this->PropertiesSection[0]); + this->AddSection(this->SeeAlsoSection.GetName(TextForm), + cmDocumentationStandardSeeAlso); } - this->AddSection("Copyright", cmDocumentationCopyright); - this->AddSection("See Also", cmDocumentationStandardSeeAlso); } //---------------------------------------------------------------------------- -void cmDocumentation::CreateManDocumentation() +void cmDocumentation::cmSection::Set(const cmDocumentationEntry* header, + const cmDocumentationEntry* section, + const cmDocumentationEntry* footer) { - this->ClearSections(); - if(!this->NameSection.empty()) - { - this->AddSection("NAME", &this->NameSection[0]); - } - if(!this->UsageSection.empty()) - { - this->AddSection("SYNOPSIS", &this->UsageSection[0]); - } - if(!this->DescriptionSection.empty()) - { - this->AddSection("DESCRIPTION", &this->DescriptionSection[0]); - } - if(!this->OptionsSection.empty()) - { - this->AddSection("OPTIONS", &this->OptionsSection[0]); - } - if(!this->GeneratorsSection.empty()) - { - this->AddSection("GENERATORS", &this->GeneratorsSection[0]); - } - if(!this->CommandsSection.empty()) - { - this->AddSection("COMMANDS", &this->CommandsSection[0]); - } - this->CreateModulesSection(); - if(!this->ModulesSection.empty()) - { - this->AddSection("MODULES", &this->ModulesSection[0]); - } - - this->AddSection("COPYRIGHT", cmDocumentationCopyright); - if(!this->SeeAlsoSection.empty()) - { - this->AddSection("SEE ALSO", &this->SeeAlsoSection[0]); - } - this->AddSection("AUTHOR", cmDocumentationAuthor); -} - -//---------------------------------------------------------------------------- -void cmDocumentation::SetSection(const cmDocumentationEntry* header, - const cmDocumentationEntry* section, - const cmDocumentationEntry* footer, - std::vector& vec) -{ - vec.erase(vec.begin(), vec.end()); + this->Entries.erase(this->Entries.begin(), this->Entries.end()); if(header) { for(const cmDocumentationEntry* op = header; op->brief; ++op) { - vec.push_back(*op); + this->Entries.push_back(*op); } } if(section) { for(const cmDocumentationEntry* op = section; op->brief; ++op) { - vec.push_back(*op); + this->Entries.push_back(*op); } } if(footer) { for(const cmDocumentationEntry* op = footer; op->brief; ++op) { - vec.push_back(*op); + this->Entries.push_back(*op); } } cmDocumentationEntry empty = {0,0,0}; - vec.push_back(empty); + this->Entries.push_back(empty); } //---------------------------------------------------------------------------- diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index 0aa81de93..0820042f7 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -85,12 +85,59 @@ public: /** Forms of documentation output. */ enum Form { TextForm, HTMLForm, ManForm, UsageForm }; + + /** Internal class representing a section of the documentation. + * Cares e.g. for the different section titles in the different + * output formats. + */ + class cmSection + { + public: + /** Create a cmSection, with a special name for man-output mode. */ + cmSection(const char* name, const char* manName) + :Name(name), ManName(manName) {} + + /** Has any content been added to this section or is it empty ? */ + bool IsEmpty() const {return Entries.empty();} + + /** Clear contents. */ + void Clear() {Entries.clear();} + + /** Return the name of this section for the given output form. */ + const char* GetName(Form form) const {return (form==ManForm?ManName.c_str():Name.c_str());} + + /** Return a pointer to the first entry of this section. */ + cmDocumentationEntry *GetEntries() {return &Entries[0];} + + /** Return a pointer to the first entry of this section. */ + const cmDocumentationEntry *GetEntries() const {return &Entries[0];} + + /** Append an entry to this section. */ + void Append(const cmDocumentationEntry& entry){Entries.push_back(entry);} + + /** Set the contents of this section. */ + void Set(const cmDocumentationEntry* header, + const cmDocumentationEntry* section, + const cmDocumentationEntry* footer); + + private: + std::string Name; + std::string ManName; + std::vector Entries; + }; + /** * Print documentation in the given form. All previously added * sections will be generated. */ void Print(Form f, std::ostream& os); + /** + * Print documentation in the current form. All previously added + * sections will be generated. + */ + void Print(std::ostream& os); + /** * Add a section of documentation. The cmDocumentationEntry pointer * should point at an array terminated by an all zero ({0,0,0}) @@ -98,12 +145,18 @@ public: */ void AddSection(const char* name, const cmDocumentationEntry* d); + /** Convenience function, does the same as above */ + void AddSection(const cmSection& section); + /** Clear all previously added sections of help. */ void ClearSections(); /** Set cmake root so we can find installed files */ void SetCMakeRoot(const char* root) { this->CMakeRoot = root;} private: + void PrintHeader(const char* title, std::ostream& os); + void PrintFooter(std::ostream& os); + void PrintSection(std::ostream& os, const cmDocumentationEntry* section, const char* name); @@ -142,14 +195,11 @@ private: bool PrintDocumentationSingleProperty(std::ostream& os); bool PrintDocumentationUsage(std::ostream& os); bool PrintDocumentationFull(std::ostream& os); - bool PrintDocumentationHTML(std::ostream& os); - bool PrintDocumentationMan(std::ostream& os); void PrintDocumentationCommand(std::ostream& os, cmDocumentationEntry* entry); void CreateUsageDocumentation(); void CreateFullDocumentation(); - void CreateManDocumentation(); void SetSection(const cmDocumentationEntry* header, const cmDocumentationEntry* section, @@ -159,15 +209,19 @@ private: bool IsOption(const char* arg) const; std::string NameString; - std::vector NameSection; - std::vector UsageSection; - std::vector DescriptionSection; - std::vector OptionsSection; - std::vector CommandsSection; - std::vector ModulesSection; - std::vector PropertiesSection; - std::vector GeneratorsSection; - std::vector SeeAlsoSection; + cmSection NameSection; + cmSection UsageSection; + cmSection DescriptionSection; + cmSection OptionsSection; + cmSection CommandsSection; + cmSection CompatCommandsSection; + cmSection ModulesSection; + cmSection PropertiesSection; + cmSection GeneratorsSection; + cmSection SeeAlsoSection; + cmSection CopyrightSection; + cmSection AuthorSection; + std::string SeeAlsoString; std::string SingleCommand; std::string SingleModuleName;