-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfile.hpp
127 lines (112 loc) · 3.25 KB
/
file.hpp
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
#pragma once
#include <cassert>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <vector>
enum class diff_t { SAME, ADDED, CHANGED };
using diffs_t = std::vector<diff_t>;
using key_t = int;
std::map<std::string, key_t> mapping = {{"", 0}};
std::map<key_t, std::string> rev_mapping = {{0, ""}};
static const std::string specials = "!\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~";
constexpr const char *diff_color(diff_t d) {
switch (d) {
case diff_t::SAME:
return "\033[0m";
case diff_t::ADDED:
return "\033[41;37;1m";
case diff_t::CHANGED:
return "\033[1;30;43m";
}
return "";
}
std::string replace_all(std::string s, const std::string &c,
const std::string &repl) {
for (size_t i = s.find(c); i != std::string::npos;
i = s.find(c, i + repl.size())) {
s.replace(i, c.size(), repl);
}
return s;
}
struct file_t {
using content_t = std::vector<key_t>;
std::string group;
std::string path;
content_t content;
std::vector<std::string> spaces;
file_t(std::string file) {
path = file;
std::ifstream in(file);
std::string str((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
std::string current;
bool is_spaces = true;
auto take = [&]() {
if (mapping.count(current) == 0) {
rev_mapping[mapping.size()] = current;
mapping[current] = mapping.size();
}
content.push_back(mapping[current]);
current = "";
is_spaces = true;
};
for (size_t i = 0; i < str.size();) {
char c = str[i];
if (is_spaces) {
if (isspace(c)) {
current += c;
i++;
} else {
spaces.push_back(current);
current = "";
is_spaces = false;
}
} else {
auto spec_pos = specials.find(c);
if (isspace(c)) {
take();
} else if (spec_pos != std::string::npos) {
if (!current.empty()) {
take();
} else {
content.push_back(-1 - spec_pos);
i++;
is_spaces = true;
}
} else {
current += c;
i++;
}
}
}
if (is_spaces) {
spaces.push_back(current);
} else {
take();
spaces.push_back("");
}
assert(spaces.size() == content.size() + 1);
}
const key_t &operator[](size_t i) const { return content[i]; }
void print(std::ofstream &out, const diffs_t &d, const diffs_t &wd) {
assert(d.size() == content.size());
out << "\033[1;4m==> " << path << " <==\033[0m" << std::endl << std::endl;
for (size_t i = 0; i < content.size(); i++) {
out << diff_color(wd[i]);
out << ((wd[i] == diff_t::SAME)
? spaces[i]
: replace_all(replace_all(spaces[i], "\r\n", "\n"), "\n",
std::string("\\n") + diff_color(diff_t::SAME) +
"\n" + diff_color(wd[i])));
out << diff_color(diff_t::SAME);
out << diff_color(d[i])
<< (content[i] >= 0 ? rev_mapping[content[i]]
: specials.substr(-1 - content[i], 1))
<< diff_color(diff_t::SAME);
}
if (!spaces.empty())
out << spaces.back() << std::endl;
}
};