REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestStringOutput.cxx
1#include "TRestStringOutput.h"
2
3#include "TRestStringHelper.h"
4
5using namespace std;
6
7#ifdef WIN32
8#include <Windows.h>
9#include <conio.h>
10#endif // WIN32
11
12int Console::GetWidth() {
13#ifdef WIN32
14 CONSOLE_SCREEN_BUFFER_INFO csbi;
15 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
16 return csbi.srWindow.Right - csbi.srWindow.Left + 1;
17#else
18 if (isatty(fileno(stdout))) {
19 struct winsize w;
20 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
21 return w.ws_col;
22 }
23 return -1;
24#endif // WIN32
25}
26
27int Console::GetHeight() {
28#ifdef WIN32
29 CONSOLE_SCREEN_BUFFER_INFO csbi;
30 GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
31 return csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
32#else
33 if (isatty(fileno(stdout))) {
34 struct winsize w;
35 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
36 return w.ws_row;
37 }
38 return -1;
39#endif // WIN32
40}
41
42bool Console::kbhit() {
43#ifdef WIN32
44 return _kbhit();
45#else
46 struct termios oldt, newt;
47 int ch;
48 int oldf;
49 tcgetattr(STDIN_FILENO, &oldt);
50 newt = oldt;
51 newt.c_lflag &= ~(ICANON | ECHO);
52 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
53 oldf = fcntl(STDIN_FILENO, F_GETFL, 0);
54 fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK);
55 ch = getchar();
56 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
57 fcntl(STDIN_FILENO, F_SETFL, oldf);
58 if (ch != EOF) {
59 ungetc(ch, stdin);
60 return true;
61 }
62 return false;
63
64// int byteswaiting;
65// ioctl(0, FIONREAD, &byteswaiting);
66// return byteswaiting > 0;
67#endif
68}
69
70int Console::Read() { return getchar(); }
71
72int Console::ReadKey() {
73#ifdef WIN32
74 return _getch();
75#else
76 struct termios tm, tm_old;
77 int fd = 0, ch;
78
79 if (tcgetattr(fd, &tm) < 0) {
80 return -1;
81 }
82
83 tm_old = tm;
84 cfmakeraw(&tm);
85 if (tcsetattr(fd, TCSANOW, &tm) < 0) {
86 return -1;
87 }
88
89 ch = getchar();
90 if (tcsetattr(fd, TCSANOW, &tm_old) < 0) {
91 return -1;
92 }
93
94 return ch;
95#endif
96}
97
98string Console::ReadLine() {
99 char a[500];
100 cin.getline(a, 500);
101 return string(a);
102}
103
104void Console::WriteLine(string content) {
105 printf("%s", content.c_str());
106 fflush(stdout);
107}
108
109void Console::CursorUp(int n) {
110 printf("\033[%dA", n);
111 fflush(stdout);
112}
113
114void Console::CursorDown(int n) {
115 printf("\033[%dB", n);
116 fflush(stdout);
117}
118
119void Console::CursorRight(int n) {
120 printf("\033[%dC", n);
121 fflush(stdout);
122}
123
124void Console::CursorLeft(int n) {
125 printf("\033[%dD", n);
126 fflush(stdout);
127}
128
129void Console::CursorToXY(int x, int y) {
130 printf("\033[%d%dH", x, y);
131 fflush(stdout);
132}
133
134void Console::ClearScreen() {
135 printf("\033[2J");
136 fflush(stdout);
137}
138
139void Console::ClearCurrentLine() {
140#ifdef WIN32
141 printf("\r");
142 fflush(stdout);
143#else
144 printf("\033[K");
145 fflush(stdout);
146#endif // WIN32
147}
148
149void Console::ClearLinesAfterCursor() {
150 printf("\033[s");
151 for (int i = 0; i < 50; i++) {
152 printf("\033[K");
153 CursorDown(1);
154 }
155 printf("\033[u");
156 fflush(stdout);
157}
158
159char mirrorchar(char c) {
160 switch (c) {
161 default:
162 return c;
163 case '<':
164 return '>';
165 case '>':
166 return '<';
167 case '[':
168 return ']';
169 case ']':
170 return '[';
171 case '{':
172 return '}';
173 case '}':
174 return '{';
175 case '(':
176 return ')';
177 case ')':
178 return '(';
179 case '\\':
180 return '/';
181 case '/':
182 return '\\';
183 case 'd':
184 return 'b';
185 case 'b':
186 return 'd';
187 case 'q':
188 return 'p';
189 case 'p':
190 return 'q';
191 }
192}
193
194#define TRestStringOutput_BestLength 100
195TRestStringOutput::TRestStringOutput(COLORCODE_TYPE _color, string formatter,
196 REST_Display_Orientation _orientation) {
197 iserror = false;
198 color = _color;
199 orientation = _orientation;
200 // check if is border expression
201 useborder = true;
202 if (formatter.size() < 2) {
203 useborder = false;
204 }
205 for (unsigned int i = 0; i < formatter.size() / 2; i++) {
206 if (mirrorchar(formatter[i]) != formatter[formatter.size() - i - 1]) {
207 useborder = false;
208 break;
209 }
210 }
211 if (formatter[formatter.size() / 2] != ' ') {
212 useborder = false;
213 }
214
215 if (useborder) {
216 formatstring = formatter.substr(0, formatter.size() / 2);
217 formatstring = Replace(formatstring, " ", "");
218 } else {
219 formatstring = formatter;
220 }
221
222 setlength(TRestStringOutput_BestLength);
223 resetstring();
224 if (length > 500 || length < 20) // unsupported console, we will fall back to compatibility modes
225 {
226 length = -1;
227 REST_Display_CompatibilityMode = true;
228 }
229
231}
232
233void TRestStringOutput::resetstring() {
234 buf.clear();
235 buf.str("");
236}
237
238string TRestStringOutput::FormattingPrintString(string input) {
239 if (input == "") return "";
240
241 // input: "=abc=", output "=============abc============="(length)
242 if (input[0] == input[input.size() - 1] &&
243 (input[0] == '=' || input[0] == '-' || input[0] == '*' || input[0] == '+')) {
244 return string(length, input[0]);
245 }
246
247 if (useborder) {
248 string output(length, ' ');
249
250 int Lstr = input.size();
251 int Lfmt = formatstring.size();
252
253 int startblank;
254 if (useborder || orientation == TRestStringOutput::REST_Display_Orientation::kMiddle) {
255 startblank = (length - Lstr) / 2;
256 } else {
257 startblank = Lfmt;
258 }
259 if (startblank < 0) {
260 startblank = 0;
261 }
262
263 string& border = formatstring;
264 for (int i = 0; i < Lfmt && i < length; i++) {
265 output[i] = border[i];
266 output[length - i - 1] = mirrorchar(border[i]);
267 }
268
269 for (int i = 0; i < Lstr; i++) {
270 if (startblank + i > length - 1) {
271 output[length - 3] = '.';
272 output[length - 2] = '.';
273 output[length - 1] = '.';
274 return output;
275 }
276 output[startblank + i] = input[i];
277 }
278
279 return output;
280 } else {
281 return formatstring + input;
282 }
283}
284
285void TRestStringOutput::setlength(int n) {
286 if (!REST_Display_CompatibilityMode) {
287 if (n >= Console::GetWidth() - 2) {
288 length = Console::GetWidth() - 2;
289 } else if (n <= 0) {
290 length = Console::GetWidth() - 2;
291 } else {
292 length = n;
293 }
294 } else {
295 length = n;
296 }
297}
298
299#ifdef WIN32
300// use >> 4 << 4 to extract first 4 bytes from COLOR_RESET, which means the background color
301#define SET_COLOR(color) \
302 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), (COLOR_RESET >> 4 << 4) + color);
303#define RESET_COLOR() SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), COLOR_RESET);
304#else
305#define SET_COLOR(color) std::cout << color;
306#define RESET_COLOR() std::cout << COLOR_RESET;
307#endif // WIN32
308
309void TRestStringOutput::flushstring() {
310 if (REST_Display_CompatibilityMode) // this means we are using condor
311 {
312 std::cout << buf.str() << std::endl;
313 } else {
314 Console::ClearCurrentLine();
315 if (orientation == TRestStringOutput::REST_Display_Orientation::kMiddle) {
316 // we always reset the length of TRestStringOutput in case the console is resized
317 setlength(TRestStringOutput_BestLength);
318 int blankwidth = (Console::GetWidth() - 2 - length) / 2;
319
320 SET_COLOR(color);
321 std::cout << string(blankwidth, ' ') << FormattingPrintString(buf.str())
322 << string(blankwidth, ' ');
323 RESET_COLOR()
324 std::cout << std::endl;
325 } else {
326 SET_COLOR(color);
327 std::cout << FormattingPrintString(buf.str());
328 RESET_COLOR()
329 std::cout << std::endl;
330 }
331 }
332 resetstring();
333}
334
335TRestStringOutput& TRestStringOutput::operator<<(void (*pfunc)(TRestStringOutput&)) {
336 if (gVerbose >= verbose) {
337 ((*pfunc)(*this));
338 }
339 return *this;
340}
@ REST_Essential
+show some essential information, as well as warnings
std::string Replace(std::string in, std::string thisString, std::string byThisString, size_t fromPosition=0, Int_t N=0)
Replace any occurences of thisSring by byThisString inside string in.