use crate::app::App;
use crate::input::CommandDef;
use ratatui::layout::{Alignment, Constraint, Direction, Layout, Rect};
use ratatui::style::{Color, Modifier, Style};
use ratatui::text::{Line, Span};
use ratatui::widgets::{Block, Borders, Clear, Paragraph};
use ratatui::Frame;
pub fn render(f: &mut Frame, area: Rect, app: &App) {
let input = &app.command_input;
let matches = app.command_registry.find_matches(input);
if matches.is_empty() {
return;
}
let completion_height = 3.min(area.height / 3);
let completion_area = Rect {
x: area.x,
y: area.height.saturating_sub(completion_height),
width: area.width,
height: completion_height,
};
render_command_list(f, completion_area, &matches);
if matches.len() == 1 || (!input.is_empty() && matches.iter().any(|cmd| cmd.name == input || cmd.aliases.contains(&input.as_str()))) {
let cmd = matches[0];
render_command_detail(f, area, cmd);
}
}
fn render_command_list(f: &mut Frame, area: Rect, commands: &[&CommandDef]) {
f.render_widget(Clear, area);
let bg_block = Block::default()
.style(Style::default().bg(Color::Rgb(30, 30, 30)));
f.render_widget(bg_block, area);
let column_width = 20;
let columns = (area.width as usize / column_width).max(1).min(5);
let max_rows = (area.height.saturating_sub(0)) as usize;
let max_commands = columns * max_rows;
let display_commands = &commands[..commands.len().min(max_commands)];
let mut lines = Vec::new();
let rows = (display_commands.len() + columns - 1) / columns;
for row in 0..rows {
let mut spans = Vec::new();
for col in 0..columns {
let idx = row + col * rows;
if idx < display_commands.len() {
let cmd = display_commands[idx];
let display_name = if cmd.aliases.is_empty() {
cmd.name
} else {
cmd.aliases[0]
};
spans.push(Span::styled(
format!("{:<width$}", display_name, width = column_width - 1),
Style::default().fg(Color::Rgb(136, 192, 208)),
));
} else {
spans.push(Span::raw(" ".repeat(column_width)));
}
}
lines.push(Line::from(spans));
}
let paragraph = Paragraph::new(lines).alignment(Alignment::Left);
f.render_widget(paragraph, area);
}
fn render_command_detail(f: &mut Frame, area: Rect, cmd: &CommandDef) {
let popup_width = 60.min(area.width.saturating_sub(4));
let popup_height = 6;
let popup_area = Rect {
x: (area.width.saturating_sub(popup_width)) / 2,
y: (area.height.saturating_sub(popup_height)) / 2,
width: popup_width,
height: popup_height,
};
f.render_widget(Clear, popup_area);
let mut lines = Vec::new();
lines.push(Line::from(vec![
Span::styled(
cmd.name,
Style::default()
.fg(Color::Rgb(136, 192, 208))
.add_modifier(Modifier::BOLD),
),
]));
lines.push(Line::from(""));
lines.push(Line::from(vec![
Span::styled(cmd.description, Style::default().fg(Color::White)),
]));
if !cmd.aliases.is_empty() {
lines.push(Line::from(""));
let aliases_str = format!("Aliases: {}", cmd.aliases.join(", "));
lines.push(Line::from(vec![
Span::styled(aliases_str, Style::default().fg(Color::Gray)),
]));
}
let paragraph = Paragraph::new(lines)
.block(
Block::default()
.borders(Borders::ALL)
.border_style(Style::default().fg(Color::Rgb(136, 192, 208)))
.border_type(ratatui::widgets::BorderType::Rounded)
.style(Style::default().bg(Color::Rgb(40, 40, 40))),
)
.alignment(Alignment::Left);
f.render_widget(paragraph, popup_area);
}