-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstrings_with_arrows.h
50 lines (42 loc) · 2 KB
/
strings_with_arrows.h
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
#pragma once
#ifndef STRINGS_WITH_ARROWS_H
#define STRINGS_WITH_ARROWS_H
#include <string>
#include <regex>
#include "../../position/position.h"
// Translation from python: https://github.com/davidcallanan/py-myopl-code/blob/master/ep2/strings_with_arrows.py
// Code is originally under the MIT License, copyright David Callanan 2019
// https://github.com/davidcallanan/py-myopl-code/blob/master/LICENSE
inline std::string strings_with_arrows(const std::string& text, const Position& positionStart, const Position& positionEnd) {
std::string result = "";
// Calculate indices
int indexStart = text.substr(0, positionStart.index).rfind('\n');
if (indexStart < 0) indexStart = 0;
int indexEnd = text.size() - 1 >= (unsigned) indexStart ? -1 : text.substr(indexStart + 1).find('\n');
if (indexEnd < 0) indexEnd = text.size(); else indexEnd += indexEnd + 1;
// Find the number of lines
int lineCount = positionEnd.lineNumber - positionStart.lineNumber + 1;
for (int i = 0; i < lineCount; i++) {
// Calculate line columns
std::string line = text.substr(indexStart, indexEnd);
int columnStart = 0;
if (i == 0) columnStart = positionStart.columnNumber;
int columnEnd = line.length() - 1;
if (i == lineCount - 1) columnEnd = positionEnd.columnNumber;
// Append the result
result += line + "\n";
result += std::string(columnStart, ' ') + std::string(columnEnd - columnStart, '^');
// Recalculate the indices
indexStart = indexEnd;
try {
indexEnd = text.substr(indexStart + 1).find('\n');
} catch (...) {
indexEnd = -1;
}
if (indexEnd < 0) indexEnd = text.size(); else indexEnd += indexEnd + 1;
}
// Get rid of tabs (I don't know why this is done, but the original does this, so I'll do it too)
// Adding regex here, just to do this, is probably really inefficient
return std::regex_replace(result, std::regex("\t"), "");
}
#endif // !STRINGS_WITH_ARROWS_H