| 115 | } |
| 116 | |
| 117 | pub fn render(&self, frame: &mut Frame, area: Rect, theme: &Theme) { |
| 118 | if !self.open || self.filtered.is_empty() { |
| 119 | return; |
| 120 | } |
| 121 | |
| 122 | let width = 50.min(area.width.saturating_sub(4)); |
| 123 | let height = (10.min(self.filtered.len()) as u16).saturating_add(2); |
| 124 | |
| 125 | let x = area.x + (area.width - width) / 2; |
| 126 | let y = area.y.saturating_sub(height + 1); |
| 127 | |
| 128 | let popup_area = Rect::new(x.max(1), y.max(1), width, height); |
| 129 | |
| 130 | let query_line = Line::from(vec![ |
| 131 | Span::raw("/"), |
| 132 | Span::styled(&self.query, Style::default().fg(theme.primary)), |
| 133 | ]); |
| 134 | |
| 135 | let items: Vec<ListItem> = self |
| 136 | .filtered |
| 137 | .iter() |
| 138 | .enumerate() |
| 139 | .map(|(idx, name)| { |
| 140 | let cmd = self.registry.get(name); |
| 141 | let title = cmd.map(|c| c.title.as_str()).unwrap_or(name); |
| 142 | let _desc = cmd.map(|c| c.description.as_str()).unwrap_or(""); |
| 143 | let keybind = cmd.and_then(|c| c.keybind.clone()); |
| 144 | |
| 145 | let is_selected = self.state.selected() == Some(idx); |
| 146 | let style = if is_selected { |
| 147 | Style::default() |
| 148 | .fg(theme.primary) |
| 149 | .bg(theme.background_element) |
| 150 | } else { |
| 151 | Style::default().fg(theme.text) |
| 152 | }; |
| 153 | |
| 154 | let content = if let Some(kb) = keybind { |
| 155 | Line::from(vec![ |
| 156 | Span::styled(title, style), |
| 157 | Span::styled(format!(" ({})", kb), Style::default().fg(theme.text_muted)), |
| 158 | ]) |
| 159 | } else { |
| 160 | Line::from(Span::styled(title, style)) |
| 161 | }; |
| 162 | |
| 163 | ListItem::new(content) |
| 164 | }) |
| 165 | .collect(); |
| 166 | |
| 167 | let list = List::new(items) |
| 168 | .block( |
| 169 | Block::default() |
| 170 | .title(query_line) |
| 171 | .borders(Borders::ALL) |
| 172 | .border_style(Style::default().fg(theme.border)), |
| 173 | ) |
| 174 | .highlight_style(Style::default().fg(theme.primary)); |