diff options
author | Brad King <brad.king@kitware.com> | 2003-02-18 20:42:02 -0500 |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2003-02-18 20:42:02 -0500 |
commit | 5e18bec8f76a811e48d2c31a954d0de44e8c5c11 (patch) | |
tree | 7c9f61e2a5d552f3ce69c2dd80618edc2cdf0af2 /Source | |
parent | ba56262ae21686670b26935d3a89cabc6f4d8a1f (diff) | |
download | cmake-5e18bec8f76a811e48d2c31a954d0de44e8c5c11.tar.gz |
ENH: Re-implemented document generation class to be more organized and more robust.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CursesDialog/ccmake.cxx | 19 | ||||
-rw-r--r-- | Source/cmDocumentation.cxx | 789 | ||||
-rw-r--r-- | Source/cmDocumentation.h | 132 | ||||
-rw-r--r-- | Source/cmakemain.cxx | 18 |
4 files changed, 590 insertions, 368 deletions
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index 47ae7ee559..a9386a2cb5 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -30,8 +30,8 @@ //---------------------------------------------------------------------------- static const cmDocumentationEntry cmDocumentationName[] = { - {"ccmake", - "- Curses Interface for CMake.", 0}, + {0, + " ccmake - Curses Interface for CMake.", 0}, {0,0,0} }; @@ -39,7 +39,7 @@ static const cmDocumentationEntry cmDocumentationName[] = static const cmDocumentationEntry cmDocumentationUsage[] = { {0, - "ccmake <path-to-source>", 0}, + " ccmake <path-to-source>", 0}, {0,0,0} }; @@ -88,10 +88,15 @@ int main(int argc, char** argv) cmDocumentation doc; if(cmDocumentation::Type ht = doc.CheckOptions(argc, argv)) { - doc.SetName(cmDocumentationName); - doc.SetUsage(cmDocumentationUsage); - doc.SetDescription(cmDocumentationDescription); - doc.Print(ht, std::cout); + cmake hcm; + std::vector<cmDocumentationEntry> commands; + hcm.GetCommandDocumentation(commands); + doc.SetNameSection(cmDocumentationName); + doc.SetUsageSection(cmDocumentationUsage); + doc.SetDescriptionSection(cmDocumentationDescription); + doc.SetOptionsSection(0); + doc.SetCommandsSection(&commands[0]); + doc.PrintDocumentation(ht, std::cout); return 0; } diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx index 8ea414e62e..1e2e695735 100644 --- a/Source/cmDocumentation.cxx +++ b/Source/cmDocumentation.cxx @@ -49,37 +49,45 @@ const cmDocumentationEntry cmDocumentationMailingList[] = { {0, "For help and discussion about using cmake, a mailing list is provided " - "at cmake@www.cmake.org. Please first read the full documentation at " + "at cmake@www.cmake.org. Please first read the full documentation at " "http://www.cmake.org before posting questions to the list.", 0}, {0,0,0} }; //---------------------------------------------------------------------------- +const cmDocumentationEntry cmDocumentationAuthor[] = +{ + {0, + "This manual page was generated by \"cmake --help-man\".", 0}, + {0,0,0} +}; + +//---------------------------------------------------------------------------- const cmDocumentationEntry cmDocumentationCopyright[] = { {0, - "Copyright (c) 2002 Kitware, Inc., Insight Consortium.\n" - "All rights reserved.\n", 0}, + "Copyright (c) 2002 Kitware, Inc., Insight Consortium. " + "All rights reserved.", 0}, {0, "Redistribution and use in source and binary forms, with or without " "modification, are permitted provided that the following conditions are " - "met:\n", 0}, - {" * ", + "met:", 0}, + {"", "Redistributions of source code must retain the above copyright notice, " - "this list of conditions and the following disclaimer.\n", 0}, - {" * ", + "this list of conditions and the following disclaimer.", 0}, + {"", "Redistributions in binary form must reproduce the above copyright " "notice, this list of conditions and the following disclaimer in the " - "documentation and/or other materials provided with the distribution.\n", + "documentation and/or other materials provided with the distribution.", 0}, - {" * ", + {"", "The names of Kitware, Inc., the Insight Consortium, or the names of " "any consortium members, or of any contributors, may not be used to " "endorse or promote products derived from this software without " - "specific prior written permission.\n", 0}, - {" * ", + "specific prior written permission.", 0}, + {"", "Modified source versions must be plainly marked as such, and must " - "not be misrepresented as being the original software.\n", 0}, + "not be misrepresented as being the original software.", 0}, {0, "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS " "``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT " @@ -91,124 +99,218 @@ const cmDocumentationEntry cmDocumentationCopyright[] = "PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF " "LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING " "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS " - "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n", 0}, + "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.", 0}, {0, 0, 0} }; //---------------------------------------------------------------------------- cmDocumentation::cmDocumentation() { - this->SetCommands(0); - this->Description = 0; - this->Name = 0; - this->UsageHelp = 0; - this->SetOptions(0); + this->CurrentForm = TextForm; + this->TextIndent = ""; + this->TextWidth = 77; } //---------------------------------------------------------------------------- -void cmDocumentation::PrintManSection(std::ostream& os, - const cmDocumentationEntry* section, - const char* name) +void cmDocumentation::PrintCopyright(std::ostream& os) { - if(!section) { return; } - os << ".SH " << name << "\n"; - for(const cmDocumentationEntry* op = section; op->brief; ++op) + os << "CMake version " CMake_VERSION_STRING "\n"; + for(const cmDocumentationEntry* op = cmDocumentationCopyright; + op->brief; ++op) { if(op->name) { - os << ".TP\n" - << ".B " << op->name << "\n" - << op->brief << "\n\n"; - if(op->full) - { - this->PrintFull(os, op->full, 0, 0); - } + os << " * "; + this->TextIndent = " "; + this->PrintColumn(os, op->brief); } else { - os << ".PP\n" - << op->brief << "\n"; + this->TextIndent = ""; + this->PrintColumn(os, op->brief); } - } + os << "\n"; + } } //---------------------------------------------------------------------------- -void cmDocumentation::PrintHelpSection(std::ostream& os, - const cmDocumentationEntry* section) +void cmDocumentation::PrintVersion(std::ostream& os) { - if(!section) { return; } - for(const cmDocumentationEntry* op = section; op->brief; ++op) + os << "CMake version " CMake_VERSION_STRING "\n"; +} + +//---------------------------------------------------------------------------- +void cmDocumentation::AddSection(const char* name, + const cmDocumentationEntry* d) +{ + this->Names.push_back(name); + this->Sections.push_back(d); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::ClearSections() +{ + this->Names.erase(this->Names.begin(), this->Names.end()); + this->Sections.erase(this->Sections.begin(), this->Sections.end()); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintDocumentation(Type ht, std::ostream& os) +{ + switch (ht) { - if(op->name) - { - os << " " << op->name << "\n" - << " "; - this->PrintColumn(os, 70, " ", op->brief); - if(op->full) - { - os << "\n" - << "\n" - << " "; - this->PrintColumn(os, 70, " ", op->full); - } - os << "\n"; - } - else - { - this->PrintColumn(os, 77, "", op->brief); - os << "\n"; - } - os << "\n"; - } + case cmDocumentation::Usage: this->PrintDocumentationUsage(os); break; + case cmDocumentation::Full: this->PrintDocumentationFull(os); break; + case cmDocumentation::HTML: this->PrintDocumentationHTML(os); break; + case cmDocumentation::Man: this->PrintDocumentationMan(os); break; + case cmDocumentation::Copyright: this->PrintCopyright(os); break; + case cmDocumentation::Version: this->PrintVersion(os); break; + default: break; + } } //---------------------------------------------------------------------------- -void cmDocumentation::PrintHTMLEscapes(std::ostream& os, const char* text) +cmDocumentation::Type cmDocumentation::CheckOptions(int argc, char** argv) { - static cmDocumentationEntry escapes[] = - { - {"<", "<", 0}, - {">", ">", 0}, - {"&", "&", 0}, - {"\n", "<br>", 0}, - {0,0,0} - }; - for(const char* p = text; *p; ++p) + for(int i=1; i < argc; ++i) { - bool found = false; - for(const cmDocumentationEntry* op = escapes; !found && op->name; ++op) + if((strcmp(argv[i], "-help") == 0) || + (strcmp(argv[i], "--help") == 0) || + (strcmp(argv[i], "/?") == 0) || + (strcmp(argv[i], "-usage") == 0) || + (strcmp(argv[i], "-h") == 0) || + (strcmp(argv[i], "-H") == 0)) { - if(op->name[0] == *p) - { - os << op->brief; - found = true; - } + return cmDocumentation::Usage; } - if(!found) + if(strcmp(argv[i], "--help-full") == 0) { - os << *p; + return cmDocumentation::Full; + } + if(strcmp(argv[i], "--help-html") == 0) + { + return cmDocumentation::HTML; + } + if(strcmp(argv[i], "--help-man") == 0) + { + return cmDocumentation::Man; + } + if(strcmp(argv[i], "--copyright") == 0) + { + return cmDocumentation::Copyright; + } + if((strcmp(argv[i], "--version") == 0) || + (strcmp(argv[i], "-version") == 0) || + (strcmp(argv[i], "-V") == 0) || + (strcmp(argv[i], "/V") == 0)) + { + return cmDocumentation::Version; } } + return cmDocumentation::None; } //---------------------------------------------------------------------------- -void cmDocumentation::PrintHTMLPreformatted(std::ostream& os, const char* text) +void cmDocumentation::Print(Form f, std::ostream& os) { - os << "<pre>"; - cmDocumentation::PrintHTMLEscapes(os, text); - os << "</pre>"; + this->CurrentForm = f; + for(int i=0; i < this->Sections.size(); ++i) + { + this->PrintSection(os, this->Sections[i], this->Names[i]); + } +} + +//---------------------------------------------------------------------------- +void cmDocumentation::SetNameSection(const cmDocumentationEntry* section) +{ + this->SetSection(0, section, 0, this->NameSection); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::SetUsageSection(const cmDocumentationEntry* section) +{ + this->SetSection(0, section, 0, this->UsageSection); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::SetDescriptionSection(const cmDocumentationEntry* section) +{ + this->SetSection(0, section, 0, this->DescriptionSection); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::SetOptionsSection(const cmDocumentationEntry* section) +{ + this->SetSection(0, section, cmDocumentationStandardOptions, + this->OptionsSection); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::SetCommandsSection(const cmDocumentationEntry* section) +{ + this->SetSection(cmDocumentationCommandsHeader, section, 0, + this->CommandsSection); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintSection(std::ostream& os, + const cmDocumentationEntry* section, + const char* name) +{ + switch (this->CurrentForm) + { + case TextForm: this->PrintSectionText(os, section, name); break; + case HTMLForm: this->PrintSectionHTML(os, section, name); break; + case ManForm: this->PrintSectionMan(os, section, name); break; + case UsageForm: this->PrintSectionUsage(os, section, name); break; + } } //---------------------------------------------------------------------------- -void cmDocumentation::PrintHelpHTMLSection(std::ostream& os, - const cmDocumentationEntry* section, - const char* header) +void cmDocumentation::PrintSectionText(std::ostream& os, + const cmDocumentationEntry* section, + const char* name) { + if(name) + { + os << name << "\n\n"; + } if(!section) { return; } - if(header) + for(const cmDocumentationEntry* op = section; op->brief; ++op) { - os << "<h2>" << header << "</h2>\n"; + if(op->name) + { + if(op->name[0]) + { + os << " " << op->name << "\n"; + } + this->TextIndent = " "; + this->PrintFormatted(os, op->brief); + if(op->full) + { + os << "\n"; + this->PrintFormatted(os, op->full); + } + } + else + { + this->TextIndent = ""; + this->PrintFormatted(os, op->brief); + } + os << "\n"; + } +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintSectionHTML(std::ostream& os, + const cmDocumentationEntry* section, + const char* name) +{ + if(name) + { + os << "<h2>" << name << "</h2>\n"; } + if(!section) { return; } for(const cmDocumentationEntry* op = section; op->brief;) { if(op->name) @@ -217,16 +319,17 @@ void cmDocumentation::PrintHelpHTMLSection(std::ostream& os, for(;op->name;++op) { os << " <li>\n"; - os << " <b><code>"; - this->PrintHTMLEscapes(os, op->name); - os << "</code></b>: "; + if(op->name[0]) + { + os << " <b><code>"; + this->PrintHTMLEscapes(os, op->name); + os << "</code></b>: "; + } this->PrintHTMLEscapes(os, op->brief); if(op->full) { - os << "<br>"; - this->PrintFull(os, op->full, - &cmDocumentation::PrintHTMLPreformatted, - &cmDocumentation::PrintHTMLEscapes); + os << "<br>\n "; + this->PrintFormatted(os, op->full); } os << "\n"; os << " </li>\n"; @@ -235,7 +338,7 @@ void cmDocumentation::PrintHelpHTMLSection(std::ostream& os, } else { - this->PrintHTMLEscapes(os, op->brief); + this->PrintFormatted(os, op->brief); os << "\n"; ++op; } @@ -243,136 +346,202 @@ void cmDocumentation::PrintHelpHTMLSection(std::ostream& os, } //---------------------------------------------------------------------------- -void cmDocumentation::PrintUsageSection(std::ostream& os, - const cmDocumentationEntry* section) +void cmDocumentation::PrintSectionMan(std::ostream& os, + const cmDocumentationEntry* section, + const char* name) { + if(name) + { + os << ".SH " << name << "\n"; + } + if(!section) { return; } + for(const cmDocumentationEntry* op = section; op->brief; ++op) + { + if(op->name) + { + os << ".TP\n" + << ".B " << (op->name[0]?op->name:"*") << "\n"; + this->PrintFormatted(os, op->brief); + this->PrintFormatted(os, op->full); + } + else + { + os << ".PP\n"; + this->PrintFormatted(os, op->brief); + } + } +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintSectionUsage(std::ostream& os, + const cmDocumentationEntry* section, + const char* name) +{ + if(name) + { + os << name << "\n"; + } if(!section) { return; } for(const cmDocumentationEntry* op = section; op->brief; ++op) { if(op->name) { os << " " << op->name; - for(int i = static_cast<int>(strlen(op->name)); i < 25; ++i) + this->TextIndent = " "; + int align = static_cast<int>(strlen(this->TextIndent))-4; + for(int i = static_cast<int>(strlen(op->name)); i < align; ++i) { os << " "; } - os << "= " << op->brief << "\n"; + os << "= "; + this->PrintColumn(os, op->brief); + os << "\n"; } else { os << "\n"; - this->PrintColumn(os, 74, "", op->brief); + this->TextIndent = ""; + this->PrintFormatted(os, op->brief); os << "\n"; } - } -} - -//---------------------------------------------------------------------------- -void cmDocumentation::PrintUsage(std::ostream& os) -{ - os << "Usage:\n"; - this->PrintUsageSection(os, this->UsageHelp); - this->PrintUsageSection(os, &this->Options[0]); + } } //---------------------------------------------------------------------------- -void cmDocumentation::PrintHelp(std::ostream& os) +void cmDocumentation::PrintFormatted(std::ostream& os, const char* text) { - os << "Usage:\n"; - os << "\n"; - this->PrintHelpSection(os, this->UsageHelp); - this->PrintHelpSection(os, this->Description); - os << "--------------------------------------------------------------------------\n"; - this->PrintHelpSection(os, &this->Options[0]); - os << "--------------------------------------------------------------------------\n"; - this->PrintHelpSection(os, &this->Commands[0]); + if(!text) + { + return; + } + const char* ptr = text; + while(*ptr) + { + // Any ptrs starting in a space are treated as preformatted text. + std::string preformatted; + while(*ptr == ' ') + { + for(char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) + { + preformatted.append(1, ch); + } + if(*ptr) + { + ++ptr; + preformatted.append(1, '\n'); + } + } + if(preformatted.length()) + { + this->PrintPreformatted(os, preformatted.c_str()); + } + + // Other ptrs are treated as paragraphs. + std::string paragraph; + for(char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) + { + paragraph.append(1, ch); + } + if(*ptr) + { + ++ptr; + paragraph.append(1, '\n'); + } + if(paragraph.length()) + { + this->PrintParagraph(os, paragraph.c_str()); + } + } } //---------------------------------------------------------------------------- -void cmDocumentation::PrintHelpHTML(std::ostream& os) +void cmDocumentation::PrintPreformatted(std::ostream& os, const char* text) { - os << "<html>\n" - << "<body>\n"; - os << "<h2>Using CMake</h2>\n"; - if(this->UsageHelp) + switch (this->CurrentForm) { - os << "<blockquote><code>\n"; - this->PrintHelpHTMLSection(os, this->UsageHelp, 0); - os << "</code></blockquote>\n"; + case TextForm: this->PrintPreformattedText(os, text); break; + case HTMLForm: this->PrintPreformattedHTML(os, text); break; + case ManForm: this->PrintPreformattedMan(os, text); break; + case UsageForm: this->PrintPreformattedText(os, text); break; } - this->PrintHelpHTMLSection(os, this->Description, 0); - this->PrintHelpHTMLSection(os, &this->Options[0], "Command-line Options"); - this->PrintHelpHTMLSection(os, &this->Commands[0], "Listfile Commands"); - //this->PrintHelpHTMLSection(os, cmDocumentationCopyright, "Copyright"); - //this->PrintHelpHTMLSection(os, cmDocumentationMailingList, "Mailing List"); - os << "</body>\n" - << "</html>\n"; } //---------------------------------------------------------------------------- -void cmDocumentation::PrintManPage(std::ostream& os) +void cmDocumentation::PrintParagraph(std::ostream& os, const char* text) { - os << ".TH CMake 1 \"" - << cmSystemTools::GetCurrentDateTime("%B %d, %Y").c_str() - << "\" \"CMake " CMake_VERSION_STRING "\"\n"; - this->PrintManSection(os, this->Name, "NAME"); - this->PrintManSection(os, this->UsageHelp, "SYNOPSIS"); - this->PrintManSection(os, this->Description, "DESCRIPTION"); - this->PrintManSection(os, &this->Options[0], "OPTIONS"); - this->PrintManSection(os, &this->Commands[0], "COMMANDS"); - this->PrintManSection(os, cmDocumentationCopyright, "COPYRIGHT"); - os << ".SH MAILING LIST\n"; - os << "For help and discussion about using cmake, a mailing list is\n" - << "provided at\n" - << ".B cmake@www.cmake.org.\n" - << "Please first read the full documentation at\n" - << ".B http://www.cmake.org\n" - << "before posting questions to the list.\n"; - os << ".SH AUTHOR\n" - << "This manual page was generated by \"cmake --help-man\".\n"; + switch (this->CurrentForm) + { + case TextForm: this->PrintParagraphText(os, text); break; + case HTMLForm: this->PrintParagraphHTML(os, text); break; + case ManForm: this->PrintParagraphMan(os, text); break; + case UsageForm: this->PrintParagraphText(os, text); break; + } } //---------------------------------------------------------------------------- -void cmDocumentation::PrintCopyright(std::ostream& os) +void cmDocumentation::PrintPreformattedText(std::ostream& os, const char* text) { - os << "CMake version " CMake_VERSION_STRING "\n"; - for(const cmDocumentationEntry* op = cmDocumentationCopyright; - op->brief; ++op) + bool newline = true; + for(const char* ptr = text; *ptr; ++ptr) { - if(op->name) + if(newline) { - os << " * "; - this->PrintColumn(os, 74, " ", op->brief); + os << this->TextIndent; + newline = false; } - else + os << *ptr; + if(*ptr == '\n') { - this->PrintColumn(os, 77, "", op->brief); + newline = true; } - os << "\n"; } + os << "\n"; } //---------------------------------------------------------------------------- -void cmDocumentation::PrintVersion(std::ostream& os) +void cmDocumentation::PrintParagraphText(std::ostream& os, const char* text) { - os << "CMake version " CMake_VERSION_STRING "\n"; + os << this->TextIndent; + this->PrintColumn(os, text); + os << "\n"; +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintPreformattedHTML(std::ostream& os, const char* text) +{ + os << "<pre>"; + this->PrintHTMLEscapes(os, text); + os << "</pre>\n "; } //---------------------------------------------------------------------------- -void cmDocumentation::PrintColumn(std::ostream& os, int width, - const char* indent, const char* text) +void cmDocumentation::PrintParagraphHTML(std::ostream& os, const char* text) { - // Print text arranged in a column of fixed witdh indented by the - // "indent" text. + os << "<p>"; + this->PrintHTMLEscapes(os, text); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintPreformattedMan(std::ostream& os, const char* text) +{ + os << text << "\n"; +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintParagraphMan(std::ostream& os, const char* text) +{ + os << text << "\n\n"; +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintColumn(std::ostream& os, const char* text) +{ + // Print text arranged in an indented column of fixed witdh. const char* l = text; int column = 0; bool newSentence = false; bool firstLine = true; - bool lastHadBlanks = false; - - // Count leading blanks in the text. - int blanks = 0; - for(const char* b = l; *b == ' '; ++b) { ++blanks; } + int width = this->TextWidth - strlen(this->TextIndent); // Loop until the end of the text. while(*l) @@ -404,38 +573,9 @@ void cmDocumentation::PrintColumn(std::ostream& os, int width, } else { - // If we are switching from a line that has leading blanks - // to a line that does not, or vice versa, add an extra - // newline. - if(blanks) - { - if(!lastHadBlanks && !firstLine) - { - os << "\n"; - } - lastHadBlanks = true; - } - else - { - if(lastHadBlanks && !firstLine) - { - os << "\n"; - } - lastHadBlanks = false; - } - // First word on line. Print indentation unless this is the // first line. - os << (firstLine?"":indent); - - // Further indent by leading blanks from the text on this - // line. - for(int i = 0; i < blanks; ++i) - { - os << " "; - ++column; - } - blanks = 0; + os << (firstLine?"":this->TextIndent); } // Print the word. @@ -450,9 +590,6 @@ void cmDocumentation::PrintColumn(std::ostream& os, int width, ++r; column = 0; firstLine = false; - - // Count leading blanks in the text. - for(const char* b = r; *b == ' '; ++b) { ++blanks; } } else { @@ -467,7 +604,7 @@ void cmDocumentation::PrintColumn(std::ostream& os, int width, firstLine = false; if(r > l) { - os << indent; + os << this->TextIndent; os.write(l, static_cast<long>(r-l)); column = static_cast<long>(r-l); newSentence = (*(r-1) == '.'); @@ -481,156 +618,170 @@ void cmDocumentation::PrintColumn(std::ostream& os, int width, } //---------------------------------------------------------------------------- -void cmDocumentation::PrintFull(std::ostream& os, const char* text, - void (*pPreform)(std::ostream&, const char*), - void (*pNormal)(std::ostream&, const char*)) +void cmDocumentation::PrintHTMLEscapes(std::ostream& os, const char* text) { - const char* line = text; - while(*line) + static cmDocumentationEntry escapes[] = + { + {"<", "<", 0}, + {">", ">", 0}, + {"&", "&", 0}, + {"\n", "<br>", 0}, + {0,0,0} + }; + for(const char* p = text; *p; ++p) { - // Any lines starting in a space are treated as preformatted text. - std::string preformatted; - while(*line == ' ') - { - for(char ch = *line; ch && ch != '\n'; ++line, ch = *line) - { - preformatted.append(1, ch); - } - if(*line) - { - ++line; - preformatted.append(1, '\n'); - } - } - if(preformatted.length()) + bool found = false; + for(const cmDocumentationEntry* op = escapes; !found && op->name; ++op) { - if(pPreform) - { - pPreform(os, preformatted.c_str()); - } - else + if(op->name[0] == *p) { - os << preformatted << "\n"; + os << op->brief; + found = true; } } - - // Other lines are treated as normal text. - std::string normal; - for(char ch = *line; ch && ch != '\n'; ++line, ch = *line) - { - normal.append(1, ch); - } - if(*line) - { - ++line; - normal.append(1, '\n'); - } - if(normal.length()) + if(!found) { - if(pNormal) - { - pNormal(os, normal.c_str()); - } - else - { - os << normal << "\n"; - } + os << *p; } } } //---------------------------------------------------------------------------- -void cmDocumentation::Print(Type ht, std::ostream& os) +void cmDocumentation::PrintDocumentationUsage(std::ostream& os) { - switch (ht) + this->CreateUsageDocumentation(); + this->Print(UsageForm, os); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintDocumentationFull(std::ostream& os) +{ + this->CreateFullDocumentation(); + this->Print(TextForm, os); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintDocumentationHTML(std::ostream& os) +{ + this->CreateFullDocumentation(); + os << "<html><body>\n"; + this->Print(HTMLForm, os); + os << "</body></html>\n"; +} + +//---------------------------------------------------------------------------- +void cmDocumentation::PrintDocumentationMan(std::ostream& os) +{ + this->CreateManDocumentation(); + os << ".TH CMake 1 \"" + << cmSystemTools::GetCurrentDateTime("%B %d, %Y").c_str() + << "\" \"CMake " CMake_VERSION_STRING "\"\n"; + this->Print(ManForm, os); +} + +//---------------------------------------------------------------------------- +void cmDocumentation::CreateUsageDocumentation() +{ + this->ClearSections(); + if(!this->NameSection.empty()) { - case cmDocumentation::Usage: this->PrintUsage(os); break; - case cmDocumentation::Help: this->PrintHelp(os); break; - case cmDocumentation::HelpHTML: this->PrintHelpHTML(os); break; - case cmDocumentation::Man: this->PrintManPage(os); break; - case cmDocumentation::Copyright: this->PrintCopyright(os); break; - case cmDocumentation::Version: this->PrintVersion(os); break; - default: break; + this->AddSection("Name", &this->NameSection[0]); + } + if(!this->UsageSection.empty()) + { + this->AddSection("Usage", &this->UsageSection[0]); + } + if(!this->OptionsSection.empty()) + { + this->AddSection("Command-Line Options", &this->OptionsSection[0]); } } //---------------------------------------------------------------------------- -cmDocumentation::Type cmDocumentation::CheckOptions(int argc, char** argv) +void cmDocumentation::CreateFullDocumentation() { - for(int i=1; i < argc; ++i) + this->ClearSections(); + if(!this->NameSection.empty()) { - if((strcmp(argv[i], "-help") == 0) || - (strcmp(argv[i], "--help") == 0) || - (strcmp(argv[i], "/?") == 0) || - (strcmp(argv[i], "-usage") == 0) || - (strcmp(argv[i], "-h") == 0) || - (strcmp(argv[i], "-H") == 0)) - { - return cmDocumentation::Usage; - } - if(strcmp(argv[i], "--help-full") == 0) - { - return cmDocumentation::Help; - } - if(strcmp(argv[i], "--help-html") == 0) - { - return cmDocumentation::HelpHTML; - } - if(strcmp(argv[i], "--help-man") == 0) - { - return cmDocumentation::Man; - } - if(strcmp(argv[i], "--copyright") == 0) - { - return cmDocumentation::Copyright; - } - if((strcmp(argv[i], "--version") == 0) || - (strcmp(argv[i], "-version") == 0) || - (strcmp(argv[i], "-V") == 0) || - (strcmp(argv[i], "/V") == 0)) - { - return cmDocumentation::Version; - } + this->AddSection("Name", &this->NameSection[0]); } - return cmDocumentation::None; + 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->CommandsSection.empty()) + { + this->AddSection("Listfile Commands", &this->CommandsSection[0]); + } + this->AddSection("Copyright", cmDocumentationCopyright); + this->AddSection("Mailing List", cmDocumentationMailingList); } //---------------------------------------------------------------------------- -void cmDocumentation::SetOptions(const cmDocumentationEntry* d) +void cmDocumentation::CreateManDocumentation() { - this->Options.erase(this->Options.begin(), this->Options.end()); - if(d) + this->ClearSections(); + if(!this->NameSection.empty()) { - for(const cmDocumentationEntry* op = d; op->brief; ++op) - { - this->Options.push_back(*op); - } + this->AddSection("NAME", &this->NameSection[0]); } - for(const cmDocumentationEntry* op = cmDocumentationStandardOptions; - op->brief; ++op) + if(!this->UsageSection.empty()) { - this->Options.push_back(*op); + this->AddSection("SYNOPSIS", &this->UsageSection[0]); } - cmDocumentationEntry empty = {0,0,0}; - this->Options.push_back(empty); + if(!this->DescriptionSection.empty()) + { + this->AddSection("DESCRIPTION", &this->DescriptionSection[0]); + } + if(!this->OptionsSection.empty()) + { + this->AddSection("OPTIONS", &this->OptionsSection[0]); + } + if(!this->CommandsSection.empty()) + { + this->AddSection("COMMANDS", &this->CommandsSection[0]); + } + this->AddSection("COPYRIGHT", cmDocumentationCopyright); + this->AddSection("MAILING LIST", cmDocumentationMailingList); + this->AddSection("AUTHOR", cmDocumentationAuthor); } //---------------------------------------------------------------------------- -void cmDocumentation::SetCommands(const cmDocumentationEntry* d) +void cmDocumentation::SetSection(const cmDocumentationEntry* header, + const cmDocumentationEntry* section, + const cmDocumentationEntry* footer, + std::vector<cmDocumentationEntry>& vec) { - this->Commands.erase(this->Commands.begin(), this->Commands.end()); - for(const cmDocumentationEntry* op = cmDocumentationCommandsHeader; - op->brief; ++op) + vec.erase(vec.begin(), vec.end()); + if(header) { - this->Commands.push_back(*op); + for(const cmDocumentationEntry* op = header; op->brief; ++op) + { + vec.push_back(*op); + } + } + if(section) + { + for(const cmDocumentationEntry* op = section; op->brief; ++op) + { + vec.push_back(*op); + } } - if(d) + if(footer) { - for(const cmDocumentationEntry* op = d; op->brief; ++op) + for(const cmDocumentationEntry* op = footer; op->brief; ++op) { - this->Commands.push_back(*op); + vec.push_back(*op); } } cmDocumentationEntry empty = {0,0,0}; - this->Commands.push_back(empty); + vec.push_back(empty); } diff --git a/Source/cmDocumentation.h b/Source/cmDocumentation.h index fc87ce0e53..5e507a0f4d 100644 --- a/Source/cmDocumentation.h +++ b/Source/cmDocumentation.h @@ -25,45 +25,111 @@ class cmDocumentation public: cmDocumentation(); - enum Type { None, Usage, Help, HelpHTML, Man, Copyright, Version }; + // High-level interface for standard documents: - void Print(Type ht, std::ostream& os); - void PrintUsage(std::ostream& os); - void PrintHelp(std::ostream& os); - void PrintHelpHTML(std::ostream& os); - void PrintManPage(std::ostream& os); - void PrintCopyright(std::ostream& os); - void PrintVersion(std::ostream& os); - - void SetCommands(const cmDocumentationEntry* d); - void SetDescription(const cmDocumentationEntry* d) {this->Description = d;} - void SetName(const cmDocumentationEntry* d) {this->Name = d;} - void SetOptions(const cmDocumentationEntry* d); - void SetUsage(const cmDocumentationEntry* d) {this->UsageHelp = d;} + /** Types of help provided. */ + enum Type { None, Usage, Full, HTML, Man, Copyright, Version }; + /** + * Check command line arguments for documentation options. Returns + * the type of help to be provided. If non-zero, the result should + * be passed to PrintDocumentation to produce the desired + * documentation. + */ Type CheckOptions(int argc, char** argv); + + /** Print help of the given type. */ + void PrintDocumentation(Type ht, std::ostream& os); + + /** Set the program name for standard document generation. */ + void SetNameSection(const cmDocumentationEntry*); + + /** Set the program usage for standard document generation. */ + void SetUsageSection(const cmDocumentationEntry*); + + /** Set the program description for standard document generation. */ + void SetDescriptionSection(const cmDocumentationEntry*); + + /** Set the program options for standard document generation. */ + void SetOptionsSection(const cmDocumentationEntry*); + + /** Set the listfile commands for standard document generation. */ + void SetCommandsSection(const cmDocumentationEntry*); + + // Low-level interface for custom documents: + + /** Forms of documentation output. */ + enum Form { TextForm, HTMLForm, ManForm, UsageForm }; + + /** + * Print documentation in the given form. All previously added + * sections will be generated. + */ + void Print(Form f, std::ostream& os); + + /** + * Add a section of documentation. The cmDocumentationEntry pointer + * should point at an array terminated by an all zero ({0,0,0}) + * entry. This can be used to generate custom help documents. + */ + void AddSection(const char* name, const cmDocumentationEntry* d); + + /** Clear all previously added sections of help. */ + void ClearSections(); private: - void PrintColumn(std::ostream& os, int width, - const char* indent, const char* text); - void PrintManSection(std::ostream& os, const cmDocumentationEntry* section, + void PrintSection(std::ostream& os, + const cmDocumentationEntry* section, + const char* name); + void PrintSectionText(std::ostream& os, + const cmDocumentationEntry* section, + const char* name); + void PrintSectionHTML(std::ostream& os, + const cmDocumentationEntry* section, + const char* name); + void PrintSectionMan(std::ostream& os, const cmDocumentationEntry* section, const char* name); - void PrintHelpSection(std::ostream& os, const cmDocumentationEntry* section); - static void PrintHTMLEscapes(std::ostream& os, const char* text); - static void PrintHTMLPreformatted(std::ostream& os, const char* text); - void PrintFull(std::ostream& os, const char* text, - void (*pPreform)(std::ostream&, const char*), - void (*pNormal)(std::ostream&, const char*)); - void PrintHelpHTMLSection(std::ostream& os, - const cmDocumentationEntry* section, - const char* header); - void PrintUsageSection(std::ostream& os, - const cmDocumentationEntry* section); + void PrintSectionUsage(std::ostream& os, + const cmDocumentationEntry* section, + const char* name); + void PrintFormatted(std::ostream& os, const char* text); + void PrintPreformatted(std::ostream& os, const char* text); + void PrintPreformattedText(std::ostream& os, const char* text); + void PrintPreformattedHTML(std::ostream& os, const char* text); + void PrintPreformattedMan(std::ostream& os, const char* text); + void PrintParagraph(std::ostream& os, const char* text); + void PrintParagraphText(std::ostream& os, const char* text); + void PrintParagraphHTML(std::ostream& os, const char* text); + void PrintParagraphMan(std::ostream& os, const char* text); + void PrintColumn(std::ostream& os, const char* text); + void PrintHTMLEscapes(std::ostream& os, const char* text); + + void PrintCopyright(std::ostream& os); + void PrintVersion(std::ostream& os); + void PrintDocumentationUsage(std::ostream& os); + void PrintDocumentationFull(std::ostream& os); + void PrintDocumentationHTML(std::ostream& os); + void PrintDocumentationMan(std::ostream& os); + + void CreateUsageDocumentation(); + void CreateFullDocumentation(); + void CreateManDocumentation(); + + void SetSection(const cmDocumentationEntry* header, + const cmDocumentationEntry* section, + const cmDocumentationEntry* footer, + std::vector<cmDocumentationEntry>&); + + std::vector<cmDocumentationEntry> NameSection; + std::vector<cmDocumentationEntry> UsageSection; + std::vector<cmDocumentationEntry> DescriptionSection; + std::vector<cmDocumentationEntry> OptionsSection; + std::vector<cmDocumentationEntry> CommandsSection; - std::vector<cmDocumentationEntry> Commands; - const cmDocumentationEntry* Description; - const cmDocumentationEntry* Name; - std::vector<cmDocumentationEntry> Options; - const cmDocumentationEntry* UsageHelp; + std::vector< const char* > Names; + std::vector< const cmDocumentationEntry* > Sections; + Form CurrentForm; + const char* TextIndent; + int TextWidth; }; #endif diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index b86dc07083..6a0dc1fb31 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -24,8 +24,8 @@ //---------------------------------------------------------------------------- static const cmDocumentationEntry cmDocumentationName[] = { - {"cmake", - "- Cross-Platform Makefile Generator.", 0}, + {0, + " cmake - Cross-Platform Makefile Generator.", 0}, {0,0,0} }; @@ -33,7 +33,7 @@ static const cmDocumentationEntry cmDocumentationName[] = static const cmDocumentationEntry cmDocumentationUsage[] = { {0, - "cmake [options] <path-to-source>", 0}, + " cmake [options] <path-to-source>", 0}, {0,0,0} }; @@ -74,12 +74,12 @@ int do_cmake(int ac, char** av) cmake hcm; std::vector<cmDocumentationEntry> commands; hcm.GetCommandDocumentation(commands); - doc.SetName(cmDocumentationName); - doc.SetUsage(cmDocumentationUsage); - doc.SetDescription(cmDocumentationDescription); - doc.SetOptions(cmDocumentationOptions); - doc.SetCommands(&commands[0]); - doc.Print(ht, std::cout); + doc.SetNameSection(cmDocumentationName); + doc.SetUsageSection(cmDocumentationUsage); + doc.SetDescriptionSection(cmDocumentationDescription); + doc.SetOptionsSection(cmDocumentationOptions); + doc.SetCommandsSection(&commands[0]); + doc.PrintDocumentation(ht, std::cout); return 0; } |