forked from endocode/snippetextractor
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathProcess.cpp
More file actions
188 lines (179 loc) · 6.94 KB
/
Process.cpp
File metadata and controls
188 lines (179 loc) · 6.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#include <QString>
#include <QRegularExpression>
#include <QFile>
#include <QTextStream>
#include "Helpers.h"
#include "Process.h"
#include "Exception.h"
void process( const QString inputfilename, const QString outputfilename) {
const QString result = process(inputfilename);
QFile outputfile(outputfilename);
if (!outputfile.open(QIODevice::WriteOnly)) {
throw Exception(u("Unable to open output file \"%1\" for writing!").arg(outputfilename));
}
QTextStream stream(&outputfile);
stream << result;
}
QString process(const QString inputfilename)
{
QFile inputfile(inputfilename);
if (!inputfile.open(QIODevice::ReadOnly)) {
throw Exception(u("Unable to open input file \"%1\" for reading!").arg(inputfilename));
}
QString result;
QTextStream stream(&inputfile);
int linecounter = 0;
while (!stream.atEnd()) {
++linecounter;
const QString positionInFile = u("%1:%2").arg(inputfilename).arg(linecounter);
auto line = stream.readLine();
const int index = line.indexOf(u("@@snippet("));
if ( index != -1) {
const int openingBracket = line.indexOf(u("("), index);
Q_ASSERT(openingBracket != 0); // we just searched for it above
int position = openingBracket;
int brackets = 1;
while (brackets != 0) {
position += 1;
if (position == line.count()) {
throw Exception(u("%1: Syntax error, opening and closing brackets do not match!")
.arg(positionInFile));
}
auto const character = line.at(position);
if (character == QChar::fromLatin1('(')) {
brackets += 1;
} else if (character == QChar::fromLatin1(')')) {
brackets -= 1;
}
}
const QString command = line.mid(index, openingBracket - index);
const QString arguments = line.mid(openingBracket + 1, position - openingBracket - 1);
if (command == u("@@snippet")) {
result += process_snippet(arguments, positionInFile);
} else {
throw Exception(u("%1: Unknown parser instruction \"%1\" at line %2!").arg(positionInFile).arg(command));
}
} else {
result.append(line + u("\n"));
}
}
return result;
}
void get_snippet_guards(const QString mode, const QString snippet,
const QString style, int linecounter,
QString& opener, QString& closer)
{
if(mode == QString("minted")) {
opener = QString("\\begin{minted}[breaklines]{%1}\n").arg(style);
closer = QString("\\end{minted}\n");
} else if(mode == QString("tabminted")) {
opener = QString("\\begin{tabminted}[breaklines]{%1}\n").arg(style);
closer = QString("\\end{tabminted}\n");
} else {
// default to markdown as it always was the default
opener = QString("~~~ {#%1 .%2 .numberLines startFrom=\"%3\"}\n")
.arg(snippet)
.arg(style)
.arg(linecounter + 1);
closer = QString("~~~\n");
}
}
int find_closing_bracket(const QString line, const int openingBracket)
{
int position = openingBracket;
int brackets = 1;
while (brackets != 0) {
position += 1;
if (position == line.count()) {
return -1;
}
auto character = line.at(position);
if (character == u("(")) {
brackets += 1;
} else if (character == u(")")) {
brackets -= 1;
}
}
return position;
}
QString process_snippet(const QString argumentString, const QString& position)
{
const QStringList arguments = argumentString.split(u(","));
if (arguments.count() != 3 && arguments.count() != 4) {
throw Exception(u("%1: Argument error!").arg(position));
}
const QString filename = arguments[0].trimmed();
const QString snippet = arguments[1].trimmed();
const QString style = arguments[2].trimmed();
QString mode = QString("markdown");
if (arguments.count() == 4) {
mode = arguments[3].trimmed();
}
QFile sourceFile(filename);
if (!sourceFile.open(QIODevice::ReadOnly)) {
throw Exception(u("%1: Error opening file \"%2\" for reading!").arg(position).arg(filename));
}
QTextStream stream(&sourceFile);
int linecounter = 0;
bool found = false;
bool reading = false;
bool complete = false;
QString result;
while (!stream.atEnd()) {
++linecounter;
QString opener, closer;
get_snippet_guards(mode, snippet, style, linecounter, opener, closer);
const QString positionInFile = u("%1:%2").arg(filename).arg(linecounter);
const QRegularExpression snipped_end(u("(\\/\\/|\\#\\#)\\@\\@snippet_end\\("));
const QRegularExpression snippet_begin(u("(\\/\\/|\\#\\#)\\@\\@snippet_begin\\("));
auto line = stream.readLine();
if (reading) {
// drop lines with @@snippet_begin
if(line.indexOf(snippet_begin) != -1)
continue;
const int index = line.indexOf(snipped_end);
if (index == -1) {
result.append(line + u("\n"));
} else {
const int openingBracket = line.indexOf(u("("), index);
Q_ASSERT(openingBracket != 0); // we just searched for it above
const int position = find_closing_bracket(line, openingBracket);
if(position == -1)
throw Exception(u("%1: Syntax error, opening and closing brackets do not match!")
.arg(positionInFile));
const QString name = line.mid(openingBracket + 1, position - openingBracket - 1);
if (name == snippet) {
reading = false;
result += closer;
complete = true;
break;
} else {
continue;
}
}
} else {
const int index = line.indexOf(snippet_begin);
if (index != -1) {
const int openingBracket = line.indexOf(u("("), index);
Q_ASSERT(openingBracket != 0); // we just searched for it above
const int position = find_closing_bracket(line, openingBracket);
if(position == -1)
throw Exception(u("%1: Syntax error, opening and closing brackets do not match!")
.arg(positionInFile));
const QString name = line.mid(openingBracket + 1, position - openingBracket - 1);
if (name == snippet) {
reading = true;
found = true;
result += opener;
}
}
}
}
if (!found) {
throw Exception(u("%1: Snippet \"%2\" not found!").arg(filename).arg(snippet));
}
if (!complete) {
throw Exception(u("%1: End tag not found for snippet \"%2\"!").arg(filename).arg(snippet));
}
return result;
}