cmDocumentationFormatter.cxx 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmDocumentationFormatter.h"
  11. #include "cmDocumentationEntry.h"
  12. #include "cmDocumentationSection.h"
  13. #include <ostream>
  14. #include <string.h>
  15. #include <string>
  16. #include <vector>
  17. cmDocumentationFormatter::cmDocumentationFormatter()
  18. : TextWidth(77)
  19. , TextIndent("")
  20. {
  21. }
  22. cmDocumentationFormatter::~cmDocumentationFormatter()
  23. {
  24. }
  25. void cmDocumentationFormatter::PrintFormatted(std::ostream& os,
  26. const char* text)
  27. {
  28. if (!text) {
  29. return;
  30. }
  31. const char* ptr = text;
  32. while (*ptr) {
  33. // Any ptrs starting in a space are treated as preformatted text.
  34. std::string preformatted;
  35. while (*ptr == ' ') {
  36. for (char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) {
  37. preformatted.append(1, ch);
  38. }
  39. if (*ptr) {
  40. ++ptr;
  41. preformatted.append(1, '\n');
  42. }
  43. }
  44. if (!preformatted.empty()) {
  45. this->PrintPreformatted(os, preformatted.c_str());
  46. }
  47. // Other ptrs are treated as paragraphs.
  48. std::string paragraph;
  49. for (char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) {
  50. paragraph.append(1, ch);
  51. }
  52. if (*ptr) {
  53. ++ptr;
  54. paragraph.append(1, '\n');
  55. }
  56. if (!paragraph.empty()) {
  57. this->PrintParagraph(os, paragraph.c_str());
  58. }
  59. }
  60. }
  61. void cmDocumentationFormatter::PrintPreformatted(std::ostream& os,
  62. const char* text)
  63. {
  64. bool newline = true;
  65. for (const char* ptr = text; *ptr; ++ptr) {
  66. if (newline && *ptr != '\n') {
  67. os << this->TextIndent;
  68. newline = false;
  69. }
  70. os << *ptr;
  71. if (*ptr == '\n') {
  72. newline = true;
  73. }
  74. }
  75. os << "\n";
  76. }
  77. void cmDocumentationFormatter::PrintParagraph(std::ostream& os,
  78. const char* text)
  79. {
  80. os << this->TextIndent;
  81. this->PrintColumn(os, text);
  82. os << "\n";
  83. }
  84. void cmDocumentationFormatter::SetIndent(const char* indent)
  85. {
  86. this->TextIndent = indent;
  87. }
  88. void cmDocumentationFormatter::PrintColumn(std::ostream& os, const char* text)
  89. {
  90. // Print text arranged in an indented column of fixed witdh.
  91. const char* l = text;
  92. long column = 0;
  93. bool newSentence = false;
  94. bool firstLine = true;
  95. int width = this->TextWidth - static_cast<int>(strlen(this->TextIndent));
  96. // Loop until the end of the text.
  97. while (*l) {
  98. // Parse the next word.
  99. const char* r = l;
  100. while (*r && (*r != '\n') && (*r != ' ')) {
  101. ++r;
  102. }
  103. // Does it fit on this line?
  104. if (r - l < (width - column - (newSentence ? 1 : 0))) {
  105. // Word fits on this line.
  106. if (r > l) {
  107. if (column) {
  108. // Not first word on line. Separate from the previous word
  109. // by a space, or two if this is a new sentence.
  110. if (newSentence) {
  111. os << " ";
  112. column += 2;
  113. } else {
  114. os << " ";
  115. column += 1;
  116. }
  117. } else {
  118. // First word on line. Print indentation unless this is the
  119. // first line.
  120. os << (firstLine ? "" : this->TextIndent);
  121. }
  122. // Print the word.
  123. os.write(l, static_cast<long>(r - l));
  124. newSentence = (*(r - 1) == '.');
  125. }
  126. if (*r == '\n') {
  127. // Text provided a newline. Start a new line.
  128. os << "\n";
  129. ++r;
  130. column = 0;
  131. firstLine = false;
  132. } else {
  133. // No provided newline. Continue this line.
  134. column += static_cast<long>(r - l);
  135. }
  136. } else {
  137. // Word does not fit on this line. Start a new line.
  138. os << "\n";
  139. firstLine = false;
  140. if (r > l) {
  141. os << this->TextIndent;
  142. os.write(l, static_cast<long>(r - l));
  143. column = static_cast<long>(r - l);
  144. newSentence = (*(r - 1) == '.');
  145. } else {
  146. column = 0;
  147. }
  148. }
  149. // Move to beginning of next word. Skip over whitespace.
  150. l = r;
  151. while (*l && (*l == ' ')) {
  152. ++l;
  153. }
  154. }
  155. }
  156. void cmDocumentationFormatter::PrintSection(
  157. std::ostream& os, cmDocumentationSection const& section)
  158. {
  159. os << section.GetName() << "\n";
  160. const std::vector<cmDocumentationEntry>& entries = section.GetEntries();
  161. for (std::vector<cmDocumentationEntry>::const_iterator op = entries.begin();
  162. op != entries.end(); ++op) {
  163. if (!op->Name.empty()) {
  164. os << " " << op->Name;
  165. this->TextIndent = " ";
  166. int align = static_cast<int>(strlen(this->TextIndent)) - 4;
  167. for (int i = static_cast<int>(op->Name.size()); i < align; ++i) {
  168. os << " ";
  169. }
  170. if (op->Name.size() > strlen(this->TextIndent) - 4) {
  171. os << "\n";
  172. os.write(this->TextIndent, strlen(this->TextIndent) - 2);
  173. }
  174. os << "= ";
  175. this->PrintColumn(os, op->Brief.c_str());
  176. os << "\n";
  177. } else {
  178. os << "\n";
  179. this->TextIndent = "";
  180. this->PrintFormatted(os, op->Brief.c_str());
  181. }
  182. }
  183. os << "\n";
  184. }