use ratatui::{
Frame,
layout::{Margin, Rect},
style::{Modifier, Style},
text::{Line, Span},
widgets::{Block, Borders, Scrollbar, ScrollbarOrientation, ScrollbarState},
};
use crate::tui::theme::TuiTheme;
pub(crate) fn pane_block(title: &str, theme: &TuiTheme, focused: bool) -> Block<'static> {
pane_block_titled(Line::from(title.to_string()), theme, focused)
}
pub(crate) fn pane_block_titled(
title: Line<'static>,
theme: &TuiTheme,
focused: bool,
) -> Block<'static> {
let border_style = if focused {
theme.border_active
} else {
theme.border
};
Block::default()
.title(title)
.borders(Borders::ALL)
.border_style(border_style)
}
pub(crate) fn render_scrollbar(
frame: &mut Frame,
area: Rect,
total: usize,
viewport: usize,
position: usize,
) {
if total <= viewport {
return;
}
let max_pos = total - viewport;
let mut state = ScrollbarState::new(max_pos + 1)
.position(position.min(max_pos))
.viewport_content_length(viewport);
frame.render_stateful_widget(
Scrollbar::new(ScrollbarOrientation::VerticalRight)
.begin_symbol(None)
.end_symbol(None)
.track_symbol(None),
area.inner(Margin {
horizontal: 0,
vertical: 1,
}),
&mut state,
);
}
pub(crate) fn colorize_diff(text: &str, theme: &TuiTheme) -> Vec<Line<'static>> {
let mut in_header = text.starts_with("commit ");
text.lines()
.map(|raw| {
if in_header && raw.starts_with("diff --git") {
in_header = false;
}
let style = if in_header {
if raw.starts_with("commit ") {
theme.dim
} else {
Style::default()
}
} else {
diff_line_style(raw, theme)
};
Line::from(Span::styled(raw.to_string(), style))
})
.collect()
}
pub(crate) fn diff_line_style(line: &str, theme: &TuiTheme) -> Style {
if line.starts_with("+++") || line.starts_with("---") || line.starts_with("diff --git") {
theme.message.add_modifier(Modifier::BOLD)
} else if line.starts_with("index ") {
theme.dim
} else if line.starts_with('+') {
theme.added
} else if line.starts_with('-') {
theme.removed
} else if line.starts_with("@@") {
theme.hunk_header
} else {
theme.context
}
}
pub(crate) fn hunk_line_style(line: &str, theme: &TuiTheme) -> Style {
if line.starts_with('+') {
theme.added
} else if line.starts_with('-') {
theme.removed
} else if line.starts_with("@@") {
theme.hunk_header
} else {
theme.context
}
}