NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
styledtextfile.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 <fstream>
20
21#include "styledtextfile.hpp"
22
23
33{
34 std::ifstream file(sFileName);
35 std::string sLine;
36
37 if (!file.good())
38 return;
39
40 vFileContents.clear();
41
42 // Read the complete file
43 while (!file.eof())
44 {
45 std::getline(file, sLine);
46
47 // Store also the character positions at the
48 // start of the current line
49 if (!vFileContents.size())
50 vFileContents.push_back(std::make_pair(0, sLine));
51 else
52 vFileContents.push_back(std::make_pair(vFileContents.back().first + vFileContents.back().second.length() + 2, sLine));
53 }
54}
55
56
65{
66 vStyles.clear();
67
68 Style lastStyle = DEFAULT;
69
70 // Go through the document
71 for (size_t i = 0; i < vFileContents.size(); i++)
72 {
73 // Create a new line in the style table
74 if (vFileContents[i].second.length())
75 vStyles.push_back(std::vector<Style>(vFileContents[i].second.length()+2, DEFAULT));
76 else // Fallback for empty lines, which will otherwise cancel comment blocks
77 vStyles.push_back(std::vector<Style>(2, lastStyle));
78
79 // Detect changes in the styles
80 for (size_t j = 0; j < vFileContents[i].second.length(); j++)
81 {
82 // Are we currently in default mode?
83 if (lastStyle == DEFAULT)
84 {
85 if (sDocCommentLine.length()
86 && vFileContents[i].second.substr(j, sDocCommentLine.length()) == sDocCommentLine)
87 {
88 for (; j < vStyles[i].size(); j++)
90 }
91 else if (sCommentLine.length()
92 && vFileContents[i].second.substr(j, sCommentLine.length()) == sCommentLine)
93 {
94 for (; j < vStyles[i].size(); j++)
95 vStyles[i][j] = COMMENT_LINE;
96 }
97 else if (useStrings
98 && vFileContents[i].second.substr(j, sStringMarks.length()) == sStringMarks)
99 lastStyle = STRING;
100 else if (sDocCommentBlockStart.length()
101 && vFileContents[i].second.substr(j, sDocCommentBlockStart.length()) == sDocCommentBlockStart)
102 lastStyle = COMMENT_DOC_BLOCK;
103 else if (sCommentBlockStart.length()
104 && vFileContents[i].second.substr(j, sCommentBlockStart.length()) == sCommentBlockStart)
105 lastStyle = COMMENT_BLOCK;
106
107 // Increment the position, if the current
108 // style starts a block style
109 if (lastStyle > BLOCK_START)
110 {
111 vStyles[i][j] = lastStyle;
112 j++;
113 }
114
115 }
116
117 // Is the current style part of any
118 // block style (possible lasting
119 // over multiple lines)
120 if (lastStyle > BLOCK_START)
121 {
122 size_t pos;
123 size_t blockEndLength;
124
125 // Try to find the end of the current
126 // block style
127 if (lastStyle == STRING)
128 {
129 blockEndLength = 1;
130 pos = j;
131
132 while ((pos = vFileContents[i].second.find(sStringMarks, pos)) != std::string::npos)
133 {
134 if (!pos || vFileContents[i].second[pos-1] != '\\')
135 break;
136
137 pos++;
138 }
139 }
140 else
141 {
142 pos = vFileContents[i].second.find(sBlockEnd, j);
143 blockEndLength = sBlockEnd.length();
144 }
145
146 // Apply the styling to the current line
147 // (style everything, if nothing was found,
148 // otherwise until the detected position)
149 if (pos == std::string::npos)
150 {
151 for (; j < vStyles[i].size(); j++)
152 vStyles[i][j] = lastStyle;
153 }
154 else
155 {
156 for (; j < pos+blockEndLength; j++)
157 vStyles[i][j] = lastStyle;
158
159 lastStyle = DEFAULT;
160 }
161 }
162 }
163 }
164}
165
166
174StyledTextFile::StyledTextFile(const std::string& fileName) : sFileName(fileName)
175{
176 sCommentLine = "##";
177 sDocCommentLine = "##!";
178 sCommentBlockStart = "#*";
179 sDocCommentBlockStart = "#*!";
180 sBlockEnd = "*#";
181 sStringMarks = "\"";
182 useStrings = true;
183
184 load();
185 lex();
186}
187
188
197{
198 return sFileName;
199}
200
201
212std::string StyledTextFile::getTextRange(int pos1, int pos2) const
213{
214 // Find the start and end line
215 int line1 = LineFromPosition(pos1);
216 int line2 = LineFromPosition(pos2);
217
218 if (line1 == -1 || line2 == -1)
219 return "";
220
221 // Find the positions in the lines
222 pos1 -= vFileContents[line1].first;
223 pos2 -= vFileContents[line2].first;
224
225 std::string sTextRange;
226
227 // Extract the contents into a single string
228 if (line1 == line2)
229 sTextRange = (vFileContents[line1].second + "\r\n").substr(pos1, pos2-pos1);
230 else
231 {
232 sTextRange = (vFileContents[line1].second + "\r\n").substr(pos1);
233
234 for (int line = line1+1; line < line2; line++)
235 sTextRange += vFileContents[line].second + "\r\n";
236
237 sTextRange += (vFileContents[line2].second + "\r\n").substr(0, pos2);
238 }
239
240 return sTextRange;
241}
242
243
252std::string StyledTextFile::getLine(size_t line) const
253{
254 if (line < vFileContents.size())
255 return vFileContents[line].second;
256
257 return "";
258}
259
260
270std::string StyledTextFile::getStrippedLine(size_t line) const
271{
272 if (line < vFileContents.size())
273 {
274 std::string sLine;
275
276 for (size_t i = 0; i < vFileContents[line].second.length(); i++)
277 {
278 if (vStyles[line][i] == StyledTextFile::DEFAULT || vStyles[line][i] == StyledTextFile::STRING)
279 sLine.push_back(vFileContents[line].second[i]);
280 }
281
282 return sLine;
283 }
284
285 return "";
286}
287
288
297{
298 return getLinesCount() ? vFileContents.back().first + vFileContents.back().second.length() : -1;
299}
300
301
310{
311 return vFileContents.size();
312}
313
314
324{
325 return getLineStartPosition(line);
326}
327
328
338{
339 for (size_t line = 0; line < vFileContents.size(); line++)
340 {
341 if (pos >= vFileContents[line].first && pos < vFileContents[line].first + vFileContents[line].second.length()+2)
342 return line;
343 }
344
345 return -1;
346}
347
348
359{
360 if (line < vFileContents.size())
361 return vFileContents[line].first + vFileContents[line].second.length();
362
363 return -1;
364}
365
366
376{
377 if (line < vFileContents.size())
378 return vFileContents[line].first;
379
380 return -1;
381}
382
383
395{
396 size_t pos = vFileContents[line].second.find_first_not_of(" \t");
397
398 if (pos == std::string::npos
399 || (getStyleAt(pos + vFileContents[line].first) != COMMENT_DOC_BLOCK
400 && getStyleAt(pos + vFileContents[line].first) != COMMENT_DOC_LINE))
401 return -1;
402
403 long long int nPos = pos + vFileContents[line].first;
404 size_t nWhitespace = 0;
405
406 while (nPos >= 0 && (getStyleAt(nPos) == COMMENT_DOC_BLOCK || getStyleAt(nPos) == COMMENT_DOC_LINE || getCharAt(nPos) == ' ' || getCharAt(nPos) == '\t'))
407 {
408 if ((getStyleAt(nPos) != COMMENT_DOC_BLOCK && getStyleAt(nPos) != COMMENT_DOC_LINE) && (getCharAt(nPos) == ' ' || getCharAt(nPos) == '\t'))
409 nWhitespace++;
410 else
411 nWhitespace = 0;
412
413 nPos--;
414 }
415
416 return LineFromPosition(nPos+nWhitespace);
417}
418
419
429{
430 int line = LineFromPosition(pos);
431
432 if (line != -1)
433 return vStyles[line][pos - getLineStartPosition(line)];
434
435 return STYLE_ERROR;
436}
437
438
447char StyledTextFile::getCharAt(size_t pos) const
448{
449 int line = LineFromPosition(pos);
450
451 if (line != -1)
452 return vFileContents[line].second[pos - vFileContents[line].first];
453
454 return '\0';
455}
456
457
473void StyledTextFile::reStyle(const std::string& sComLine,
474 const std::string& sDocComLine,
475 const std::string& sComBlockStart,
476 const std::string& sDocComBlockStart,
477 const std::string& sComBlockEnd,
478 const std::string& sStrMarks,
479 bool strings)
480{
481 sCommentLine = sComLine;
482 sDocCommentLine = sDocComLine;
483 sCommentBlockStart = sComBlockStart;
484 sDocCommentBlockStart = sComBlockStart;
485 sBlockEnd = sComBlockEnd;
486 sStringMarks = sStrMarks;
487 useStrings = strings;
488
489 lex();
490}
491
492
493
int getLastPosition() const
Returns the last printable character position in the currently loaded file.
std::string sCommentLine
std::vector< std::pair< size_t, std::string > > vFileContents
std::string getStrippedLine(size_t line) const
Returns the selected line (without the line termination characters and without any comments).
int getLineStartPosition(size_t line) const
Returns the position of the first character in the selected line.
void lex()
This method runs a lexer over the loaded document to obtain styling information.
StyledTextFile(const std::string &fileName)
StyledTextFile constructor. Will load and lex the specified file using NumeRe code.
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...
std::string sBlockEnd
std::string sFileName
std::string sCommentBlockStart
std::string sDocCommentLine
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 sDocCommentBlockStart
int findDocStartLine(size_t line) const
Finds the first line of the current documentation comment or -1, if the current line does not contain...
void reStyle(const std::string &sComLine, const std::string &sDocComLine, const std::string &sComBlockStart, const std::string &sDocComBlockStart, const std::string &sComBlockEnd, const std::string &sStrMarks="", bool strings=true)
Can be used to change the code style detection sequences and to re-apply the lexer to the currently l...
void load()
This method loads the specified file to memory, while keeping the character positions.
int getLinesCount() const
Returns the number of lines in the current loaded file.
std::vector< std::vector< Style > > vStyles
std::string sStringMarks
std::string getLine(size_t line) const
Returns the selected line (without the line termination characters).
std::string getFileName() const
Returns the filename of the respresented file in memory.
char getCharAt(size_t pos) const
Returns the character located at the position pos.