vtcode_tui/core_tui/session/
palette.rs1use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
9use std::path::PathBuf;
10
11use super::{
12 Session,
13 file_palette::{FilePalette, extract_file_reference},
14};
15use crate::ui::tui::session::slash;
16
17impl Session {
18 pub(super) fn load_file_palette(&mut self, files: Vec<String>, workspace: PathBuf) {
20 let mut palette = FilePalette::new(workspace);
21 palette.load_files(files);
22 self.file_palette = Some(palette);
23 self.file_palette_active = false;
24 self.check_file_reference_trigger();
25 }
26
27 pub fn check_file_reference_trigger(&mut self) {
29 if let Some(palette) = self.file_palette.as_mut() {
30 if let Some((_start, _end, query)) =
31 extract_file_reference(self.input_manager.content(), self.input_manager.cursor())
32 {
33 palette.set_filter(query);
34 if !self.file_palette_active {
35 self.file_palette_active = true;
36 self.needs_full_clear = true;
37 self.mark_dirty();
38 }
39 } else if self.file_palette_active {
40 self.close_file_palette();
41 }
42 }
43 }
44
45 pub(super) fn close_file_palette(&mut self) {
47 self.file_palette_active = false;
48 self.needs_full_clear = true;
49
50 if let Some(palette) = self.file_palette.as_mut() {
52 palette.set_filter(String::new());
53 }
54 }
55
56 pub(super) fn handle_file_palette_key(&mut self, key: &KeyEvent) -> bool {
60 if !self.file_palette_active {
61 return false;
62 }
63
64 let Some(palette) = self.file_palette.as_mut() else {
65 return false;
66 };
67
68 match key.code {
69 KeyCode::Up => {
70 palette.move_selection_up();
71 self.mark_dirty();
72 true
73 }
74 KeyCode::Down => {
75 palette.move_selection_down();
76 self.mark_dirty();
77 true
78 }
79 KeyCode::Tab => {
80 palette.select_best_match();
81 self.mark_dirty();
82 true
83 }
84 KeyCode::Enter => {
85 let selected_path = palette.get_selected().map(|e| e.relative_path.clone());
86 if let Some(path) = selected_path {
87 self.insert_file_reference(&path);
88 self.close_file_palette();
89 self.mark_dirty();
90 true } else {
92 self.close_file_palette();
94 self.mark_dirty();
95 false }
97 }
98 KeyCode::Esc => {
99 self.close_file_palette();
100 self.mark_dirty();
101 true
102 }
103 KeyCode::Char('n') if key.modifiers.contains(KeyModifiers::CONTROL) => {
104 palette.move_selection_down();
105 self.mark_dirty();
106 true
107 }
108 KeyCode::Char('p') if key.modifiers.contains(KeyModifiers::CONTROL) => {
109 palette.move_selection_up();
110 self.mark_dirty();
111 true
112 }
113 _ => false,
114 }
115 }
116
117 pub(super) fn insert_file_reference(&mut self, file_path: &str) {
119 if let Some((start, end, _)) =
120 extract_file_reference(self.input_manager.content(), self.input_manager.cursor())
121 {
122 let before = &self.input_manager.content()[..start];
123 let after = &self.input_manager.content()[end..];
124 let reference_alias = format!("@{}", file_path);
125 let new_content = format!("{}{} {}", before, reference_alias, after);
126 let new_cursor = start + reference_alias.len() + 1;
127
128 self.input_manager.set_content(new_content);
129 self.input_manager.set_cursor(new_cursor);
130 slash::update_slash_suggestions(self);
131 }
132 }
133}