use std::path::PathBuf;
#[derive(Debug, Clone)]
pub struct TemplateFile {
pub name: String,
pub path: PathBuf,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ActiveList {
Default,
Custom,
}
#[derive(Debug, Clone)]
pub struct PickerState {
pub default_templates: Vec<TemplateFile>,
pub custom_templates: Vec<TemplateFile>,
pub active_list: ActiveList,
pub default_cursor: usize,
pub custom_cursor: usize,
}
impl Default for PickerState {
fn default() -> Self {
let mut state = Self {
default_templates: Vec::new(),
custom_templates: Vec::new(),
active_list: ActiveList::Default,
default_cursor: 0,
custom_cursor: 0,
};
state.load_all_templates();
state
}
}
impl PickerState {
pub fn load_all_templates(&mut self) {
self.load_default_templates();
self.load_custom_templates();
}
fn load_default_templates(&mut self) {
self.default_templates.clear();
let builtin_templates = code2prompt_core::builtin_templates::BuiltinTemplates::get_all();
let mut template_entries: Vec<_> = builtin_templates.iter().collect();
template_entries.sort_by(|a, b| a.1.name.cmp(b.1.name));
for (key, template) in template_entries {
self.default_templates.push(TemplateFile {
name: template.name.to_string(),
path: PathBuf::from(format!("builtin://{}", key)),
});
}
}
fn load_custom_templates(&mut self) {
self.custom_templates.clear();
if let Ok(all_templates) = crate::utils::load_all_templates() {
for (name, path) in all_templates {
self.custom_templates.push(TemplateFile {
name,
path: PathBuf::from(path),
});
}
}
}
pub fn move_cursor_up(&mut self) {
let total_items = self.get_total_selectable_items();
if total_items == 0 {
return;
}
let current_global = self.get_global_template_index();
let new_global = if current_global == 0 {
total_items - 1 } else {
current_global - 1
};
self.set_cursor_from_global_position(new_global);
}
pub fn move_cursor_down(&mut self) {
let total_items = self.get_total_selectable_items();
if total_items == 0 {
return;
}
let current_global = self.get_global_template_index();
let new_global = (current_global + 1) % total_items;
self.set_cursor_from_global_position(new_global);
}
pub fn refresh(&mut self) {
self.load_all_templates();
if self.default_cursor >= self.default_templates.len() {
self.default_cursor = self.default_templates.len().saturating_sub(1);
}
if self.custom_cursor >= self.custom_templates.len() {
self.custom_cursor = self.custom_templates.len().saturating_sub(1);
}
}
pub fn get_global_cursor_position(&self) -> usize {
let mut position = 0;
if !self.default_templates.is_empty() {
position += 1; if self.active_list == ActiveList::Default {
position += self.default_cursor;
return position;
}
position += self.default_templates.len();
}
if !self.custom_templates.is_empty() {
if !self.default_templates.is_empty() {
position += 1; }
position += 1; if self.active_list == ActiveList::Custom {
position += self.custom_cursor;
return position;
}
}
position
}
fn get_global_template_index(&self) -> usize {
match self.active_list {
ActiveList::Default => self.default_cursor,
ActiveList::Custom => self.default_templates.len() + self.custom_cursor,
}
}
fn get_total_selectable_items(&self) -> usize {
self.default_templates.len() + self.custom_templates.len()
}
fn set_cursor_from_global_position(&mut self, global_pos: usize) {
let mut template_index = 0;
if global_pos < self.default_templates.len() {
self.active_list = ActiveList::Default;
self.default_cursor = global_pos;
return;
}
template_index += self.default_templates.len();
if global_pos < template_index + self.custom_templates.len() {
self.active_list = ActiveList::Custom;
self.custom_cursor = global_pos - template_index;
}
}
}