use ratatui::style::{Modifier, Style};
use ratatui::text::Span;
use crate::{Diagnostic, DiagnosticSeverity, GutterConfig, GutterSign, VimTheme};
pub fn width(line_count_width: usize, has_diagnostics: bool) -> usize {
let diag_col = if has_diagnostics { 2 } else { 0 };
line_count_width + 2 + diag_col
}
#[allow(clippy::too_many_arguments)]
pub fn render_line<'a>(
line_idx: usize,
cursor_row: usize,
is_cursor_line: bool,
line_count_width: usize,
gutter: &GutterConfig,
has_diagnostics: bool,
has_diff_signs: bool,
theme: &VimTheme,
bg_style: Style,
) -> Vec<Span<'a>> {
let mut spans = Vec::with_capacity(5);
let diag = gutter.diagnostics.get(&line_idx);
let diff = gutter.signs.get(&line_idx);
if has_diagnostics {
let (ch, style) = diag_display(diag, gutter, bg_style);
spans.push(Span::styled(ch, style));
spans.push(Span::styled(" ", bg_style));
}
let line_num = if has_diff_signs {
if is_cursor_line {
format!("{:>width$} ", line_idx + 1, width = line_count_width)
} else {
let distance = line_idx.abs_diff(cursor_row);
format!("{:>width$} ", distance, width = line_count_width)
}
} else {
if is_cursor_line {
format!("{:>width$} ", line_idx + 1, width = line_count_width)
} else {
let distance = line_idx.abs_diff(cursor_row);
format!("{:>width$} ", distance, width = line_count_width)
}
};
let num_style = num_color(diag, diff, gutter, is_cursor_line, theme);
spans.push(Span::styled(line_num, num_style));
if has_diff_signs {
let (ch, style) = diff_display(diff, gutter, bg_style);
spans.push(Span::styled(ch, style));
}
spans
}
pub fn render_tilde<'a>(
line_count_width: usize,
has_diagnostics: bool,
theme: &VimTheme,
bg_style: Style,
) -> Vec<Span<'a>> {
let mut spans = Vec::with_capacity(3);
if has_diagnostics {
spans.push(Span::styled(" ", bg_style));
}
let prefix = format!("{:>width$} ", "~", width = line_count_width);
spans.push(Span::styled(prefix, Style::default().fg(theme.dim)));
spans
}
fn diag_display(
diag: Option<&Diagnostic>,
g: &GutterConfig,
bg_style: Style,
) -> (&'static str, Style) {
match diag.map(|d| &d.severity) {
Some(DiagnosticSeverity::Error) => ("✘", Style::default().fg(g.sign_error)),
Some(DiagnosticSeverity::Warning) => ("⚠", Style::default().fg(g.sign_warning)),
None => (" ", bg_style),
}
}
fn diff_display(
diff: Option<&GutterSign>,
g: &GutterConfig,
bg_style: Style,
) -> (&'static str, Style) {
match diff {
Some(GutterSign::Added) => ("│", Style::default().fg(g.sign_added)),
Some(GutterSign::Modified) => ("│", Style::default().fg(g.sign_modified)),
Some(GutterSign::DeletedAbove) => ("▲", Style::default().fg(g.sign_deleted)),
Some(GutterSign::DeletedBelow) => ("▼", Style::default().fg(g.sign_deleted)),
None => (" ", bg_style),
}
}
fn num_color(
diag: Option<&Diagnostic>,
diff: Option<&GutterSign>,
g: &GutterConfig,
is_cursor_line: bool,
theme: &VimTheme,
) -> Style {
if let Some(d) = diag {
return match d.severity {
DiagnosticSeverity::Error => Style::default().fg(g.sign_error),
DiagnosticSeverity::Warning => Style::default().fg(g.sign_warning),
};
}
if let Some(s) = diff {
match s {
GutterSign::Added => return Style::default().fg(g.sign_added),
GutterSign::Modified => return Style::default().fg(g.sign_modified),
_ => {}
}
}
if is_cursor_line {
Style::default().fg(theme.line_nr_active).add_modifier(Modifier::BOLD)
} else {
Style::default().fg(theme.line_nr)
}
}