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 }
37 } else if self.file_palette_active {
38 self.close_file_palette();
39 }
40 }
41 }
42
43 pub(super) fn close_file_palette(&mut self) {
45 self.file_palette_active = false;
46
47 if let Some(palette) = self.file_palette.as_mut() {
49 palette.set_filter(String::new());
50 }
51 }
52
53 pub(super) fn handle_file_palette_key(&mut self, key: &KeyEvent) -> bool {
57 if !self.file_palette_active {
58 return false;
59 }
60
61 let Some(palette) = self.file_palette.as_mut() else {
62 return false;
63 };
64
65 match key.code {
66 KeyCode::Up => {
67 palette.move_selection_up();
68 self.mark_dirty();
69 true
70 }
71 KeyCode::Down => {
72 palette.move_selection_down();
73 self.mark_dirty();
74 true
75 }
76 KeyCode::Tab => {
77 palette.select_best_match();
78 self.mark_dirty();
79 true
80 }
81 KeyCode::Enter => {
82 let selected_path = palette.get_selected().map(|e| e.relative_path.clone());
83 if let Some(path) = selected_path {
84 self.insert_file_reference(&path);
85 self.close_file_palette();
86 self.mark_dirty();
87 }
88 true
89 }
90 KeyCode::Esc => {
91 self.close_file_palette();
92 self.mark_dirty();
93 true
94 }
95 KeyCode::Char('n') if key.modifiers.contains(KeyModifiers::CONTROL) => {
96 palette.move_selection_down();
97 self.mark_dirty();
98 true
99 }
100 KeyCode::Char('p') if key.modifiers.contains(KeyModifiers::CONTROL) => {
101 palette.move_selection_up();
102 self.mark_dirty();
103 true
104 }
105 _ => false,
106 }
107 }
108
109 pub(super) fn insert_file_reference(&mut self, file_path: &str) {
111 if let Some((start, end, _)) =
112 extract_file_reference(self.input_manager.content(), self.input_manager.cursor())
113 {
114 let before = &self.input_manager.content()[..start];
115 let after = &self.input_manager.content()[end..];
116 let reference_alias = format!("@{}", file_path);
117 let new_content = format!("{}{} {}", before, reference_alias, after);
118 let new_cursor = start + reference_alias.len() + 1;
119
120 self.input_manager.set_content(new_content);
121 self.input_manager.set_cursor(new_cursor);
122 slash::update_slash_suggestions(self);
123 }
124 }
125}