use crate::keymap;
use crate::mode::Mode;
use crate::theme::{Semantic, Theme};
use ratatui::Frame;
use ratatui::layout::Rect;
use ratatui::style::{Color, Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::Paragraph;
pub(crate) fn mode_color(mode: Mode, sem: &Semantic) -> Color {
match mode {
Mode::Browse => sem.mode_browse,
Mode::Search | Mode::Find => sem.mode_search,
Mode::Insert => sem.mode_insert,
Mode::Normal => sem.mode_normal,
Mode::Leader => sem.mode_leader,
Mode::Visual => sem.mode_visual,
}
}
pub struct Modeline {
pub context: String,
pub status: Option<String>,
}
impl Default for Modeline {
fn default() -> Self {
Self::new()
}
}
impl Modeline {
pub fn new() -> Modeline {
Modeline {
context: String::new(),
status: None,
}
}
pub fn render(&self, frame: &mut Frame, area: Rect, mode: Mode, theme: &Theme) {
let sem = &theme.semantic;
let chip_bg = mode_color(mode, sem);
let mut spans = vec![
Span::styled(
format!(" {} ", mode.chip()),
Style::default()
.fg(sem.crust)
.bg(chip_bg)
.add_modifier(Modifier::BOLD),
),
Span::styled(" ", Style::default().bg(sem.mantle)),
];
if let Some(status) = &self.status {
spans.push(Span::styled(
format!(" {status} "),
Style::default().fg(sem.warning).bg(sem.mantle),
));
}
spans.push(Span::styled(
format!(" {} ", self.context),
Style::default().fg(sem.subtext0).bg(sem.mantle),
));
let hint_text: Vec<Span> = keymap::hints(mode)
.iter()
.flat_map(|(k, desc)| {
[
Span::styled(
format!(" {k}"),
Style::default()
.fg(sem.text)
.bg(sem.mantle)
.add_modifier(Modifier::BOLD),
),
Span::styled(
format!(" {desc} ·"),
Style::default().fg(sem.hint).bg(sem.mantle),
),
]
.into_iter()
})
.collect();
let used: usize = spans.iter().map(|s| s.content.width()).sum::<usize>()
+ hint_text.iter().map(|s| s.content.width()).sum::<usize>();
let pad = (area.width as usize).saturating_sub(used);
spans.push(Span::styled(
" ".repeat(pad),
Style::default().bg(sem.mantle),
));
spans.extend(hint_text);
frame.render_widget(Paragraph::new(Line::from(spans)), area);
}
}
use unicode_width::UnicodeWidthStr;