NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
docgen.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2020 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19#include "docgen.hpp"
20#include "../../../common/datastructures.h"
21#include "../../kernel.hpp"
22#include "../utils/tools.hpp"
23#include "../procedure/dependency.hpp"
24#include "../ui/winlayout.hpp"
25
26
39void DocumentationGenerator::followBranch(const std::string& sFile, std::set<std::string>& fileSet, std::vector<std::string>& vFiles) const
40{
41 // Add the current file to the set
42 fileSet.insert(sFile);
43 vFiles.push_back(sFile);
44
45 // Is the current file a window layout?
46 if (sFile.find(".nlyt") != std::string::npos)
47 {
48 // Get all event procedures
49 std::vector<std::string> vEventProcs = getEventProcedures(sFile);
50
51 // Get the dependencies for each event procedure
52 for (size_t i = 0; i < vEventProcs.size(); i++)
53 {
54 if (fileSet.find(vEventProcs[i]) == fileSet.end())
55 followBranch(vEventProcs[i], fileSet, vFiles);
56 }
57
58 // Return. Nothing more to be done
59 return;
60 }
61 else if (sFile.find(".nprc") == std::string::npos)
62 return;
63
64 // Get a reference to the procedure library
65 // and calculate the dependencies of the current file
68
69 // If the returned dependencies are not already part of
70 // the set, call this function recursively using the dependencies,
71 // which are not part of the set yet
72 for (auto iter = dep->getDependencyMap().begin(); iter != dep->getDependencyMap().end(); ++iter)
73 {
74 for (auto listiter = iter->second.begin(); listiter != iter->second.end(); ++listiter)
75 {
76 if (fileSet.find(listiter->getFileName()) == fileSet.end())
77 followBranch(listiter->getFileName(), fileSet, vFiles);
78 }
79 }
80}
81
82
95std::string DocumentationGenerator::convertToLaTeX(const std::string& sFileName) const
96{
97 std::string sFileContents;
98 std::string sLaTeXFileName = createLaTeXFileName(sFileName) + ".tex";
99 std::string sMainProc = createMainProcedure(sFileName);
100 std::ofstream file_out;
101
102 bool bTextMode = true;
103 int startpos = 0;
104
105 sFileContents += "% Created by NumeRe from the source of " + sFileName + "\n\n";
106
107 StyledTextFile file(sFileName);
108
109 // Go through the whole file and convert the
110 // syntax elements correspondingly
111 for (int i = 0; i < file.getLastPosition(); i++)
112 {
113 // Determine the type of documentation,
114 // into which the current and the following
115 // characters shall be converted
116 if (file.getStyleAt(i) == StyledTextFile::COMMENT_DOC_LINE) // That's a documentation
117 {
118 if (!bTextMode)
119 {
120 if (i - startpos > 1)
121 sFileContents += getStrippedRange(file, startpos, i) + "\n";
122
123 bTextMode = true;
124 sFileContents += "\\end{lstlisting}\n";
125 }
126
127 int j = i;
128
129 // Find all combined documentation comment lines
131 j = file.PositionFromLine(file.LineFromPosition(j) + 1);
132
133 sFileContents += parseDocumentation(file, sMainProc, i + 3, file.getLineEndPosition(file.LineFromPosition(j) - 1)) + "\n";
134 i = j-1;
135 startpos = j-1;
136 }
137 else if (file.getStyleAt(i) == StyledTextFile::COMMENT_LINE && file.getTextRange(i, i + 3) == "##~") // ignore that (escaped comment)
138 {
139 if (i - startpos > 1)
140 sFileContents += getStrippedRange(file, startpos, i) + "\n";
141
142 i = file.getLineEndPosition(file.LineFromPosition(i)) + 1;
143 startpos = i;
144 }
145 else if (file.getStyleAt(i) == StyledTextFile::COMMENT_DOC_BLOCK) // that's also a documentation
146 {
147 if (!bTextMode)
148 {
149 if (i - startpos > 1)
150 sFileContents += getStrippedRange(file, startpos, i) + "\n";
151
152 bTextMode = true;
153 sFileContents += "\\end{lstlisting}\n";
154 }
155
156 for (int j = i + 3; j < file.getLastPosition(); j++)
157 {
158 if (file.getStyleAt(j+3) != StyledTextFile::COMMENT_DOC_BLOCK || j + 1 == file.getLastPosition())
159 {
160 sFileContents += parseDocumentation(file, sMainProc, i + 3, j) + "\n";
161 i = j + 2;
162 break;
163 }
164 }
165
166 startpos = i;
167 }
168 else if (file.getStyleAt(i) == StyledTextFile::COMMENT_BLOCK && file.getTextRange(i, i + 3) == "#**") // ignore that, that's also an escaped comment
169 {
170 if (i - startpos > 1)
171 sFileContents += getStrippedRange(file, startpos, i) + "\n";
172
173 for (int j = i + 3; j < file.getLastPosition(); j++)
174 {
175 if (file.getStyleAt(j+3) != StyledTextFile::COMMENT_BLOCK || j + 1 == file.getLastPosition())
176 {
177 i = j + 2;
178 break;
179 }
180 }
181
182 startpos = i + 1;
183 }
184 else // a normal code fragment
185 {
186 if (bTextMode)
187 {
188 startpos = i;
189 bTextMode = false;
190 sFileContents += "\\begin{lstlisting}\n";
191 }
192
193 if (i + 1 == file.getLastPosition())
194 {
195 if (i - startpos > 1)
196 {
197 sFileContents += getStrippedRange(file, startpos, i) + "\n";
198 }
199 }
200 }
201 }
202
203 // Append a trailing \end{lstlisting}, if needed
204 if (!bTextMode)
205 sFileContents += "\\end{lstlisting}\n";
206
207 if (!sFileContents.length())
208 return "";
209
210 // Write the converted documentation to the
211 // target LaTeX file
212 file_out.open(sLaTeXFileName.c_str());
213
214 if (!file_out.good())
215 return "";
216
217 file_out << sFileContents;
218 file_out.close();
219
220 return sLaTeXFileName;
221}
222
223
242std::string DocumentationGenerator::getStrippedRange(const StyledTextFile& file, int pos1, int pos2, bool encode) const
243{
244 std::string sTextRange = file.getTextRange(pos1, pos2);
245
246 // Remove leading whitespaces
247 while (sTextRange.front() == ' ' || sTextRange.front() == '\r' || sTextRange.front() == '\n' )
248 sTextRange.erase(0, 1);
249
250 // Remove trailing whitespaces
251 while (sTextRange.back() == ' ' || sTextRange.back() == '\t' || sTextRange.back() == '\r' || sTextRange.back() == '\n')
252 sTextRange.erase(sTextRange.length() - 1);
253
254 // Convert CR LF into LF only
255 while (sTextRange.find("\r\n") != std::string::npos)
256 sTextRange.replace(sTextRange.find("\r\n"), 2, "\n");
257
258 // Remove documentation comment sequences
259 size_t nCommentSeq;
260
261 while ((nCommentSeq = sTextRange.find("\n##!")) != std::string::npos)
262 sTextRange.erase(nCommentSeq+1, 3);
263 //sTextRange.erase(nCommentSeq+1, sTextRange.find_first_not_of(" \t", nCommentSeq+4) - nCommentSeq-1);
264
265 // Convert umlauts, if the encode flag
266 // has been set
267 if (encode)
268 {
269 for (size_t i = 0; i < sTextRange.length(); i++)
270 {
271 switch (sTextRange[i])
272 {
273 case 'Ä':
274 sTextRange.replace(i, 1, "Ae");
275 break;
276 case 'ä':
277 sTextRange.replace(i, 1, "ae");
278 break;
279 case 'Ö':
280 sTextRange.replace(i, 1, "Oe");
281 break;
282 case 'ö':
283 sTextRange.replace(i, 1, "oe");
284 break;
285 case 'Ü':
286 sTextRange.replace(i, 1, "Ue");
287 break;
288 case 'ü':
289 sTextRange.replace(i, 1, "ue");
290 break;
291 case 'ß':
292 sTextRange.replace(i, 1, "ss");
293 break;
294 }
295 }
296 }
297
298 if (sTextRange.find_first_not_of('\t') == std::string::npos)
299 return "";
300
301 return sTextRange;
302}
303
304
322std::string DocumentationGenerator::parseDocumentation(const StyledTextFile& file, const std::string& sMainProc, int pos1, int pos2) const
323{
324 // Get the text range
325 std::string sTextRange = getStrippedRange(file, pos1, pos2, false);
326
327 // Handle procedure names
328 if (sTextRange.find("\\procedure ") != std::string::npos)
329 {
330 // Find start and end of procedure name
331 size_t nPosStart = sTextRange.find("\\procedure ")+10;
332 nPosStart = sTextRange.find_first_not_of(' ', nPosStart);
333 size_t nPosEnd = sTextRange.find_first_not_of(" \r\n", nPosStart);
334 nPosEnd = sTextRange.find_first_of(" \r\n", nPosEnd);
335
336 std::string sProcedure = sTextRange.substr(nPosStart, nPosEnd-nPosStart);
337 std::string sMain;
338 std::string sDependencies;
339
340 if (sMainProc.length())
341 {
342 if (sMainProc != sProcedure)
343 {
344 if (sMainProc.find('~') != std::string::npos && sMainProc.substr(sMainProc.rfind('~')+1) == sProcedure)
345 sProcedure = sMainProc;
346 else
347 {
348 sProcedure.insert(0, "thisfile~");
349 sMain = sMainProc;
350
351 if (sMain.find('~') != std::string::npos)
352 sMain.erase(0, sMain.rfind('~')+1);
353
354 replaceAll(sMain, "_", "\\_");
355 sMain.insert(0, "(): local member of \\$");
356 }
357 }
358
360 std::map<std::string, DependencyList>& mDependencies = _procLib.getProcedureContents(file.getFileName())->getDependencies()->getDependencyMap();
361 std::map<std::string, DependencyList>::iterator iter;
362
363 if (sProcedure.find("thisfile~") != std::string::npos)
364 iter = mDependencies.find("$" + sMainProc + "::" + sProcedure);
365 else
366 iter = mDependencies.find("$" + sProcedure);
367
368 if (iter != mDependencies.end())
369 {
370 DependencyList _depList = iter->second;
371
372 for (auto listiter = _depList.begin(); listiter != _depList.end(); ++listiter)
373 {
374 if (sDependencies.length())
375 sDependencies += ", ";
376
377 if (listiter->getProcedureName().find("::thisfile~") != std::string::npos)
378 sDependencies += "!!$" + listiter->getProcedureName().substr(listiter->getProcedureName().find("::")+2) + "()!!";
379 else
380 sDependencies += "!!" + listiter->getProcedureName() + "()!!";
381 }
382
383 if (sDependencies.length())
384 sDependencies = "\n\\depends{" + sDependencies + "}";
385 }
386
387 }
388
389 // Insert procedure call with namespace
390 // and braces around the procedure name
391 sTextRange.insert(nPosEnd, sMain + "}{$" + sProcedure + "()}" + sDependencies);
392 sTextRange[nPosStart-1] = '{';
393 }
394
395 // Handle layout names
396 if (sTextRange.find("\\layout ") != std::string::npos)
397 {
398 // Find start and end of layout name
399 size_t nPosStart = sTextRange.find("\\layout ")+7;
400 nPosStart = sTextRange.find_first_not_of(' ', nPosStart);
401 size_t nPosEnd = sTextRange.find_first_not_of(" \r\n", nPosStart);
402 nPosEnd = sTextRange.find_first_of(" \r\n", nPosEnd);
403
404 std::string sLayout = sTextRange.substr(nPosStart, nPosEnd-nPosStart);
405 replaceAll(sLayout, "_", "\\_");
406
407 // Insert braces around the layout name
408 sTextRange.replace(nPosStart-1, nPosEnd-nPosStart+1, "{" + sLayout + "}");
409 }
410
411 // Handle unordered lists
412 if (sTextRange.find("- ") != std::string::npos) // thats a unordered list
413 {
414 size_t nItemizeStart = 0;
415 size_t nLength = 0;
416
417 while ((nItemizeStart = findListItem(sTextRange, nLength)) != std::string::npos)
418 {
419 std::string sItemStart = "\n" + std::string(nLength-3, ' ') + "- ";
420 std::string sIndent = "\n" + std::string(nLength-1, ' ');
421
422 for (size_t i = nItemizeStart; i < sTextRange.length(); i++)
423 {
424 if (sTextRange.substr(i, nLength) == sItemStart)
425 {
426 sTextRange.replace(i + 1, nLength-2, "\t\\item");
427 continue;
428 }
429
430 if ((sTextRange[i] == '\n' && sTextRange.substr(i, nLength) != sIndent) || i + 1 == sTextRange.length())
431 {
432 if (sTextRange[i] == '\n')
433 sTextRange.insert(i+1, "\\end{itemize}");
434 else
435 sTextRange += "\n\\end{itemize}";
436
437 sTextRange.insert(nItemizeStart + 1, "\\begin{itemize}\n");
438 break;
439 }
440 }
441 }
442 }
443
444 // Handle parameter lists
445 if (sTextRange.find("\\param ") != std::string::npos)
446 {
447 while (sTextRange.find("\\param ") != std::string::npos)
448 {
449 size_t nItemizeStart = sTextRange.find("\\param ");
450 size_t nLastParam = nItemizeStart;
451 std::vector<std::string> vParameters;
452
453 for (size_t i = nItemizeStart+1; i < sTextRange.length(); i++)
454 {
455 if (sTextRange.substr(i, 7) == "\\param ")
456 {
457 vParameters.push_back(sTextRange.substr(nLastParam, i - nLastParam));
458 nLastParam = i;
459 continue;
460 }
461
462 if (i + 1 == sTextRange.length()
463 || (sTextRange[i] == '\n' && sTextRange[i+1] == '\n')
464 || (sTextRange[i+1] == '\\' && sTextRange.substr(i+1, 7) != "\\param "))
465 {
466 vParameters.push_back(sTextRange.substr(nLastParam, i - nLastParam+1));
467 sTextRange.replace(nItemizeStart, i+1 - nItemizeStart, "\\parameters\n\\noindent\n" + createParametersTable(vParameters));
468
469 break;
470 }
471 }
472 }
473 }
474
475 // Handle return value lists
476 if (sTextRange.find("\\return ") != std::string::npos)
477 {
478 while (sTextRange.find("\\return ") != std::string::npos)
479 {
480 size_t nItemizeStart = sTextRange.find("\\return ");
481 size_t nLastParam = nItemizeStart;
482 std::vector<std::string> vReturns;
483
484 for (size_t i = nItemizeStart+1; i < sTextRange.length(); i++)
485 {
486 if (sTextRange.substr(i, 8) == "\\return ")
487 {
488 vReturns.push_back(sTextRange.substr(nLastParam, i - nLastParam));
489 nLastParam = i;
490 continue;
491 }
492
493 if (i + 1 == sTextRange.length()
494 || (sTextRange[i] == '\n' && sTextRange[i+1] == '\n')
495 || (sTextRange[i+1] == '\\' && sTextRange.substr(i+1, 8) != "\\return "))
496 {
497 vReturns.push_back(sTextRange.substr(nLastParam, i - nLastParam+1));
498 sTextRange.replace(nItemizeStart, i+1 - nItemizeStart, "\\returns\n\\noindent\n" + createReturnsTable(vReturns));
499
500 break;
501 }
502 }
503 }
504 }
505
506 // Convert umlauts in LaTeX command sequences
507 for (size_t i = 0; i < sTextRange.length(); i++)
508 {
509 switch (sTextRange[i])
510 {
511 case 'Ä':
512 sTextRange.replace(i, 1, "\\\"A");
513 break;
514 case 'ä':
515 sTextRange.replace(i, 1, "\\\"a");
516 break;
517 case 'Ö':
518 sTextRange.replace(i, 1, "\\\"O");
519 break;
520 case 'ö':
521 sTextRange.replace(i, 1, "\\\"o");
522 break;
523 case 'Ü':
524 sTextRange.replace(i, 1, "\\\"U");
525 break;
526 case 'ü':
527 sTextRange.replace(i, 1, "\\\"u");
528 break;
529 case 'ß':
530 sTextRange.replace(i, 1, "\\ss ");
531 break;
532 }
533 }
534
535 // Handle inline code sequences
536 for (size_t i = 0; i < sTextRange.length(); i++)
537 {
538 if (sTextRange.substr(i, 2) == "!!")
539 {
540 for (size_t j = i + 2; j < sTextRange.length(); j++)
541 {
542 if (sTextRange.substr(j, 2) == "!!")
543 {
544 sTextRange.replace(j, 2, "`");
545 sTextRange.replace(i, 2, "\\lstinline`");
546 break;
547 }
548 }
549 }
550 }
551
552 return sTextRange;
553}
554
555
565std::string DocumentationGenerator::createParametersTable(const std::vector<std::string>& vParams) const
566{
567 // Table heads
568 std::string sTable = "\\begin{tabular}{p{0.22\\textwidth}p{0.15\\textwidth}p{0.55\\textwidth}}\n\t\\toprule\n\tParameter & Defaults to & Description\\\\\n\t\\midrule\n";
569 std::string sParameter;
570
571 size_t nDescPos;
572
573 // Write every single parameter line
574 for (size_t i = 0; i < vParams.size(); i++)
575 {
576 sParameter = vParams[i];
577 replaceAll(sParameter, "\n", " ");
578
579 size_t nDefaultPos = sParameter.find("(!!", 8);
580
581 if (nDefaultPos != std::string::npos)
582 nDescPos = sParameter.find_first_not_of(' ', sParameter.find("!!)")+3);
583 else
584 nDescPos = sParameter.find_first_not_of(' ', sParameter.find(' ', 8));
585
586 sTable += "\t!!" + sParameter.substr(7, sParameter.find(' ', 8) - 7) + "!! & ";
587
588 if (nDefaultPos != std::string::npos)
589 {
590 // Exclude the initial equal sign, if possibl
591 if (sParameter[nDefaultPos+3] == '=')
592 sTable += "!!" + sParameter.substr(nDefaultPos+4, sParameter.find("!!)")-nDefaultPos -2) + " & ";
593 else
594 sTable += sParameter.substr(nDefaultPos+1, sParameter.find("!!)")+1-nDefaultPos) + " & ";
595 }
596 else
597 sTable += "& ";
598
599 sTable += sParameter.substr(nDescPos) + "\\\\\n";
600 }
601
602 // Append the table foot and return
603 return sTable + "\t\\bottomrule\n\\end{tabular}\n";
604}
605
606
616std::string DocumentationGenerator::createReturnsTable(const std::vector<std::string>& vReturns) const
617{
618 // Table heads
619 std::string sTable = "\\begin{tabular}{p{0.22\\textwidth}p{0.725\\textwidth}}\n\t\\toprule\n\tReturn type & Description\\\\\n\t\\midrule\n";
620 std::string sReturnValue;
621
622 size_t nDescPos;
623
624 // Write every single parameter line
625 for (size_t i = 0; i < vReturns.size(); i++)
626 {
627 sReturnValue = vReturns[i];
628 replaceAll(sReturnValue, "\n", " ");
629
630 nDescPos = sReturnValue.find_first_not_of(' ', sReturnValue.find(' ', 9));
631
632 sTable += "\t!!" + sReturnValue.substr(8, sReturnValue.find(' ', 9) - 8) + "!! & ";
633 sTable += sReturnValue.substr(nDescPos) + "\\\\\n";
634 }
635
636 // Append the table foot and return
637 return sTable + "\t\\bottomrule\n\\end{tabular}\n";
638}
639
640
651size_t DocumentationGenerator::findListItem(const std::string& sTextRange, size_t& nLength) const
652{
653 size_t nItemCandidate = sTextRange.find("- ");
654
655 if (nItemCandidate == std::string::npos)
656 return nItemCandidate;
657
658 size_t nItemStart = sTextRange.find_last_not_of("- ", nItemCandidate);
659
660 if (nItemStart == std::string::npos || sTextRange[nItemStart] != '\n')
661 return std::string::npos;
662
663 nLength = nItemCandidate - nItemStart + 2;
664
665 return nItemStart;
666}
667
668
678std::string DocumentationGenerator::createMainProcedure(std::string sFileName) const
679{
680 std::vector<std::string> vPaths = NumeReKernel::getInstance()->getPathSettings();
681
682 if (sFileName.find(".nprc") == std::string::npos)
683 return "";
684
685 sFileName.erase(sFileName.rfind('.'));
686
687 // Try to detect the corresponding namespace
688 if (sFileName.substr(0, vPaths[PROCPATH].length()) == vPaths[PROCPATH])
689 {
690 sFileName.erase(0, vPaths[PROCPATH].length());
691
692 if (sFileName.front() == '/')
693 sFileName.erase(0, 1);
694
695 replaceAll(sFileName, "/", "~");
696 }
697 else
698 {
699 sFileName.erase(0, sFileName.rfind('/')+1);
700 sFileName.insert(0, "this~");
701 }
702
703 return sFileName;
704}
705
706
718std::string DocumentationGenerator::createLaTeXFileName(std::string sFileName) const
719{
720 std::vector<std::string> vPaths = NumeReKernel::getInstance()->getPathSettings();
721
722 if (sFileName.substr(0, vPaths[PROCPATH].length()) == vPaths[PROCPATH])
723 {
724 // This is one of the default folders
725 sFileName.erase(0, vPaths[PROCPATH].length());
726 sFileName = getPath() + "/procedures" + sFileName;
727 }
728 else if (sFileName.substr(0, vPaths[SCRIPTPATH].length()) == vPaths[SCRIPTPATH])
729 {
730 // This is one of the default folders
731 sFileName.erase(0, vPaths[SCRIPTPATH].length());
732 sFileName = getPath() + "/scripts" + sFileName;
733 }
734 else if (sFileName.substr(0, vPaths[EXEPATH].length()) == vPaths[EXEPATH])
735 {
736 // This is one of the default folders
737 sFileName.erase(0, vPaths[EXEPATH].length());
738 sFileName = getPath() + sFileName;
739 }
740 else
741 {
742 // This is not in one of the default folders
743 sFileName.erase(0, sFileName.rfind('/'));
744 sFileName = getPath() + "/externals" + sFileName;
745 }
746
747 createFolders(sFileName.substr(0, sFileName.rfind('/')));
748 sFileName[sFileName.rfind('.')] = '_';
749
750 return sFileName;
751}
752
753
764std::string DocumentationGenerator::prepareFileNameForLaTeX(std::string sFileName) const
765{
766 std::vector<std::string> vPaths = NumeReKernel::getInstance()->getPathSettings();
767
768 // Remove standard path parts
769 for (size_t i = LOADPATH; i < PATH_LAST; i++)
770 {
771 if (sFileName.substr(0, vPaths[i].length()) == vPaths[i])
772 {
773 sFileName.erase(0, vPaths[i].length());
774
775 if (sFileName.front() == '/')
776 sFileName.erase(0, 1);
777
778 break;
779 }
780 }
781
782 // Mask underscores
783 for (size_t i = 0; i < sFileName.length(); i++)
784 {
785 if (sFileName[i] == '_' && (!i || sFileName[i-1] != '\\'))
786 {
787 sFileName.insert(i, 1, '\\');
788 i++;
789 }
790 }
791
792 return sFileName;
793}
794
795
805std::string DocumentationGenerator::constructKeyWords(std::string sKeyWordList) const
806{
807 for (size_t i = 0; i < sKeyWordList.length(); i++)
808 {
809 if (sKeyWordList[i] == ' ')
810 sKeyWordList[i] = ',';
811 }
812
813 if (sKeyWordList.back() == ',')
814 sKeyWordList.erase(sKeyWordList.length()-1);
815
816 return sKeyWordList;
817}
818
819
832{
833 std::ifstream fHeaderTemplate;
834
835 // Open the header template
836 fHeaderTemplate.open((NumeReKernel::getInstance()->getSettings().getExePath() + "/lang/tmpl_header.tex").c_str());
837
838 // Ensure that the file exists
839 if (!fHeaderTemplate.good())
840 return;
841
842 std::string sLine;
843 std::string sTemplate;
844
845 // Read all contents of the template into a
846 // single string separated with line break
847 // characters
848 while (!fHeaderTemplate.eof())
849 {
850 std::getline(fHeaderTemplate, sLine);
851 sTemplate += sLine + "\n";
852 }
853
854 // Replace the syntax list placeholders with
855 // the current set of syntax elements
856 size_t pos;
857
858 if ((pos = sTemplate.find("NSCRCOMMANDS")) != std::string::npos)
859 sTemplate.replace(pos, 12, constructKeyWords(m_syntax->getCommands() + m_syntax->getNPRCCommands()));
860
861 if ((pos = sTemplate.find("NSCRFUNCTIONS")) != std::string::npos)
862 sTemplate.replace(pos, 13, constructKeyWords(m_syntax->getFunctions()));
863
864 if ((pos = sTemplate.find("NSCRCONSTANTS")) != std::string::npos)
865 sTemplate.replace(pos, 13, constructKeyWords(m_syntax->getConstants()));
866
867 if ((pos = sTemplate.find("NSCROPTIONS")) != std::string::npos)
868 sTemplate.replace(pos, 11, constructKeyWords(m_syntax->getOptions()));
869
870 if ((pos = sTemplate.find("NSCRMETHODS")) != std::string::npos)
871 sTemplate.replace(pos, 11, constructKeyWords(m_syntax->getMethods()));
872
873 if ((pos = sTemplate.find("NSCRSPECIALVALS")) != std::string::npos)
874 sTemplate.replace(pos, 15, constructKeyWords(m_syntax->getSpecial()));
875
876 // Now open the target header file
877 std::ofstream fHeader;
878 fHeader.open((getPath() + "/numereheader.tex").c_str());
879
880 // Ensure that the file is writable
881 if (!fHeader.good())
882 return;
883
884 // Write the header file contents
885 fHeader << sTemplate;
886}
887
888
900std::string DocumentationGenerator::createMainFile(const std::string& sFileName, const std::vector<std::string>& vIncludesList, const std::vector<std::string>& vFiles) const
901{
902 std::ofstream fMain;
903 std::string sLaTeXMainFile = createLaTeXFileName(sFileName) + "_main.tex";
904
905 fMain.open(sLaTeXMainFile.c_str());
906
907 if (!fMain.good())
908 return "";
909
910 // Write the preamble
911 fMain << "\\documentclass[DIV=17]{scrartcl}" << std::endl;
912 fMain << "% Main file for the documentation file " << sFileName << std::endl << std::endl;
913 fMain << "\\input{" << getPath() << "/numereheader}" << std::endl << std::endl;
914 fMain << "\\ohead{" << prepareFileNameForLaTeX(sFileName) << "}" << std::endl;
915 fMain << "\\ihead{Documentation}" << std::endl;
916 fMain << "\\ifoot{NumeRe: Free numerical software}" << std::endl;
917 fMain << "\\ofoot{Get it at: www.numere.org}" << std::endl;
918 fMain << "\\pagestyle{scrheadings}" << std::endl;
919 fMain << "\\subject{Documentation}" << std::endl;
920 fMain << "\\title{" << prepareFileNameForLaTeX(sFileName) << "}" << std::endl;
921
922 if (vFiles.size() > 1)
923 fMain << "\\subtitle{And all called procedures}" << std::endl;
924
925 fMain << "\\begin{document}" << std::endl;
926 fMain << " \\maketitle" << std::endl;
927
928 // Create an overview, if necessary
929 if (vFiles.size() > 1)
930 {
931 fMain << " \\addsec{Files included in this documentation}\n \\begin{itemize}" << std::endl;
932
933 for (size_t i = 0; i < vFiles.size(); i++)
934 fMain << " \\item " << prepareFileNameForLaTeX(vFiles[i]) << std::endl;
935
936 fMain << " \\end{itemize}" << std::endl;
937 }
938
939 // Reference all created files
940 for (size_t i = 0; i < vIncludesList.size(); i++)
941 fMain << " \\input{" << vIncludesList[i] << "}" << std::endl;
942
943 fMain << "\\end{document}" << std::endl;
944
945 return sLaTeXMainFile;
946}
947
948
957{
958 m_syntax = _syntax;
959 setPath(sRootPath, true, NumeReKernel::getInstance()->getSettings().getExePath());
960}
961
962
973std::string DocumentationGenerator::createDocumentation(const std::string& sFileName) const
974{
975 if (sFileName.find(".nscr") == std::string::npos
976 && sFileName.find(".nlyt") == std::string::npos
977 && sFileName.find(".nprc") == std::string::npos)
978 return "";
979
980 return convertToLaTeX(replacePathSeparator(sFileName));
981}
982
983
994std::string DocumentationGenerator::createFullDocumentation(const std::string& sFileName) const
995{
996 if (sFileName.find(".nscr") == std::string::npos
997 && sFileName.find(".nlyt") == std::string::npos
998 && sFileName.find(".nprc") == std::string::npos)
999 return "";
1000
1001 std::set<std::string> fileSet;
1002 std::vector<std::string> vIncludesList;
1003 std::vector<std::string> vFiles;
1004
1005 // Find all dependent files
1006 followBranch(replacePathSeparator(sFileName), fileSet, vFiles);
1007
1008 // Create documentations for all files
1009 for (size_t i = 0; i < vFiles.size(); i++)
1010 {
1011 vIncludesList.push_back(convertToLaTeX(vFiles[i]));
1012 }
1013
1014 // Create style and main files
1016 return createMainFile(replacePathSeparator(sFileName), vIncludesList, vFiles);
1017}
1018
This class handles the dependencies of the current procedure file (passed as pointer to a ProcedureEl...
Definition: dependency.hpp:81
std::map< std::string, DependencyList > & getDependencyMap()
Definition: dependency.hpp:98
This class is a child of the std::list, where the function unique() has been overridden (i....
Definition: dependency.hpp:64
std::string createReturnsTable(const std::vector< std::string > &vParams) const
This member function creates a table out of the declared return values in the documentation comments.
Definition: docgen.cpp:616
std::string convertToLaTeX(const std::string &sFileName) const
Writes the content of the current code file to a LaTeX file.
Definition: docgen.cpp:95
size_t findListItem(const std::string &sTextRange, size_t &nLength) const
This helper function finds the next list item in the passed documentation string.
Definition: docgen.cpp:651
NumeReSyntax * m_syntax
Definition: docgen.hpp:43
std::string createMainFile(const std::string &sFileName, const std::vector< std::string > &vIncludesList, const std::vector< std::string > &vFiles) const
This member function creates a main LaTeX file including the perviously created LaTeX documentation f...
Definition: docgen.cpp:900
std::string constructKeyWords(std::string sKeyWordList) const
This member function replaces the passed whitespace-separated keyword list with a comma-separated lis...
Definition: docgen.cpp:805
std::string createDocumentation(const std::string &sFileName) const
This member function creates a LaTeX documentation from a single file and stores it....
Definition: docgen.cpp:973
std::string getStrippedRange(const StyledTextFile &file, int pos1, int pos2, bool encode=true) const
Gets the contents of the selected range.
Definition: docgen.cpp:242
std::string createLaTeXFileName(std::string sFileName) const
This method will create a target filename for the TeX files and create the needed folder structure on...
Definition: docgen.cpp:718
std::string createParametersTable(const std::vector< std::string > &vParams) const
This member function creates a table out of the declared parameters in the documentation comments.
Definition: docgen.cpp:565
DocumentationGenerator(NumeReSyntax *_syntax, const std::string &sRootPath)
DocumentationGenerator constructor.
Definition: docgen.cpp:956
std::string createMainProcedure(std::string sFileName) const
This method converts the passed filename into a main procedure for the current file.
Definition: docgen.cpp:678
std::string parseDocumentation(const StyledTextFile &file, const std::string &sMainProc, int pos1, int pos2) const
Converts the documentation into LaTeX code.
Definition: docgen.cpp:322
void createStyleFile() const
This member function writes the LaTeX header file used to highlight the code snippets,...
Definition: docgen.cpp:831
void followBranch(const std::string &sFile, std::set< std::string > &fileSet, std::vector< std::string > &vFiles) const
This member function finds all dependent procedure files. If the current file is not a procedure,...
Definition: docgen.cpp:39
std::string createFullDocumentation(const std::string &sFileName) const
This member function creates a LaTeX documentation from the passed file and all dependent files....
Definition: docgen.cpp:994
std::string prepareFileNameForLaTeX(std::string sFileName) const
This member function removes the path parts of the default paths and masks underscores,...
Definition: docgen.cpp:764
This class implements the basic input/ output file system and provides functionalities to work with f...
Definition: filesystem.hpp:92
std::string getPath() const
Returns the default path of this FileSystem instance.
Definition: filesystem.cpp:547
int createFolders(const std::string &_sPath) const
This member function creates all missing directories in the passed path.
Definition: filesystem.cpp:234
int setPath(std::string _sPath, bool bMkDir, std::string _sExePath)
This member function may be used to set the preferred file path of the current FileSystem instance.
Definition: filesystem.cpp:443
static NumeReKernel * getInstance()
This static member function returns a a pointer to the singleton instance of the kernel.
Definition: kernel.hpp:221
ProcedureLibrary & getProcedureLibrary()
Definition: kernel.hpp:321
std::vector< std::string > getPathSettings() const
This member function returns a vector containing all currently declared paths in a distinct order.
Definition: kernel.cpp:2531
This class contains all needed keywords to highlight their occurences correspondingly....
Definition: syntax.hpp:55
std::string getNPRCCommands() const
Definition: syntax.hpp:117
std::string getConstants() const
Definition: syntax.hpp:125
std::string getMethods() const
Definition: syntax.hpp:123
std::string getCommands() const
Definition: syntax.hpp:115
std::string getSpecial() const
Definition: syntax.hpp:127
std::string getFunctions() const
Definition: syntax.hpp:121
std::string getOptions() const
Definition: syntax.hpp:119
Dependencies * getDependencies()
This member function returns the first-level dependencies of the current procedure file....
This class manages all already read and possibly pre-parsed procedure files for easier and faster acc...
ProcedureElement * getProcedureContents(const std::string &sProcedureFileName)
Returns the ProcedureElement pointer to the desired procedure file. It also creates the element,...
This class represents a text file in memory (e.g. a code file). This class will try to lex the loaded...
int getLastPosition() const
Returns the last printable character position in the currently loaded file.
int LineFromPosition(size_t pos) const
Returns the line number containing the selected character position.
std::string getTextRange(int pos1, int pos2) const
This method returns the text between the passed two positions (including possible line termination ch...
int getLineEndPosition(size_t line) const
Returns the position of the last printable character in the selected line (before any line terminatio...
int PositionFromLine(size_t line) const
Returns the position of the first character in the selected line.
Style getStyleAt(size_t pos) const
Returns the style at the current selected character position.
std::string getFileName() const
Returns the filename of the respresented file in memory.
@ SCRIPTPATH
@ EXEPATH
@ LOADPATH
@ PATH_LAST
@ PROCPATH
std::string replacePathSeparator(const std::string &)
This function replaces the Windows style path sparators to UNIX style.
void replaceAll(std::string &sToModify, const char *sToRep, const char *sNewValue, size_t nStart, size_t nEnd)
This function replaces all occurences of the string sToRep in the string sToModify with the new value...
std::vector< std::string > getEventProcedures(const std::string &sLayoutFile)
Examines a window layout file and searches for all event handler procedures. Returns their correspond...
Definition: winlayout.cpp:723