termstyle 1.0.0-pre.3
An open-source C++ header file that enables developers to easily define and apply customizable style presets for terminal outputs such as warnings, infos, and errors.
Loading...
Searching...
No Matches
termstyle.hpp
Go to the documentation of this file.
1
9#pragma once
10#ifndef TERMSTYLE_HPP
11#define TERMSTYLE_HPP
12
13#include <iostream>
14#include <stdexcept>
15
16#define TERMSTYLE_NODISCARD [[nodiscard]]
17
18#define TERMSTYLE_ERROR_DEF(parent, name) \
19protected: \
20 name(std::string ename, std::string msg, int exit_code) \
21 : parent(std::move(ename), std::move(msg), exit_code) {} \
22 name(std::string ename, std::string msg, ExitCodes exit_code) \
23 : parent(std::move(ename), std::move(msg), exit_code) {} \
24 \
25public: \
26 name(std::string msg, ExitCodes exit_code) \
27 : parent(#name, std::move(msg), exit_code) {} \
28 name(std::string msg, int exit_code) \
29 : parent(#name, std::move(msg), exit_code) {}
30
31#define TERMSTYLE_ERROR_SIMPLE(name) \
32 explicit name(std::string msg) : name(#name, msg, ExitCodes::name) {}
33
34enum class ExitCodes : int
35{
36 SUCCESS = 0,
37 IncorrectConstruction = 100,
41 BaseClass = 200
42};
43
53class Error : public std::runtime_error
54{
55 int exit_code;
56 std::string error_name{"Error"};
57
58public:
59 TERMSTYLE_NODISCARD int getExitCode() const
60 {
61 return exit_code;
62 }
63
64 TERMSTYLE_NODISCARD std::string getErrorName() const
65 {
66 return error_name;
67 }
68
69 Error(std::string name, std::string msg, int exit_code = static_cast<int>(ExitCodes::BaseClass))
70 : std::runtime_error(msg), exit_code(exit_code), error_name(name) {}
71
72 Error(std::string name, std::string msg, ExitCodes exit_code) : Error(name, msg,
73 static_cast<int>(exit_code)) {}
74};
75
79class PresetNameUsed : public Error
80{
81 TERMSTYLE_ERROR_DEF(Error, PresetNameUsed)
82 explicit PresetNameUsed(std::string name)
83 : PresetNameUsed("Preset name \"" + name + "\" is already used.", ExitCodes::PresetNameUsed) {}
84};
85
90class PresetNotFound : public Error
91{
92 TERMSTYLE_ERROR_DEF(Error, PresetNotFound)
93 explicit PresetNotFound(std::string name)
94 : PresetNotFound("Preset \"" + name + "\" not found.", ExitCodes::PresetNotFound) {}
95};
96
97class BadColorID : public Error
98{
99 TERMSTYLE_ERROR_DEF(Error, BadColorID)
100 TERMSTYLE_ERROR_SIMPLE(BadColorID);
101};
102
103#undef TERMSTYLE_ERROR_DEF
104#undef TERMSTYLE_ERROR_SIMPLE
105
106 // end of Error_group
107
108#include <string>
109#include <vector>
110#include <map>
111
115namespace termstyle
116{
117
127 enum class Codes : int
128 {
129 RESTORE = 0,
130 BRIGHT = 1,
131 DIM = 2,
132 ITALIC = 3,
133 UNDERLINE = 4,
134 FLASH = 5,
135 REVERSE = 7,
136 HIDDEN = 8,
137 STRIKE = 9,
138
139 BRIGHT_RESET = 22, // reset bright and dim
140 DIM_RESET = 22,
141 ITALIC_RESET = 23,
142 UNDERLINE_RESET = 24,
143 FLASH_RESET = 25,
144 REVERSE_RESET = 27,
145 HIDDEN_RESET = 28,
146 STRIKE_RESET = 29,
147
148 FOREGROUND_BLACK = 30,
149 FOREGROUND_RED = 31,
150 FOREGROUND_GREEN = 32,
151 FOREGROUND_YELLOW = 33,
152 FOREGROUND_BLUE = 34,
153 FOREGROUND_PURPLE = 35,
154 FOREGROUND_CYAN = 36,
155 FOREGROUND_WHITE = 37,
156
157 FOREGROUND_RESET = 39,
158
159 BACKGROUND_BLACK = 40,
160 BACKGROUND_RED = 41,
161 BACKGROUND_GREEN = 42,
162 BACKGROUND_YELLOW = 43,
163 BACKGROUND_BLUE = 44,
164 BACKGROUND_PURPLE = 45,
165 BACKGROUND_CYAN = 46,
166 BACKGROUND_WHITE = 47,
167
168 BACKGROUND_RESET = 49
169 };
170
185 template<typename T>
186 std::string code2string(const std::vector<T>& codelist) noexcept
187 {
188 if (codelist.empty()) return "";
189 std::string res = "\033[";
190 for (size_t i = 0; i < codelist.size(); i++)
191 {
192 res += std::to_string(static_cast<int>(codelist[i]));
193 if (i != codelist.size() - 1)
194 {
195 res += ";";
196 }
197 }
198 res += "m";
199 return res;
200 }
201
208 std::string code2string(const Codes &col)
209 {
210 return "\033[" + std::to_string(static_cast<int>(col)) + "m";
211 }
212
213 // end of Col16_group
214
218 enum class ColorMode : int
219 {
220 FOREGROUND = 38,
221 BACKGROUND = 48
222 };
223
227 enum class ColorType : int
228 {
229 COL16 = 0,
230 COL256 = 1,
231 COLRGB = 2
232 };
233
249 bool validateColorID(int ID)
250 {
251 return ID >= 0 && ID <= 255;
252 }
253
257 struct Col256
258 {
270 int ID;
271 explicit Col256(ColorMode mode, int ID) : mode(mode), ID(ID) {
272 if (!validateColorID(ID))
273 {
274 throw BadColorID("Invalid color ID: " + std::to_string(ID));
275 }
276 }
277 };
278
290 std::string col256_2string(std::vector<Col256> codelist) noexcept
291 {
292 if (codelist.empty()) return "";
293 std::string res = "\033[";
294 for (size_t i = 0; i < codelist.size(); i++)
295 {
296 res += std::to_string(static_cast<int>(codelist[i].mode)) + ";5;" + std::to_string(codelist[i].ID);
297 if (i != codelist.size() - 1)
298 {
299 res += ";";
300 }
301 }
302 res += "m";
303 return res;
304 }
305
312 std::string col256_2string(const Col256 &col) noexcept
313 {
314 std::string res = "\033[";
315 res += std::to_string(static_cast<int>(col.mode)) + ";5;";
316 res += std::to_string(col.ID) + "m";
317 return res;
318 }
319
320 // end of Col256_group
321
331 struct ColRGB
332 {
338 int r, g, b;
339
348 explicit ColRGB(ColorMode mode, int r, int g, int b) : mode(mode), r(r), g(g), b(b) {}
349 };
350
362 std::string colrgb_2string(const ColRGB &col) noexcept
363 {
364 std::string res = "\033[";
365 res += std::to_string(static_cast<int>(col.mode)) + ";2;";
366 res += std::to_string(col.r) + ";";
367 res += std::to_string(col.g) + ";";
368 res += std::to_string(col.b) + "m";
369 return res;
370 }
371
372 // end of ColRGB_group
373
383 struct Color
384 {
390 union {
397 };
398
402 explicit Color(Codes col16) : type(ColorType::COL16), col16(col16) {}
406 explicit Color(Col256 col256) : type(ColorType::COL256), col256(col256) {}
410 explicit Color(ColRGB colrgb) : type(ColorType::COLRGB), colrgb(colrgb) {}
411 };
412
417 {
421 std::string text = "";
422
428 std::vector<Color> prestyles = {};
429
435 std::vector<Color> poststyles = {};
436
446 std::vector<Codes> prestyle16 = {};
447
457 std::vector<Codes> poststyle16 = {};
458
468 std::vector<Col256> prestlye256 = {};
469
479 std::vector<Col256> poststyle256 = {};
480 };
481
485 struct Config
486 {
492 bool leading_restore = true;
498 bool trailing_restore = true;
499
505 bool trailing_newline = true;
506 };
507
520
521 // end of Construct_group
522
530 std::map<std::string, PresetConfig> presets = {};
531
535 enum class ParseMode : int
536 {
537 ALL = 0,
538 PREFIX = 1,
539 SUFFIX = 2
540 };
541
548 std::string parseColortype(std::vector<Color> codelist) noexcept
549 {
550 if (codelist.empty()) return "";
551 std::string res = "";
552 for (size_t i = 0; i < codelist.size(); i++)
553 {
554 switch (codelist[i].type)
555 {
556 case ColorType::COL16:
557 res += code2string(codelist[i].col16);
558 break;
559 case ColorType::COL256:
560 res += col256_2string(codelist[i].col256);
561 break;
562 case ColorType::COLRGB:
563 res += colrgb_2string(codelist[i].colrgb);
564 break;
565 default:
566 break;
567 }
568 }
569 return res;
570 }
571
579 std::string parse(const PresetConfig &preset, ParseMode mode = ParseMode::ALL) noexcept
580 {
581 if (mode == ParseMode::PREFIX)
582 {
583 return code2string(preset.prefix.prestyle16)
584 + col256_2string(preset.prefix.prestlye256)
585 + parseColortype(preset.prefix.prestyles)
586 + preset.prefix.text
587 + code2string(preset.prefix.poststyle16)
588 + col256_2string(preset.prefix.poststyle256)
589 + parseColortype(preset.prefix.poststyles);
590 }
591 if (mode == ParseMode::SUFFIX)
592 {
593 return code2string(preset.suffix.prestyle16)
594 + col256_2string(preset.suffix.prestlye256)
595 + parseColortype(preset.suffix.prestyles)
596 + preset.suffix.text
597 + code2string(preset.suffix.poststyle16)
598 + col256_2string(preset.suffix.poststyle256)
599 + parseColortype(preset.suffix.poststyles)
600 + (preset.config.trailing_newline ? "\n" : "");
601 }
602 if (mode == ParseMode::ALL)
603 {
604 return code2string(preset.prefix.prestyle16)
605 + col256_2string(preset.prefix.prestlye256)
606 + parseColortype(preset.prefix.prestyles)
607 + preset.prefix.text
608 + code2string(preset.prefix.poststyle16)
609 + col256_2string(preset.prefix.poststyle256)
610 + parseColortype(preset.prefix.poststyles)
611
612 + code2string(preset.suffix.prestyle16)
613 + col256_2string(preset.suffix.prestlye256)
614 + parseColortype(preset.suffix.prestyles)
615 + preset.suffix.text
616 + code2string(preset.suffix.poststyle16)
617 + col256_2string(preset.suffix.poststyle256)
618 + parseColortype(preset.suffix.poststyles)
619
620 + (preset.config.trailing_newline ? "\n" : "");
621 }
622 return "";
623 }
624
634 void addPreset(std::string name, PresetConfig preset)
635 {
636 if (presets.find(name) != presets.end()) // preset already exists
637 {
638 throw PresetNameUsed(name);
639 }
640
641 if (preset.config.leading_restore)
642 {
643 preset.prefix.prestyles.insert(preset.prefix.prestyles.begin(), Color(Codes::RESTORE));
644 }
645 if (preset.config.trailing_restore)
646 {
647 preset.suffix.poststyles.emplace_back(Color(Codes::RESTORE));
648 }
649
650 presets[name] = std::move(preset);
651 }
652
666 void print(std::string preset, std::string text = "")
667 {
668 if (presets.find(preset) == presets.end())
669 {
670 throw PresetNotFound(preset);
671 }
672 const PresetConfig &config = presets[preset];
673 std::cout << parse(config, ParseMode::PREFIX) << text << parse(config, ParseMode::SUFFIX);
674 }
675
684 {
685 private:
691 const PresetConfig &config;
692
693 public:
694 explicit StyledCout(const PresetConfig &config) : config(config)
695 {
696 std::cout << parse(config, ParseMode::PREFIX);
697 }
698
700 {
701 std::cout << parse(config, ParseMode::SUFFIX);
702 }
703
704 template<typename T>
705 std::ostream& operator<<(const T& value)
706 {
707 return std::cout << value;
708 }
709 };
710
717 StyledCout style(const std::string &preset)
718 {
719 if (presets.find(preset) == presets.end())
720 {
721 throw PresetNotFound(preset);
722 }
723 return StyledCout(presets[preset]);
724 }
725
738 class OnExit
739 {
740 public:
748 {
749 std::cout << code2string<Codes>({Codes::RESTORE});
750 }
751 };
752
753 OnExit onExitInstance;
754
755} // namespace termstyle
756
757#endif // TERMSTYLE_HPP
Definition termstyle.hpp:98
Base class for all exceptions thrown by the library.
Definition termstyle.hpp:54
Thrown when a preset name is already used.
Definition termstyle.hpp:80
Thrown when a preset is not found.
Definition termstyle.hpp:91
The OnExit class is a helper class that performs an action when it goes out of scope.
Definition termstyle.hpp:739
~OnExit()
Destructor for the OnExit class.
Definition termstyle.hpp:747
A class that provides styled output to the standard output stream.
Definition termstyle.hpp:684
Codes
Enum class for ANSI escape codes.
Definition termstyle.hpp:128
std::string code2string(const std::vector< T > &codelist) noexcept
Definition termstyle.hpp:186
bool validateColorID(int ID)
Validates a color 256 ID.
Definition termstyle.hpp:249
std::string col256_2string(std::vector< Col256 > codelist) noexcept
Definition termstyle.hpp:290
std::string colrgb_2string(const ColRGB &col) noexcept
Definition termstyle.hpp:362
void addPreset(std::string name, PresetConfig preset)
Adds a preset with the given name and configuration.
Definition termstyle.hpp:634
void print(std::string preset, std::string text="")
Definition termstyle.hpp:666
StyledCout style(const std::string &preset)
Definition termstyle.hpp:717
Namespace for the termstyle library.
Definition termstyle.hpp:116
std::string parseColortype(std::vector< Color > codelist) noexcept
Definition termstyle.hpp:548
std::map< std::string, PresetConfig > presets
A map that stores preset configurations.
Definition termstyle.hpp:530
ColorMode
Enum class for color modes.
Definition termstyle.hpp:219
ColorType
Enum class for color types.
Definition termstyle.hpp:228
std::string parse(const PresetConfig &preset, ParseMode mode=ParseMode::ALL) noexcept
Definition termstyle.hpp:579
ParseMode
Enum class for parse modes.
Definition termstyle.hpp:536
Struct for storing 256-color codes.
Definition termstyle.hpp:258
ColorMode mode
Definition termstyle.hpp:264
int ID
Definition termstyle.hpp:270
Struct for storing RGB color codes.
Definition termstyle.hpp:332
ColRGB(ColorMode mode, int r, int g, int b)
Constructs a ColRGB object with the specified color mode and RGB values.
Definition termstyle.hpp:348
ColorMode mode
Definition termstyle.hpp:337
Struct for storing different types of colors.
Definition termstyle.hpp:384
ColRGB colrgb
Definition termstyle.hpp:396
Color(Col256 col256)
Constructs a Color object with the specified 256-color code.
Definition termstyle.hpp:406
Codes col16
Definition termstyle.hpp:392
Color(ColRGB colrgb)
Constructs a Color object with the specified RGB color.
Definition termstyle.hpp:410
ColorType type
Definition termstyle.hpp:389
Color(Codes col16)
Constructs a Color object with the specified 16-color code.
Definition termstyle.hpp:402
Col256 col256
Definition termstyle.hpp:394
Configuration namespace.
Definition termstyle.hpp:486
bool trailing_restore
Definition termstyle.hpp:498
bool trailing_newline
Definition termstyle.hpp:505
bool leading_restore
Definition termstyle.hpp:492
Struct for storing preset configurations.
Definition termstyle.hpp:512
Config config
Definition termstyle.hpp:518
StyleString suffix
Definition termstyle.hpp:516
StyleString prefix
Definition termstyle.hpp:514
Struct for storing styled strings.
Definition termstyle.hpp:417
std::vector< Color > prestyles
Definition termstyle.hpp:428
std::vector< Col256 > poststyle256
Definition termstyle.hpp:479
std::vector< Color > poststyles
Definition termstyle.hpp:435
std::vector< Col256 > prestlye256
Definition termstyle.hpp:468
std::string text
Definition termstyle.hpp:421
std::vector< Codes > prestyle16
Definition termstyle.hpp:446
std::vector< Codes > poststyle16
Definition termstyle.hpp:457