use std::fmt::{self, Write};
use owo_colors::OwoColorize;
use super::{
handler::GraphicalReportHandler,
label::write_repeated_char,
line::Line,
span::{FancySpan, LabelRenderMode},
};
impl GraphicalReportHandler {
pub(super) fn write_linum(
&self,
f: &mut impl fmt::Write,
width: usize,
linum: usize,
) -> fmt::Result {
f.write_char(' ')?;
if self.theme.styles.linum.is_plain() {
write!(f, "{linum:width$}")?;
} else {
write!(f, "{:width$}", linum.style(self.theme.styles.linum), width = width)?;
}
f.write_char(' ')?;
f.write_char(self.theme.characters.vbar)?;
f.write_char(' ')
}
pub(super) fn write_no_linum(&self, f: &mut impl fmt::Write, width: usize) -> fmt::Result {
write_repeated_char(f, ' ', width + 2)?;
f.write_char(self.theme.characters.vbar_break)?;
f.write_char(' ')
}
pub(super) fn render_line_gutter(
&self,
f: &mut impl fmt::Write,
max_gutter: usize,
line: &Line<'_>,
highlights: &[FancySpan],
) -> fmt::Result {
if max_gutter == 0 {
return Ok(());
}
let chars = &self.theme.characters;
let mut gutter = String::new();
let applicable = highlights.iter().filter(|hl| line.span_applies_gutter(hl));
let mut arrow = false;
for (i, hl) in applicable.enumerate() {
if line.span_starts(hl) {
write!(gutter, "{}", chars.ltop.style(hl.style))?;
write!(
gutter,
"{}",
chars.hbar.to_string().repeat(max_gutter.saturating_sub(i)).style(hl.style)
)?;
write!(gutter, "{}", chars.rarrow.style(hl.style))?;
arrow = true;
break;
} else if line.span_ends(hl) {
if hl.has_label() {
write!(gutter, "{}", chars.lcross.style(hl.style))?;
} else {
write!(gutter, "{}", chars.lbot.style(hl.style))?;
}
write!(
gutter,
"{}",
chars.hbar.to_string().repeat(max_gutter.saturating_sub(i)).style(hl.style)
)?;
write!(gutter, "{}", chars.rarrow.style(hl.style))?;
arrow = true;
break;
} else if line.span_flyby(hl) {
write!(gutter, "{}", chars.vbar.style(hl.style))?;
} else {
gutter.push(' ');
}
}
write!(
f,
"{}{}",
gutter,
" ".repeat(
if arrow { 1 } else { 3 } + max_gutter.saturating_sub(gutter.chars().count())
)
)?;
Ok(())
}
pub(super) fn render_highlight_gutter(
&self,
f: &mut impl fmt::Write,
max_gutter: usize,
line: &Line<'_>,
highlights: &[FancySpan],
render_mode: LabelRenderMode,
) -> fmt::Result {
if max_gutter == 0 {
return Ok(());
}
let mut gutter_cols = 0;
let chars = &self.theme.characters;
let mut gutter = String::new();
let applicable = highlights.iter().filter(|hl| line.span_applies_gutter(hl));
for (i, hl) in applicable.enumerate() {
if !line.span_line_only(hl) && line.span_ends(hl) {
if render_mode == LabelRenderMode::BlockRest {
let horizontal_space = max_gutter.saturating_sub(i) + 2;
for _ in 0..horizontal_space {
gutter.push(' ');
}
gutter_cols += horizontal_space + 1;
} else {
let num_repeat = max_gutter.saturating_sub(i) + 2;
write!(gutter, "{}", chars.lbot.style(hl.style))?;
write!(
gutter,
"{}",
chars
.hbar
.to_string()
.repeat(
num_repeat
- usize::from(render_mode == LabelRenderMode::BlockFirst),
)
.style(hl.style)
)?;
gutter_cols += num_repeat + 1;
}
break;
}
write!(gutter, "{}", chars.vbar.style(hl.style))?;
gutter_cols += 1;
}
let num_spaces = (max_gutter + 3).saturating_sub(gutter_cols);
write!(f, "{}{:width$}", gutter, "", width = num_spaces)?;
Ok(())
}
}