use ratatui::style::{Color, Style};
use ratatui::text::{Line, Span};
use std::collections::HashMap;
use crate::app::App;
use crate::lsp::Severity;
use super::{GUTTER_SIGN_WIDTH, GUTTER_VCS_WIDTH};
pub(super) fn build_row_severity(
app: &App,
scroll: usize,
last: usize,
) -> std::collections::HashMap<usize, Severity> {
let mut map: std::collections::HashMap<usize, Severity> = std::collections::HashMap::new();
let diags = match app.current_diagnostics() {
Some(d) => d,
None => return map,
};
for d in diags {
let lo = d.range.start.line as usize;
let hi = d.range.end.line as usize;
for row in lo.max(scroll)..=hi.min(last.saturating_sub(1)) {
map.entry(row)
.and_modify(|s| {
if (d.severity as u8) < (*s as u8) {
*s = d.severity;
}
})
.or_insert(d.severity);
}
}
map
}
pub(super) struct RowDiag {
pub severity: Severity,
pub message: String,
pub extra: usize,
}
pub(super) fn build_row_diag_summary(app: &App, cursor_row: usize) -> HashMap<usize, RowDiag> {
let mut out: HashMap<usize, RowDiag> = HashMap::new();
let Some(diags) = app.current_diagnostics() else {
return out;
};
for d in diags {
let row = d.range.start.line as usize;
if row != cursor_row && d.severity != Severity::Error {
continue;
}
let msg = d.message.lines().next().unwrap_or("").to_string();
match out.get_mut(&row) {
None => {
out.insert(
row,
RowDiag {
severity: d.severity,
message: msg,
extra: 0,
},
);
}
Some(existing) => {
if (d.severity as u8) < (existing.severity as u8) {
existing.severity = d.severity;
existing.message = msg;
}
existing.extra += 1;
}
}
}
out
}
pub(super) fn diagnostic_line(diag: &RowDiag, inner_text_width: usize) -> Line<'static> {
let color = severity_color(diag.severity);
let gutter = " ".repeat((GUTTER_SIGN_WIDTH + 5 + GUTTER_VCS_WIDTH) as usize);
let mut text = String::from("↳ ");
text.push_str(&diag.message);
if diag.extra > 0 {
text.push_str(&format!(" (+{})", diag.extra));
}
if inner_text_width > 0 && text.chars().count() > inner_text_width {
let mut t: String = text
.chars()
.take(inner_text_width.saturating_sub(1))
.collect();
t.push('…');
text = t;
}
Line::from(vec![
Span::raw(gutter),
Span::styled(
text,
Style::default()
.fg(color)
.add_modifier(ratatui::style::Modifier::ITALIC),
),
])
}
pub(super) fn severity_color(sev: Severity) -> Color {
match sev {
Severity::Error => Color::Red,
Severity::Warning => Color::Yellow,
Severity::Info => Color::LightBlue,
Severity::Hint => Color::DarkGray,
}
}