use ratatui::buffer::Buffer as Surface;
use ratatui::layout::Rect;
use ratatui::text::{Line, Span};
use ratatui::widgets::Widget;
use unicode_width::UnicodeWidthStr;
use crate::theme::Theme;
pub struct SearchBox<'a> {
pub query: &'a str,
pub forward: bool,
pub error: Option<&'a str>,
pub theme: &'a Theme,
}
impl SearchBox<'_> {
const fn sigil(&self) -> &'static str {
if self.forward { "/" } else { "?" }
}
#[must_use]
pub fn caret_position(&self, area: Rect) -> (u16, u16) {
let column = u16::try_from(self.query.width()).unwrap_or(u16::MAX);
(
area.x
.saturating_add(1 + column)
.min(area.right().saturating_sub(1)),
area.y,
)
}
}
impl Widget for SearchBox<'_> {
fn render(self, area: Rect, surface: &mut Surface) {
if area.is_empty() {
return;
}
surface.set_style(area, self.theme.command);
let mut spans = vec![
Span::styled(self.sigil(), self.theme.command),
Span::styled(self.query, self.theme.command),
];
if let Some(error) = self.error {
spans.push(Span::styled(
format!(" {error}"),
self.theme.command.patch(self.theme.command_error),
));
}
Line::from(spans).render(area, surface);
}
}