Porytiles
Loading...
Searching...
No Matches
stderr_styled_user_diagnostics.cpp
Go to the documentation of this file.
2
3#include <cstddef>
4#include <iostream>
5#include <string>
6#include <vector>
7
11
12namespace {
13
14using namespace porytiles;
15
16// The gutter "│ " that prefixes every body line occupies two visible columns.
17constexpr std::size_t gutter_columns = 2;
18
25void print_body(
26 const TextFormatter &fmt, const Style style, const std::vector<std::string> &lines, const std::size_t wrap_width)
27{
28 const std::size_t body_width =
29 wrap_width == 0 ? 0 : (wrap_width > gutter_columns ? wrap_width - gutter_columns : 1);
30 const std::string gutter = fmt.style("│", style);
31 for (const auto &logical : lines) {
32 for (const auto &physical : wrap_ansi_line(logical, body_width)) {
33 std::cerr << gutter << " " << physical << std::endl;
34 }
35 }
36}
37
38} // namespace
39
40namespace porytiles {
41
42void StderrStyledUserDiagnostics::remark(const std::string &tag, const std::vector<std::string> &lines) const
43{
44 assert_or_panic(!lines.empty(), "lines vector is empty");
45 assert_or_panic(!tag.empty(), "tag is empty");
46
47 std::cerr << formatter().style("remark ", Style::bold | Style::blue)
49 << formatter().style("]:", Style::bold | Style::blue) << std::endl;
50 std::cerr << formatter().style("│", Style::bold | Style::blue) << std::endl;
51 print_body(formatter(), Style::bold | Style::blue, lines, wrap_width_);
52 std::cerr << formatter().style("│", Style::bold | Style::blue) << std::endl;
53}
54
55void StderrStyledUserDiagnostics::warning(const std::string &tag, const std::vector<std::string> &lines) const
56{
57 assert_or_panic(!lines.empty(), "lines vector is empty");
58 assert_or_panic(!tag.empty(), "tag is empty");
59
60 std::cerr << formatter().style("warning ", Style::bold | Style::magenta)
63 << formatter().style("]:", Style::bold | Style::magenta) << std::endl;
64 std::cerr << formatter().style("│", Style::bold | Style::magenta) << std::endl;
65 print_body(formatter(), Style::bold | Style::magenta, lines, wrap_width_);
66 std::cerr << formatter().style("│", Style::bold | Style::magenta) << std::endl;
67}
68
69void StderrStyledUserDiagnostics::error(const std::string &tag, const std::vector<std::string> &lines) const
70{
71 assert_or_panic(!lines.empty(), "lines vector is empty");
72 assert_or_panic(!tag.empty(), "tag is empty");
73
74 std::cerr << formatter().style("error ", Style::bold | Style::red)
76 << formatter().style("]:", Style::bold | Style::red) << std::endl;
77 std::cerr << formatter().style("│", Style::bold | Style::red) << std::endl;
78 print_body(formatter(), Style::bold | Style::red, lines, wrap_width_);
79 std::cerr << formatter().style("│", Style::bold | Style::red) << std::endl;
80}
81
83{
84 auto lines = err.details(formatter());
85 if (!lines.empty()) {
86 std::cerr << formatter().style("fatal:", Style::bold | Style::red) << std::endl;
87 std::cerr << formatter().style("│", Style::bold | Style::red) << std::endl;
88 print_body(formatter(), Style::bold | Style::red, lines, wrap_width_);
89 std::cerr << formatter().style("│", Style::bold | Style::red) << std::endl;
90 }
91}
92
94{
95 std::cerr << formatter().style("├ caused by:", Style::bold | Style::red) << std::endl;
96 std::cerr << formatter().style("│", Style::bold | Style::red) << " " << std::endl;
97
98 auto lines = err.details(formatter());
99 if (!lines.empty()) {
100 print_body(formatter(), Style::bold | Style::red, lines, wrap_width_);
101 }
102 std::cerr << formatter().style("│", Style::bold | Style::red) << std::endl;
103}
104
106{
107 std::cerr << formatter().style("├ root cause:", Style::bold | Style::red) << std::endl;
108 std::cerr << formatter().style("│", Style::bold | Style::red) << " " << std::endl;
109
110 auto lines = err.details(formatter());
111 if (!lines.empty()) {
112 print_body(formatter(), Style::bold | Style::red, lines, wrap_width_);
113 }
114 std::cerr << formatter().style("│", Style::bold | Style::red) << std::endl;
115}
116
117void StderrStyledUserDiagnostics::remark_note(const std::string &tag, const std::vector<std::string> &lines) const
118{
119 emit_note_impl(tag, lines);
120}
121
122void StderrStyledUserDiagnostics::warning_note(const std::string &tag, const std::vector<std::string> &lines) const
123{
124 emit_note_impl(tag, lines);
125}
126
127void StderrStyledUserDiagnostics::error_note(const std::string &tag, const std::vector<std::string> &lines) const
128{
129 emit_note_impl(tag, lines);
130}
131
132void StderrStyledUserDiagnostics::emit_note_impl(const std::string &tag, const std::vector<std::string> &lines) const
133{
134 assert_or_panic(!lines.empty(), "lines vector is empty");
135 assert_or_panic(!tag.empty(), "tag is empty");
136
137 std::cerr << formatter().style("note ", Style::bold | Style::cyan)
139 << formatter().style("]:", Style::bold | Style::cyan) << std::endl;
140 std::cerr << formatter().style("│", Style::bold | Style::cyan) << std::endl;
141 print_body(formatter(), Style::bold | Style::cyan, lines, wrap_width_);
142 std::cerr << formatter().style("│", Style::bold | Style::cyan) << std::endl;
143}
144
145} // namespace porytiles
Abstract interface for all error types used in ChainableResult error chains.
Definition error.hpp:17
virtual std::vector< std::string > details(const TextFormatter &formatter) const =0
Returns a formatted multi-line string representation of the error.
void error(const std::string &tag, const std::vector< std::string > &lines) const override
Display a multi-line tagged error message to stderr.
void warning_note(const std::string &tag, const std::vector< std::string > &lines) const override
Display a multi-line tagged note associated with a warning to stderr.
void emit_fatal_proximate(const Error &err) const override
Emit the proximate (immediate) error in a fatal error chain to stderr.
void remark(const std::string &tag, const std::vector< std::string > &lines) const override
Display a multi-line tagged informational remark to stderr.
void remark_note(const std::string &tag, const std::vector< std::string > &lines) const override
Display a multi-line tagged note associated with a remark to stderr.
void emit_fatal_root(const Error &err) const override
Emit the root cause error in a fatal error chain to stderr.
void emit_fatal_step(const Error &err) const override
Emit an intermediate step error in a fatal error chain to stderr.
void warning(const std::string &tag, const std::vector< std::string > &lines) const override
Display a multi-line tagged warning to stderr.
void error_note(const std::string &tag, const std::vector< std::string > &lines) const override
Display a multi-line tagged note associated with an error to stderr.
Text styling class supporting formatting, foreground colors, and background colors.
static const Style magenta
Magenta foreground color.
static const Style red
Red foreground color.
static const Style cyan
Cyan foreground color.
static const Style blue
Blue foreground color.
static const Style bold
Bold text formatting.
Abstract base class for applying text styling with context-aware formatting.
virtual std::string style(const std::string &text, Style styles) const =0
Applies styling to a text string.
const TextFormatter & formatter() const
void assert_or_panic(bool condition, const StringViewSourceLoc &s)
Conditionally panics if the given condition is false.
Definition panic.cpp:53
std::vector< std::string > wrap_ansi_line(const std::string &line, std::size_t width)
Word-wraps a single logical line to a visible column width, preserving ANSI styling.