2 use termcolor
::{ColorSpec, WriteColor}
;
4 use crate::diagnostic
::Severity
;
5 use crate::term
::Config
;
14 pub fn label_style
<'config
>(self, config
: &'config Config
) -> &'config ColorSpec
{
16 MarkStyle
::Primary(severity
) => config
.styles
.primary_label(severity
),
17 MarkStyle
::Secondary
=> &config
.styles
.secondary_label
,
21 pub fn caret_char(self, config
: &Config
) -> char {
23 MarkStyle
::Primary(_
) => config
.chars
.primary_caret
,
24 MarkStyle
::Secondary
=> config
.chars
.secondary_caret
,
28 pub fn multiline_caret_char(self, config
: &Config
) -> char {
30 MarkStyle
::Primary(_
) => config
.chars
.multiline_primary_caret
,
31 MarkStyle
::Secondary
=> config
.chars
.multiline_secondary_caret
,
36 /// The underline of a single source line.
39 /// ^^ expected `Int` but found `String`
41 pub struct Underline
<'a
> {
42 mark_style
: MarkStyle
,
43 prefix_source
: &'a
str,
44 highlighted_source
: &'a
str,
48 impl<'a
> Underline
<'a
> {
50 mark_style
: MarkStyle
,
51 prefix_source
: &'a
str,
52 highlighted_source
: &'a
str,
63 pub fn emit(&self, writer
: &mut impl WriteColor
, config
: &Config
) -> io
::Result
<()> {
64 let prefix_len
= config
.width(self.prefix_source
);
65 write
!(writer
, " {space: >width$}", space
= "", width
= prefix_len
)?
;
67 writer
.set_color(self.mark_style
.label_style(config
))?
;
68 // We use `usize::max` here to ensure that we print at least one
69 // underline character - even when we have a zero-length span.
70 let underline_len
= usize::max(config
.width(self.highlighted_source
), 1);
71 for _
in 0..underline_len
{
72 write
!(writer
, "{}", self.mark_style
.caret_char(config
))?
;
74 if !self.message
.is_empty() {
75 write
!(writer
, " {}", self.message
)?
;
83 /// The top-left of a multi-line underline.
88 pub struct UnderlineTopLeft
{
89 mark_style
: MarkStyle
,
92 impl UnderlineTopLeft
{
93 pub fn new(mark_style
: MarkStyle
) -> UnderlineTopLeft
{
94 UnderlineTopLeft { mark_style }
97 pub fn emit(&self, writer
: &mut impl WriteColor
, config
: &Config
) -> io
::Result
<()> {
100 writer
.set_color(self.mark_style
.label_style(config
))?
;
101 write
!(writer
, "{}", config
.chars
.multiline_top_left
)?
;
108 /// The top of a multi-line underline.
113 pub struct UnderlineTop
<'a
> {
114 mark_style
: MarkStyle
,
115 prefix_source
: &'a
str,
118 impl<'a
> UnderlineTop
<'a
> {
119 pub fn new(mark_style
: MarkStyle
, prefix_source
: &'a
str) -> UnderlineTop
<'a
> {
126 pub fn emit(&self, writer
: &mut impl WriteColor
, config
: &Config
) -> io
::Result
<()> {
127 write
!(writer
, " ")?
;
129 writer
.set_color(self.mark_style
.label_style(config
))?
;
130 write
!(writer
, "{}", config
.chars
.multiline_top_left
)?
;
131 let underline_len
= config
.width(self.prefix_source
) + 1;
132 for _
in 0..underline_len
{
133 write
!(writer
, "{}", config
.chars
.multiline_top
)?
;
135 write
!(writer
, "{}", self.mark_style
.multiline_caret_char(config
))?
;
142 /// The left of a multi-line underline.
143 pub struct UnderlineLeft
{
144 mark_style
: MarkStyle
,
148 pub fn new(mark_style
: MarkStyle
) -> UnderlineLeft
{
149 UnderlineLeft { mark_style }
152 pub fn emit(&self, writer
: &mut impl WriteColor
, config
: &Config
) -> io
::Result
<()> {
153 write
!(writer
, " ")?
;
154 writer
.set_color(self.mark_style
.label_style(config
))?
;
155 write
!(writer
, "{}", config
.chars
.multiline_left
)?
;
162 /// The bottom of a multi-line underline.
165 /// ╰──────────────^ `case` clauses have incompatible types
167 pub struct UnderlineBottom
<'a
> {
168 mark_style
: MarkStyle
,
169 highlighted_source
: &'a
str,
173 impl<'a
> UnderlineBottom
<'a
> {
175 mark_style
: MarkStyle
,
176 highlighted_source
: &'a
str,
178 ) -> UnderlineBottom
<'a
> {
186 pub fn emit(&self, writer
: &mut impl WriteColor
, config
: &Config
) -> io
::Result
<()> {
187 write
!(writer
, " ")?
;
189 writer
.set_color(self.mark_style
.label_style(config
))?
;
190 write
!(writer
, "{}", config
.chars
.multiline_bottom_left
)?
;
191 let width
= config
.width(self.highlighted_source
);
193 write
!(writer
, "{}", config
.chars
.multiline_bottom
)?
;
195 write
!(writer
, "{}", self.mark_style
.multiline_caret_char(config
))?
;
196 if !self.message
.is_empty() {
197 write
!(writer
, " {}", self.message
)?
;