use crate::theme::Theme;
use ratatui::{
layout::Rect,
text::{Line, Span},
widgets::{Block, Borders, Paragraph, Wrap},
Frame,
};
pub struct ShellPanel {
pub command: String,
pub cursor: usize,
pub history: Vec<String>,
pub history_pos: Option<usize>,
}
impl ShellPanel {
pub fn new() -> Self {
Self {
command: String::new(),
cursor: 0,
history: Vec::new(),
history_pos: None,
}
}
pub fn insert_char(&mut self, c: char) {
self.command.insert(self.cursor, c);
self.cursor += 1;
}
pub fn delete_char(&mut self) {
if self.cursor > 0 {
self.command.remove(self.cursor - 1);
self.cursor -= 1;
}
}
pub fn move_left(&mut self) {
if self.cursor > 0 {
self.cursor -= 1;
}
}
pub fn move_right(&mut self) {
if self.cursor < self.command.len() {
self.cursor += 1;
}
}
pub fn clear(&mut self) {
self.command.clear();
self.cursor = 0;
}
pub fn get_command(&self) -> &str {
&self.command
}
pub fn render(&self, frame: &mut Frame, area: Rect, focused: bool, theme: &Theme) {
let border_style = if focused {
theme.style_border_focused()
} else {
theme.style_border()
};
let title = if focused {
" Shell (Active) "
} else {
" Shell "
};
let block = Block::default()
.title(title)
.borders(Borders::ALL)
.border_style(border_style);
let prompt = Span::styled("$ ", theme.style_accent());
let command_text = Span::styled(&self.command, theme.style_normal());
let mut line = vec![prompt, command_text];
if focused {
line.push(Span::styled("█", theme.style_accent()));
}
let paragraph = Paragraph::new(Line::from(line))
.block(block)
.wrap(Wrap { trim: false });
frame.render_widget(paragraph, area);
}
}
impl Default for ShellPanel {
fn default() -> Self {
Self::new()
}
}